Brand
PublishPage sells one moment: you ask, and a page is up. Everything here exists to keep that moment legible — a globe for the open web, a plain white ground, and exactly one blue that belongs to actions.
This page is a live specimen: every swatch and sample below is rendered by the stylesheet that renders the product, so it cannot drift from what ships.
The mark
A globe cut into six segments along one equator and two meridians. It is the web — the thing a page lands on — and the cut says the globe is made of pages rather than drawn as one solid object. The two segments that pull away from the centre on the right give the mark its lean, which is the only motion in an otherwise still shape.
It is a filled mark with no strokes, so it survives being small. The gaps between segments carry the drawing: they are set at 6.25% of the mark's width, which holds a visible hairline all the way down to 16px. Never thin them to fit a tighter space — shrink the mark instead, or use a size where it works.
Blue on white
The default. Use it everywhere the ground is white or slate-50.
White on blue
For the blue card, the app icon, and any saturated ground.
Slate on white
One-colour printing, embossing, and partner walls that ban colour.
Lockup
The mark sits left of the wordmark, vertically centred, with a gap of roughly one third the mark's height. The wordmark is Figtree 700 at −0.025em in slate-900, set as one word with a capital P and a capital P: PublishPage. There is no tile behind the mark — the globe is its own silhouette, and a rounded square around a round mark is a container the design does not need. The tile exists only as an app icon, where the platform demands a square.
Primary lockup
28px mark, 18px wordmark, 10px gap. This is the header of every app-host surface.
Reversed lockup
Both parts go white. Never keep a blue mark against a blue ground.
The mark alone
Drop the wordmark where the context already names the product — favicons, app icons, avatars, the footer, the badge on a published page.
Clear space and minimum size
Keep clear space equal to half the mark's height on all four sides of the whole lockup. Nothing enters it: no rules, no other logos, no copy, no edge of a photograph.
Clear space
Half the mark's height on every side — 14px around a 28px mark. The dashed line is the boundary, not part of the artwork.
Minimum size
The mark alone never goes below 16px; the lockup never below a 24px mark, because the wordmark stops being readable first.
Misuse
Six things that break the mark. Each specimen below is wrong on purpose.
Don't box it
The tile is for app icons only, where the platform forces a square. On a page, the globe stands alone.
Don't recolour it
Blue-600, white, or slate-900. There is no second hue in this system, and signal colours mean something else.
Don't distort it
Scale both axes together. A stretched globe stops being a globe.
Don't decorate it
No shadow, no outline, no gradient, no glow. The mark is flat everywhere it appears.
Don't bury it
On a mid-tone or busy ground, switch to the white mark rather than fighting for contrast.
Don't reletter it
One word, capital P and capital P, Figtree 700. Not "Publish Page", not lowercase, not a lighter weight.
Downloads
Every file is generated from one path on a 40 × 40 grid, so no two assets can disagree about the drawing. Prefer the SVG anywhere a vector will render.
| Asset | Files |
|---|---|
|
The mark The globe alone, on a transparent ground. The currentColor file is the one to embed in code — it inherits whatever colour surrounds it. |
currentColor SVG Blue SVG Slate SVG White SVG |
|
The mark, raster Transparent PNGs for slide decks, avatars, READMEs, and anywhere a vector will not go. |
Blue 128 Blue 256 Blue 512 Blue 1024 White 256 White 512 |
|
App icon The white mark on a blue-600 squircle, glyph at 60% of the tile. Opaque by design: phone home screens composite it onto their own ground. |
SVG PNG 192 PNG 512 Maskable 512 |
|
Favicons favicon.svg carries both themes in one file and follows the browser chrome. The light and dark files are the same artwork split apart, for anywhere that needs them separately. |
Adaptive SVG Light SVG Dark SVG ICO Apple touch icon |
Favicons, in practice
favicon.svg holds both themes in one
file: an embedded prefers-color-scheme
rule paints the globe blue-600 against light browser chrome and blue-400 against dark, transparent
either way. The .ico carries 16, 32
and 48px rasters for clients that ignore SVG icons. The Apple touch icon is the only opaque file,
because iOS flattens transparency to black.
<link rel="icon" href="/favicon.ico" sizes="32x32">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<link rel="manifest" href="/site.webmanifest">
Colour
A near-monochrome slate system on white, interrupted by exactly one saturated hue for action and three narrow-purpose signal colours that never decorate. Values are authored in oklch; the hex is the sRGB rendering of the same colour.
Action
One saturated hue in the whole system. It means act on this: primary buttons, the brand mark, the single blue card. Its darker siblings are states, not new colours.
Blue 600
#155DFC
oklch(54.6% 0.245 262.881)
Primary fill, the mark, focus rings
Blue 700
#1447E6
oklch(48.8% 0.243 264.376)
Hover, destination links
Blue 800
#193CB8
oklch(42.4% 0.199 265.638)
Press
Blue 300
#8EC5FF
oklch(80.9% 0.105 251.813)
Link underline decoration
Blue 100
#DBEAFE
oklch(93.2% 0.032 255.585)
Press, on the blue card
Blue 50
#EFF6FF
oklch(97% 0.014 254.604)
Body copy on the blue card
Ground and ink
A four-step ink ramp on white. Text darkness encodes rank, and structure is built from hairlines and recession rather than weight.
White
#FFFFFF
oklch(100% 0 0)
The universal ground
Slate 50
#F8FAFC
oklch(98.4% 0.003 247.858)
The one alternate surface
Slate 100
#F1F5F9
oklch(96.8% 0.007 247.896)
Hairlines and dividers
Slate 200
#E2E8F0
oklch(92.9% 0.013 255.508)
Every structural border
Slate 300
#CAD5E2
oklch(86.9% 0.022 252.894)
Input and button strokes
Slate 400
#90A1B9
oklch(70.4% 0.04 256.788)
Strokes on hover
Slate 500
#62748E
oklch(55.4% 0.046 257.417)
Metadata
Slate 600
#45556C
oklch(44.6% 0.043 257.281)
Running prose
Slate 700
#314158
oklch(37.2% 0.044 257.287)
Labels and dense body
Slate 900
#0F172B
oklch(20.8% 0.042 265.755)
Headings and the wordmark
Signal
State vocabulary, never decoration. Emerald means serving, amber means suspended, red means your input was rejected. Each one always carries a word beside it, so no state depends on hue alone.
Emerald 500
#00BC7D
oklch(69.6% 0.17 162.48)
The live dot
Emerald 700
#007A55
oklch(50.8% 0.118 165.612)
The word “Live”
Emerald 50
#ECFDF5
oklch(97.9% 0.021 166.113)
Confirmation panels
Amber 800
#973C00
oklch(47.3% 0.137 46.201)
Suspended, admin only
Amber 50
#FFFBEB
oklch(98.7% 0.022 95.277)
The suspended pill
Red 600
#E7000B
oklch(57.7% 0.245 27.325)
Validation messages
Red 400
#FF6467
oklch(70.4% 0.191 22.216)
Invalid field stroke
Red 50
#FEF2F2
oklch(97.1% 0.013 17.38)
The one red surface
The One Blue Rule
Blue-600 is the only saturated fill, and it means act on this. If a surface needs emphasis, it gets weight, size, or white space — not a second accent.
The Signal-Not-Decoration Rule
Emerald appears only where something is genuinely serving, amber only where an admin suspended something, red only where input was rejected. Using them to look nicer breaks the only colour code the product teaches.
The Ink Ladder Rule
Darkness encodes rank: slate-900 headings, slate-700 labels, slate-600 prose, slate-500 metadata. Never set body prose in slate-900.
Typography
Figtree does every job, separated by weight rather than by family. Its tall x-height keeps 14px UI text legible, and its 800 weight is heavy enough that the homepage headline needs no second face. The platform mono stack is not a second voice — it appears only where a string is meant to be copied or read literally by a machine.
Figtree, ui-sans-serif, system-ui, sans-serif
From chat to live URL.
Display
800 · 48–72px · −0.03em · 1.04
The homepage headline. One per site.
What your agent can do
Headline
700 · 30–36px · −0.025em · 1.15
Section headings and every page h1.
Your pages
Title
600 · 18–24px · −0.025em · 1.55
Card headings and empty-state statements.
Your AI builds a page and PublishPage puts it online: a real link on its own subdomain.
Body
400 · 16–20px · normal · 1.625
All running prose, always in slate-600.
Connect your agent
Label
500–600 · 14px
Buttons, nav, fields, table cells. Over half the type in the app.
Expires in 3 hours
Meta
400–600 · 12px
Timestamps, helper text, footnotes.
pages/{page_ulid}/current.html
Machine
System mono · 12–14px
Strings meant to be copied or read by a machine.
The One Family Rule
No display serif, no condensed face, no second sans. Weight and size carry every distinction.
The Measure Rule
Every paragraph is capped, by a ch measure or a container. Headlines get text-balance, paragraphs text-pretty.
The Weight-Not-Case Rule
No uppercase, no letter-spaced eyebrows, no kickers above headings anywhere in interface chrome.
Shape, depth and motion
Radius is functional rather than decorative: it tells you what an element does. Nothing in the system has square corners, and nothing floats.
Pill · 9999px
Anything you press, or anything reporting a state at a glance.
Card · 1rem
Anything that holds content: cards, panels, tables, the browser window.
Notice · 0.75rem
Inline status strips that sit between prose rather than standing as cards.
Field · 0.5rem
Anything you type into or copy out of.
The Single Shadow Rule
The system has exactly one shadow and it belongs to the browser-window motif, which is what makes a live page read as an object sitting on the page. Everything else is a 1px slate-200 border or a slate-50 fill.
The No-Lift Rule
Hover changes colour and nothing else. Nothing scales, translates, rotates, or gains a shadow.
The Motion-Safe Rule
One authored entrance, one pulsing live dot, nothing else moves — and every animation is gated behind motion-safe.
Status, always a word and a colour
Every state carries a word beside its colour, so none of them depend on hue alone. A dark page loses the dot — the absence is the signal — and reads in slate-500.
Voice
We are talking to someone who has never deployed anything and may have met their first AI agent last week. Say the plain thing. Name the consequence rather than the mechanism, and never let excitement do the work a fact should do.
Do
- “Your page is live for 24 hours.”
- “Nothing has been deleted.”
- “Sending the link” while a button works.
- Short sentences. One idea each.
- Words for controls, not icons.
Don't
- “Effortlessly supercharge your workflow.”
- “Oops! Something went wrong.”
- Exclamation marks in interface chrome.
- Jargon a first-timer has to look up: deploy, edge, artifact.
- Promising a thing the product has not done yet.
Using the mark elsewhere
You may use the PublishPage mark to link to us, to say a page is published here, or to credit the product in a write-up. Keep it unmodified, keep its clear space, and don't imply we endorse or sponsor what you're making. For anything beyond that, ask first.