OG Images for Portfolio Sites: Stand Out When Your Work Gets Shared
How to design and implement OG images for developer and designer portfolios — unique project previews, case study cards, and social-ready work samples.
Why portfolio OG images matter
When a recruiter, client, or collaborator shares your portfolio link in a Slack channel, Discord server, or LinkedIn message — what do they see? If your OG image is missing, broken, or a generic screenshot, you're losing the first impression before anyone even clicks.
A well-designed portfolio OG image is essentially a mini cover letter: it should communicate your role, style, and caliber of work in one glance at 1200×630 pixels.
OG image strategy by page type
Homepage / root URL
Your homepage OG image is the most shared. It should include your name, title (e.g., "Frontend Engineer" or "Product Designer"), and a visual that represents your work quality. Keep it minimal and professional.
Individual project / case study pages
Each project page should have a unique OG image. Use a screenshot or mockup of the project with the project name overlaid. This way, when someone shares a specific project, the preview immediately shows what it is.
Writing / blog section
For portfolio blogs or writing samples, generate OG images dynamically from the post title — branded with your name and domain.
Static OG image implementation (Next.js)
// app/layout.tsx (site-wide default)
import type { Metadata } from "next";
export const metadata: Metadata = {
metadataBase: new URL("https://yourname.dev"),
title: {
default: "Jane Smith — Frontend Engineer",
template: "%s | Jane Smith",
},
description: "I build accessible, high-performance React applications.",
openGraph: {
type: "website",
siteName: "Jane Smith Portfolio",
images: [
{
url: "/og/homepage.png", // static 1200×630 image
width: 1200,
height: 630,
alt: "Jane Smith — Frontend Engineer",
},
],
},
twitter: {
card: "summary_large_image",
creator: "@janesmith",
},
};Dynamic project OG images (Next.js edge)
For project pages, generate OG images on-the-fly so each project has a unique preview:
// app/work/[slug]/opengraph-image.tsx
import { ImageResponse } from "next/og";
import { getProject } from "@/lib/projects";
export const size = { width: 1200, height: 630 };
export const contentType = "image/png";
export default async function OgImage({
params,
}: {
params: { slug: string };
}) {
const project = getProject(params.slug);
return new ImageResponse(
(
<div
style={{
display: "flex",
background: "#0a0a0a",
width: "100%",
height: "100%",
position: "relative",
overflow: "hidden",
}}
>
{/* Project screenshot on right */}
{project.screenshot && (
<img
src={project.screenshot}
style={{
position: "absolute",
right: -40,
top: -20,
width: "60%",
height: "120%",
objectFit: "cover",
opacity: 0.3,
transform: "rotate(3deg)",
}}
alt=""
/>
)}
{/* Content on left */}
<div
style={{
display: "flex",
flexDirection: "column",
justifyContent: "center",
padding: "60px",
zIndex: 1,
maxWidth: "60%",
}}
>
{/* Category tag */}
<div
style={{
fontSize: 18,
color: "#8b5cf6",
fontWeight: 600,
marginBottom: 16,
textTransform: "uppercase",
letterSpacing: "0.1em",
}}
>
{project.category}
</div>
{/* Project name */}
<div
style={{
fontSize: 56,
fontWeight: 900,
color: "#ffffff",
lineHeight: 1.1,
}}
>
{project.title}
</div>
{/* Short description */}
<div
style={{
fontSize: 22,
color: "#a1a1aa",
marginTop: 20,
lineHeight: 1.4,
}}
>
{project.description}
</div>
{/* Name attribution */}
<div
style={{
fontSize: 18,
color: "#52525b",
marginTop: 32,
}}
>
yourname.dev
</div>
</div>
</div>
),
size
);
}Portfolio OG design principles
- Show your work visually: Include a screenshot or mockup — portfolios are visual by nature
- Name + title always visible: Recruiters share links in notes/emails — make sure they always know whose work this is
- Consistent color system: Use your portfolio's primary color so previews look branded, not generic
- Dark background works well: Dark OG images stand out in social feeds dominated by white backgrounds
- Font hierarchy: Large project title, smaller description, smallest attribution — maintain visual hierarchy even at thumbnail size
- No tiny text: If it can't be read at 300px wide, cut it
Static vs dynamic: which approach to use
| Approach | Best for | Trade-off |
|---|---|---|
| Static PNG files | Small portfolios (<10 projects) | Manual effort per page |
| opengraph-image.tsx per route | Next.js apps with many projects | Requires edge runtime |
| /api/og?title=... route | Blog posts and text-heavy pages | Less control per page |
| Figma export per project | Unique branded project cards | Most time-consuming |
Check your portfolio's social previews
Paste your portfolio URL into OGFixer to see exactly how it looks when shared on Twitter, LinkedIn, Discord, and Slack — before a recruiter does.
Check your portfolio OG free →