The pages a stranger sees. One foundation, three surfaces.
Part of the Konjo design language. The laws in the spine apply here unless this chapter contradicts them, and the two contradictions are named below.
Studio serves a set of routes that no one signs in to reach:
| Route | Who lands on it |
|---|---|
/d/[slug] |
a prospect who searched for the dojo |
/d/[slug]/trial |
the same prospect, converting |
/d/[slug]/waiver/[templateId] |
a parent following an emailed signing link |
/e/[slug], /e/[slug]/thanks |
someone registering for a public event |
/family-wallet |
a parent managing the card their dojo may charge |
/kiosk/[token] |
whoever is standing at the tablet in the lobby |
/apply, /unsubscribe/[token] |
a school considering Konjo; a recipient leaving a list |
/invite-signup, /staff-invite, /onboarding-invite |
a new member or staff member finishing an invitation that arrived by email |
They are not Studio screens. Nobody navigated here from a rail, nobody has a session, and nobody has agreed to learn anything. Until this chapter, that was handled per file: the dojo page invented a palette in its own module CSS, the wallet went its own way in green, and the kiosk and the event page were bare inline styles on a default-white document. Three answers to one question is the drift this chapter closes.
The marketing site, getkonjo.com (apps/site/), is a fourth Konjo-owned public surface —
outside Studio's own app, but held to the same rule. It draws from the same generated palette
(apps/site/src/app/tokens.generated.css, byte-identical to Studio's copy), keeps to the same
budgets — one loud block, one red role, one filled primary, one uppercase register per page —
and the same 44px touch floor. scripts/verify/walk.mjs walks it as anon @ site.
The rule
Every session-less page is set in the shared palette, in ink and Konjo red, and every one of them says whose page it is above the fold. A public page carries a brand mark — the dojo's name on a dojo-owned surface, the Konjo wordmark on a Konjo-owned one. A page reached only from an email says who sent it before it asks for a decision.
Colour comes from tokens.generated.css (var(--color-…)), the same file the desk uses, so a
palette change reaches all of it at once. PublicDojoPage.module.css additionally defines the
storefront's own --pd-* locals; anything new that is not storefront chrome uses the shared
tokens.
The budgets are the spine's, unchanged: one loud block, one red role, one filled primary, one uppercase register per page. A storefront's hero is its one loud block, and its "Book a free trial" is its one red fill; that spends both, so nothing else on the page may be either.
The two deliberate exceptions
Both belong to the conversion funnel — the storefront /d/[slug] and the pages that
continue it: /d/[slug]/trial, /d/[slug]/waiver/[templateId] and /e/[slug]. Neither
reaches the wallet, the kiosk or the unsubscribe page, which are utility surfaces for people
who have already chosen.
1. Gradients. The storefront's hero and the event-cover fallback may carry an ink→red
gradient, and the funnel bar (.trialBar) carries the same fill onto the trial, waiver and
event pages — it is one header, so it is one fill. Everywhere else in the product a fill is
flat. The reason is that this is the one path competing with a school's existing website
rather than serving someone who already trained here. The storefront's closing trial band
is not a second loud block: it repeats the ask at the bottom of a long page as a white
card on the tinted ground with a bordered control, so the hero stays the page's one loud
block and its CTA the page's one red fill.
2. Lift on hover. The storefront only, not the rest of the funnel: an event card
that links to its registration page raises on pointer hover, and the one filled CTA carries
a red glow that deepens on hover. A card that goes nowhere never raises — a staff card is
not a link, and a raise under the pointer that leads nowhere is an affordance that lies.
This is the one place the depth law (elevation) is relaxed —
a card's raise is pointer hover only, the CTA's glow is the single resting shadow anywhere
in Konjo, and both sit inside @media (prefers-reduced-motion: reduce) guards that remove
the transition.
Everything else the spine forbids stays forbidden here: no resting shadows beyond that one CTA, no off-ramp spacing, no hardcoded hex outside a module's own token block, no second red role.
What a utility public page looks like
The wallet is the worked example — apps/studio/src/app/(public)/family-wallet/Wallet.module.css:
shared tokens, a wordmark and a one-line brand line at the top, white cards on the tinted
page, one filled primary and every other control bordered, 44px touch minimums because a
parent meets it on a phone. The kiosk —
apps/studio/src/app/(public)/kiosk/[token]/Kiosk.module.css — is the same system at
lobby-tablet scale: bigger targets, the dojo's name in the header, and a full-screen
confirmation that names the person it just checked in.
The rest of the funnel is not a utility surface: the event page and the waiver page borrow the
storefront's own module —
apps/studio/src/app/(public)/d/[slug]/PublicDojoPage.module.css — rather than restating it,
and each opens with the bar that links back to the dojo. They are steps in one funnel, not
separate sites.
Copy
The voice chapter applies, with one addition: a public page is read by someone who does not know the product's words. No enum slugs, no internal mechanics (a parent has never heard of an "authorization version"), and no jargon that only makes sense next to a database. Say what the reader can act on, then what happens next.