the brand sheet.

ugc.name is a portfolio for the people brands pay to make ads, built in about five minutes. this page is the whole system it is drawn and written in — rendered from the same components and the same constants the product ships, so it cannot quietly go out of date.

icon

the same mark, wired up.

src/app/icon.svg and src/app/apple-icon.png are Next's app-directory conventions: nothing imports them, and the framework emits the icon and apple-touch-icon link tags on every page for us. Both are drawn from the geometry in @/lib/brand/mark-geometry, and the PNG is regenerated by scripts/generate-brand-icons.mjs.

16px32px64px128px
The favicon at the sizes a browser actually asks for. The counter stays open at 16px, which is the whole reason the @ is geometry and not a glyph.
The ugc.name home-screen icon: a cream @ on a cobalt square.
apple-icon.png, 180×180. Full-bleed cobalt with no chip and no keyline: iOS masks the corners itself and paints the icon on a wallpaper nobody controls.
ugc.name — the portfolio brands as…
On a dark browser chrome the keyline disappears into the background and the cobalt chip carries the shape on its own — which is why the chip is a fill and not an outline.

colour

six colours, committed to whole surfaces.

Colour is never a highlight here. A band is cobalt or it is cream; nothing is “cobalt with a cream accent”. Every hex below is the live token value, and every ratio underneath is computed from it at render time by contrastRatio() — so this table cannot be wrong about the palette it is printed next to.

cobalt

#4A56E0 · var(--cobalt)

The primary surface. Committed to whole panels — a cobalt band, a cobalt card — never used as a highlight or an accent on something else.

cobalt deep

#3D48C9 · var(--cobalt-deep)

The second cobalt, for a band that has to sit next to the first one without the two reading as a single block. Also the only cobalt that carries lilac text.

cream

#F0EBE3 · var(--cream)

The page. Warm rather than grey, which is what lets the neutral chrome tokens sit on it without going green.

lilac

#E9D2F2 · var(--lilac)

The third surface, for one band per page at most. Carries ink type only.

ink

#14121A · var(--ink)

Every word, every keyline, every sticker outline. Near-black rather than black, so it reads as drawn rather than printed.

flare

#FF5C2B · var(--flare)

Spent exactly once per page, on the moment that matters: the Claim button the instant a handle turns out to be free. A second flare object makes the first one ordinary.

Safe text pairs — 4.5:1 and above

WCAG 2.2 AA for normal-size text, with no large-text discount taken. A headline that is large on a phone is normal size on a laptop.

  • ink on cream15.65:1
  • ink on lilac13.23:1
  • ink on flare6.03:1
  • cream on cobalt4.78:1
  • cream on cobalt deep5.96:1
  • cream on ink15.65:1
  • lilac on ink13.23:1
  • lilac on cobalt deep5.04:1
  • cobalt on cream4.78:1
  • cobalt deep on cream5.96:1

Banned pairs

These are the combinations the palette invites and the maths refuses. Shown on a safe ground rather than set in themselves, because the point is that you cannot read them.

  • lilac on cobalt4.05:1 — fails AA
  • ink on cobalt3.27:1 — fails AA
  • cream on flare2.60:1 — fails AA

type

two families, and one of them is rationed.

Shantell Sans is a marker-drawn variable face that matches the sticker linework. It is the wordmark and the landing hero, and nothing else — not the app chrome, not body copy, not a section heading in the editor. Archivo is everything else. Loading them as CSS variables rather than classNames is what keeps that rule enforceable: a component has to ask for font-[family-name:var(--font-brand)] by name.

var(--font-brand) · Shantell Sans · 700

the ugc portfolio

abcdefghijklmnopqrstuvwxyz 0123456789 @.

Brand moments only: the wordmark, the landing hero, the FAQ’s banner heading. Always lowercase. Tracking −0.02em.

var(--font-ui) · Archivo · 400 / 500 / 600

views, watch time and saves, on the video they belong to.

Every heading, every label, every button, every paragraph. Headings tight at −0.03em; body copy at normal tracking and 1.5 line height, capped at about 60 characters.

abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789

A published portfolio is the one place neither of these rules applies: each of the eight themes names its own heading and body stack, and the creator’s page is set in theirs, not in ours.

stickers

twelve die-cut drawings, never in a grid.

Thick black stroke, white fill, a white die-cut halo around the whole shape, rotated a few degrees. They are printed vinyl, not icons: they overlap the thing they sit on, they are never centred, never evenly spaced, and never set inside a circle. Every one is aria-hidden — they carry no meaning the copy does not already carry. Shown here on a grid, which is the one place a grid is allowed, because this is the sheet rather than a composition.

  • clapper
  • pencil
  • f9
  • camcorder
  • hourglass
  • headphones
  • smiley
  • peace
  • cursor
  • mug
  • pizza
  • skull

Drawn on a 100×100 viewBox inside roughly 10–90, because the die-cut pass is a 20-wide stroke and anything closer to an edge has its halo clipped. A creator can pin up to twelve of them on their own header; the ids above are the contract between the editor and the renderer.

seo & og

what a link preview says about us.

Every string below is imported from @/lib/brand/seo, which is the same module the <head> reads — so this is the live copy, not a transcription of it. The card underneath is an HTML replica of the real 1200×630 PNG that src/app/opengraph-image.tsx renders.

<title>
ugc.name — your UGC portfolio, in 5 minutes
meta description · 200 characters
Build the portfolio page brands ask UGC creators for, in about five minutes. Your best brand videos, what each one did, and one link to send instead of a media kit. $10/month after a 7-day free trial.
og:image:alt
ugc.name — your UGC portfolio, in 5 minutes. The page brands ask UGC creators for: your best videos, what each one did, and one link to send instead of a media kit.
taglines, short to long
your ugc portfolio, in 5 minutes.the page brands ask ugc creators for.you make the ads. this is where you keep them.send one link instead of a media kit.

/opengraph-image · 1200×630

ugc.name

your ugc portfolio, in 5 minutes.

the page brands ask ugc creators for: your best videos, what each one did, and one link to send instead of a media kit.

ugc.name/@you$10/month · 7 days free

The generated card is set in the renderer’s own sans rather than Shantell Sans. Loading the brand face into ImageResponse means fetching a font from Google during next build, and a build that can fail because a font CDN is having a bad morning is not a trade worth making for a preview image. The card carries the brand in its colour, its mark and its voice instead.

/brand is indexable. It is a public, static, unauthenticated page that says what the product is and who it is for, it holds no customer data, and it is exactly the kind of page that should be findable. It is named in the allow list in src/app/robots.ts rather than left to the blanket allow: “/”, so that the decision is visible.

voice

plain first, dry second, and specific about money.

The rewrite this page documents started with a single note from the client: the headings were clever and nobody could tell what the product did. So rule one is now “say what the thing does”, and every “not” below is a line the product genuinely shipped or could plausibly have shipped. Every “so” is a real string from the live surfaces, quoted rather than written for this page.

  • Say what the thing does. Wry is a tone, not a substitute for the message.

    The headings used to make the reader decode before they could understand — “the three videos that book you. not everything you have posted.” reads as a riddle at the four seconds a visitor actually gives it. Informative beats clever every time.

    notthe three videos that book you. not everything you have posted.

    soput your three best brand videos at the top of the page.

  • Lowercase on the marketing surfaces, sentence case in the app.

    The landing page is a voice; the editor is a tool. A form label in lowercase reads as a style choice at exactly the moment somebody is trying to fill it in.

    notClaim Your Handle Today!

    soyour ugc portfolio, in 5 minutes.

  • Say UGC creator. Never just creator, never influencer, never user.

    The audience is the person a brand pays to make the ad. “Creator” also means a newsletter writer and a streamer, and every sentence that blurs that makes the product sound like a link-in-bio.

    notThe link in bio for creators.

    soyou make ads for brands. this is the page you send them when they ask what you have made.

  • Lead with the outcome, then the price, then the mechanics.

    A creator decides whether this is worth ten dollars in the first screen. Making them scroll three bands to find out what it costs is how a page loses the people who were already sold.

    nota rate is easier to hold when the work is already on the table.

    so$10 a month. the first 7 days are free.

  • Name the thing it replaces.

    Nobody wakes up wanting a portfolio. They wake up having to rebuild a media kit because a brand asked for one.

    notShowcase your content beautifully.

    sono media kit, no pdf, no drive folder.

  • Label a projection as a projection. Never dress one up as a measurement.

    The landing page runs one outcome claim while the product is new and nobody has a first month on it yet. Running it is a commercial decision; presenting it as a measured result would be a factual claim an agency could check and find false. So the page says which kind of number it is, and `SocialProofStat.status` is what forces the question in code.

    not2× — creators earned double in their first month. Source: internal study, 2026.

    sothat is what we are building for, not a figure anyone has measured — ugc.name is new and no creator has finished a first month on it yet.

  • Dry, never zany. One joke per page, at most.

    The drawings carry the personality. If the copy is also doing bits, the page reads as trying.

    notYour portfolio just entered its main character era ✨

    sosix made-up ugc creators, six of the looks you can pick from. drag the row, or use the arrows.

  • Short words. No throat-clearing, no seamlessly, no empower, no elevate.

    The reader is halfway through a reply to a brand. Every clause they have to parse is a clause that is not about them.

    notSeamlessly elevate your creator brand with a unified presence.

    soone link to send a brand: ugc.name/@you.

  • Be specific about money and about rules.

    Vagueness about price reads as a trap, and a creator who finds out the terms later is a creator who leaves.

    notAffordable plans for every creator.

    sofree for the first 7 days, then $10 a month. the trial starts when you publish, not when you sign up.

  • Every button on the home page says the same thing, and it says the price.

    Six CTAs with six wordings makes a page feel assembled by six people. “get started” also hides the one fact standing between the reader and the click, so the button answers it.

    notget started / try it now / claim yours / sign up free

    soget started for free

  • A footnote has to have something to point at.

    An asterisk with no antecedent is the one typographic tic that makes a careful page look careless. The client found ours before we did.

    not*terms apply.

    sothe address is yours*. / *claim it and then use it — a handle that sits unpublished for 30 days goes back in the pool.