Skip to content

feat(web): implement public profile page with Open Graph meta tags for /u/:username#345

Open
samarthsugandhi wants to merge 2 commits into
Dev-Card:mainfrom
samarthsugandhi:feat/public-profile-preview-page
Open

feat(web): implement public profile page with Open Graph meta tags for /u/:username#345
samarthsugandhi wants to merge 2 commits into
Dev-Card:mainfrom
samarthsugandhi:feat/public-profile-preview-page

Conversation

@samarthsugandhi
Copy link
Copy Markdown

Summary

Implements the public-facing profile page at /u/:username that renders a user's DevCard with all platform links, and injects dynamic Open Graph meta tags so the URL generates a rich link preview when shared on Twitter/X, LinkedIn, WhatsApp, or Telegram.

Closes #239


Changes Made

apps/web/src/routes/u/[username]/+page.svelte (modified)

  • Replaced the placeholder page with a fully rendered profile card
  • Reads data.profile and data.error from the existing +page.server.ts load function (no changes needed there)
  • Renders avatar, display name, username, bio, and platform links as styled tappable buttons
  • Each platform link button is coloured with the platform's brand colour
  • Handles the error/404 state gracefully with a user-friendly message

apps/web/src/routes/u/[username]/+page.svelte — Open Graph tags added

  • og:title — user's display name or username
  • og:description — user's bio, or a generated fallback
  • og:image — user's avatar URL, or the site default OG image
  • og:url — canonical URL for the profile
  • twitter:card — set to summary for Twitter/X previews
  • <link rel="canonical"> — added for SEO

packages/shared/src/types.ts (modified)

  • Added PublicProfile and PublicCardLink interfaces matching the shape returned by the backend

How to Test

  1. Run pnpm dev from the repo root
  2. Visit http://localhost:5173/u/<any-seeded-username>
  3. You should see the profile card rendered with platform links
  4. Visit http://localhost:5173/u/nonexistent — you should see the "Profile not found" error page
  5. Open browser DevTools → View Page Source → confirm <meta property="og:title"> and other OG tags are present in the <head>
  6. Paste the URL into https://opengraph.xyz to verify the rich preview renders correctly

Checklist

  • Profile card renders correctly for existing users
  • 404 / error state is handled gracefully
  • Open Graph meta tags present in page source
  • Platform links open in a new tab with rel="noopener noreferrer"
  • Page is mobile-responsive
  • No private user data (email, tokens) exposed
  • pnpm lint passes with no errors
  • Existing +page.server.ts left unchanged

Copilot AI review requested due to automatic review settings May 26, 2026 11:53
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds a public, unauthenticated “shareable profile” surface by introducing a backend endpoint, shared response types, and a simplified web profile page with Open Graph/SEO meta tags.

Changes:

  • Added shared PublicCardResponse / PublicCardLink types for the public card API.
  • Added backend route GET /public/cards/:username to serve safe, public profile data.
  • Updated /u/[username] page to render from the public API shape and emit OG/Twitter/canonical meta tags.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 10 comments.

File Description
packages/shared/src/types.ts Introduces shared TS interfaces for the public card API response.
apps/web/src/routes/u/[username]/+page.svelte Reworks the public profile page UI and adds OG/Twitter/canonical meta tags.
apps/backend/src/routes/publicCards.ts Adds an unauthenticated public endpoint to fetch a user’s default card links.
apps/backend/src/app.ts Registers the new publicCardRoutes route module.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

const error = data.error;
export let data: PageData;

const card: PublicCardResponse = data.card;
{:else}
<title>User Not Found | DevCard</title>
{/if}
<title>{card.displayName ?? card.username} | DevCard</title>
<main class="profile-page">
<div class="card">
<!-- Avatar -->
{#if card.avatarUrl}
{/if}

<!-- Name + username -->
<h1 class="display-name">{card.displayName ?? card.username}</h1>
{/if}

<!-- Platform links -->
{#if card.links.length > 0}
}

// Build the page URL for the canonical + og:url tag
const pageUrl = `https://dev-card-web.vercel.app/u/${card.username}`;
<meta property="og:url" content={pageUrl} />
<meta
property="og:image"
content={card.avatarUrl ?? "https://dev-card-web.vercel.app/og-image.jpg"}
<meta name="twitter:description" content={ogDescription} />
<meta
name="twitter:image"
content={card.avatarUrl ?? "https://dev-card-web.vercel.app/og-image.jpg"}
/>

<!-- Canonical URL -->
<link rel="canonical" href={pageUrl} />
Comment on lines +27 to +55
schema: {
params: {
type: "object",
required: ["username"],
properties: {
username: { type: "string" },
},
},
response: {
200: {
type: "object",
properties: {
username: { type: "string" },
displayName: { type: ["string", "null"] },
bio: { type: ["string", "null"] },
avatarUrl: { type: ["string", "null"] },
links: {
type: "array",
items: {
type: "object",
properties: {
platform: { type: "string" },
url: { type: "string" },
label: { type: ["string", "null"] },
},
},
},
},
},
@samarthsugandhi
Copy link
Copy Markdown
Author

@ShantKhatri Hi! Could you please review this PR when you get a chance?
It implements the public profile page at /u/:username with Open Graph meta tags
as described in issue #239. All checklist items are complete. Thank you!

@Harxhit Harxhit added gssoc:approved Required label for every approved PR. Gives the base +50 points and enables contribution tracking. gssoc-26 Issues and contributions accepted under GSSoC'26. and removed gssoc-26 Issues and contributions accepted under GSSoC'26. labels May 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gssoc:approved Required label for every approved PR. Gives the base +50 points and enables contribution tracking.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

web + backend: add public shareable profile URL with Open Graph meta tags

3 participants