linkedin-post: LinkedIn post image
Goal: produce the PNG asset of a LinkedIn post image, at the chosen ratio,
aligned with the guidelines.
This is a specialization of new-template with the LinkedIn constraints
hard-coded. Same conventions: the Template contract (from brand-artisan),
assets through brand(), fonts discovered in fonts/,
export default ... satisfies Template.
Status of the dimensions. LinkedIn only officially documents one visual, at
1200×627 (1.91:1), for the link preview on Pages. For an image posted
directly, LinkedIn publishes no dimensions: the 1080×1080 square and the
1080×1350 portrait are conventions (carried over from the advertising
specs), not from the organic documentation.
0. Prerequisites (blocking)
The chain project -> template folder -> guidelines must exist:
- Resolve
<project> (from the arguments, otherwise ask).
- Check
templates/<project>/ and brands/<project>/brand.md.
- Missing guidelines or project -> STOP: ask for
/new-project <project>
first. No visual without guidelines (CLAUDE.md rule).
1. Frame it
- Which orientation? Ask. Default: portrait (4:5, takes the most height
in the feed). Otherwise square (1:1) or landscape (1.91:1).
- Default slug
linkedin-post (or linkedin-post-<orientation> if there are
several). Check that the target .tsx does not exist.
- Read
brands/<project>/brand.md: palette, type, logo variants, don'ts.
- Read
brands/<project>/project.md if it exists: set the tone and the
claims (don't invent figures or promises). If absent -> ask for the tone and
the message rather than guessing.
- Ask for the message: short headline + standfirst (1 sentence). No paragraph.
- If the project already holds a
.tsx, read it as a style reference.
2. LinkedIn constraints (to respect)
| Orientation |
Size (px) |
Ratio |
Status |
| Portrait (default) |
1080x1350 |
4:5 |
Convention (ads specs) |
| Square |
1080x1080 |
1:1 |
Convention (ads specs) |
| Landscape |
1200x627 |
1.91:1 |
Official LinkedIn (link preview) |
- Format: PNG or JPG, opaque background.
- The post's text (body, link) lives outside the image, in the
publication: don't write everything into the visual. One idea per card.
- Legible when small: the LinkedIn feed displays narrow on mobile. Large
headline, short standfirst, strong contrast, safe area of about 80 px.
- LinkedIn tone: a professional audience. Favor a standfirst carrying added
value (an insight, a data point, a business benefit) over an aggressive pitch.
3. Write the template
templates/<project>/<slug>.tsx, with colors as constants taken from the
guidelines. Pick SIZE according to the orientation. Skeleton:
import type { ReactNode } from "react";
import { brand, type Template } from "brand-artisan";
// import { readFile } from "node:fs/promises"; // if you load the mark
// Pick according to the orientation:
const SIZE = { width: 1080, height: 1350 }; // Portrait 4:5 (default)
// const SIZE = { width: 1080, height: 1080 }; // Square 1:1
// const SIZE = { width: 1200, height: 627 }; // Landscape 1.91:1
// <Project> guideline palette (from brands/<project>/brand.md).
const INK = "#......";
function render(): ReactNode {
return (
<div
style={{
width: "100%",
height: "100%",
display: "flex",
flexDirection: "column",
justifyContent: "center",
padding: 80, // safe area
backgroundColor: INK, // opaque background
}}
>
{/* logo + large headline + short standfirst, strong contrast */}
</div>
);
}
export default { size: SIZE, title: "<Project> LinkedIn post", render } satisfies Template;
Shared conventions: assets through brand("<project>/..."), fonts discovered in
fonts/; a missing font -> the "missing font" appendix in new-template, never
silently. Keep the code minimal.
4. Verify
npm run typecheck -> green.
npm run build -> writes out/<project>/<slug>.png.
- Check the PNG: exact dimensions for the orientation, opaque background,
correct ratio (4:5 / 1:1 / 1.91:1).
- Preview:
npm run dev then /<project>/<slug>; check legibility shrunk to the
width of a mobile feed.
Success criterion: a PNG at the dimensions of the chosen orientation, opaque,
legible when small, professional in tone, and using only colors and type from
brand.md.
1---2name: linkedin-post3description: Creates a LinkedIn post image at LinkedIn's dimensions, in the chosen orientation. Use when the user wants a "LinkedIn image", a "LinkedIn post", a "LinkedIn visual" or a "LinkedIn publication" for a project. Asks for the orientation (portrait by default, square, landscape) and produces a .tsx template at the right ratio, aligned with the brand guidelines, rendered as a PNG through the project's engine. Requires a project with its brand.md in place.4---56# linkedin-post: LinkedIn post image78Goal: produce the **PNG asset** of a LinkedIn post image, at the chosen **ratio**,9aligned with the guidelines.1011This is a specialization of `new-template` with the LinkedIn constraints12hard-coded. Same conventions: the `Template` contract (from `brand-artisan`),13assets through `brand()`, fonts discovered in `fonts/`,14`export default ... satisfies Template`.1516> **Status of the dimensions.** LinkedIn only officially documents one visual, at17> **1200×627 (1.91:1)**, for the **link** preview on Pages. For an image posted18> directly, LinkedIn publishes **no** dimensions: the **1080×1080 square** and the19> **1080×1350 portrait** are **conventions** (carried over from the advertising20> specs), not from the organic documentation.2122## 0. Prerequisites (blocking)2324The chain **project -> template folder -> guidelines** must exist:2526- Resolve `<project>` (from the arguments, otherwise ask).27- Check `templates/<project>/` **and** `brands/<project>/brand.md`.28- Missing guidelines or project -> **STOP**: ask for `/new-project <project>`29 first. No visual without guidelines (CLAUDE.md rule).3031## 1. Frame it3233- **Which orientation?** Ask. **Default: portrait** (4:5, takes the most height34 in the feed). Otherwise square (1:1) or landscape (1.91:1).35- Default slug `linkedin-post` (or `linkedin-post-<orientation>` if there are36 several). Check that the target `.tsx` does not exist.37- Read `brands/<project>/brand.md`: palette, type, logo variants, **don'ts**.38- Read `brands/<project>/project.md` if it exists: set the **tone** and the39 **claims** (don't invent figures or promises). If absent -> ask for the tone and40 the message rather than guessing.41- Ask for the **message**: short headline + standfirst (1 sentence). No paragraph.42- If the project already holds a `.tsx`, read it as a style reference.4344## 2. LinkedIn constraints (to respect)4546| Orientation | Size (px) | Ratio | Status |47|---|---|---|---|48| **Portrait** (default) | **1080x1350** | 4:5 | Convention (ads specs) |49| **Square** | **1080x1080** | 1:1 | Convention (ads specs) |50| **Landscape** | **1200x627** | 1.91:1 | Official LinkedIn (link preview) |5152- **Format**: PNG or JPG, **opaque** background.53- **The post's text** (body, link) lives **outside the image**, in the54 publication: don't write everything into the visual. **One idea per card.**55- **Legible when small**: the LinkedIn feed displays narrow on mobile. Large56 headline, short standfirst, strong contrast, **safe area of about 80 px**.57- **LinkedIn tone**: a professional audience. Favor a standfirst carrying added58 value (an insight, a data point, a business benefit) over an aggressive pitch.5960## 3. Write the template6162`templates/<project>/<slug>.tsx`, with colors as constants taken from the63guidelines. Pick `SIZE` according to the orientation. Skeleton:6465```tsx66import type { ReactNode } from "react";67import { brand, type Template } from "brand-artisan";68// import { readFile } from "node:fs/promises"; // if you load the mark6970// Pick according to the orientation:71const SIZE = { width: 1080, height: 1350 }; // Portrait 4:5 (default)72// const SIZE = { width: 1080, height: 1080 }; // Square 1:173// const SIZE = { width: 1200, height: 627 }; // Landscape 1.91:17475// <Project> guideline palette (from brands/<project>/brand.md).76const INK = "#......";7778function render(): ReactNode {79 return (80 <div81 style={{82 width: "100%",83 height: "100%",84 display: "flex",85 flexDirection: "column",86 justifyContent: "center",87 padding: 80, // safe area88 backgroundColor: INK, // opaque background89 }}90 >91 {/* logo + large headline + short standfirst, strong contrast */}92 </div>93 );94}9596export default { size: SIZE, title: "<Project> LinkedIn post", render } satisfies Template;97```9899Shared conventions: assets through `brand("<project>/...")`, fonts discovered in100`fonts/`; a missing font -> the "missing font" appendix in `new-template`, never101silently. Keep the code minimal.102103## 4. Verify104105- `npm run typecheck` -> green.106- `npm run build` -> writes `out/<project>/<slug>.png`.107- Check the PNG: **exact dimensions** for the orientation, opaque background,108 correct ratio (4:5 / 1:1 / 1.91:1).109- Preview: `npm run dev` then `/<project>/<slug>`; check legibility shrunk to the110 width of a mobile feed.111112**Success criterion**: a PNG at the dimensions of the chosen orientation, opaque,113legible when small, professional in tone, and using only colors and type from114`brand.md`.