What Studio is, how it is organised, and every screen it ships.
Part of the Konjo design language. The laws in the spine apply here unless this chapter contradicts them. Studio-specific — see the dialect.
Where the visual rules live. This chapter carries Studio's structure and vocabulary. It does not carry colours, type, spacing or radii — those come from the generated token tables, and the way Studio deliberately differs from mobile is the dialect. Tables get their own chapter; so do charts.
This document previously opened with a section headed "Visual identity (strict — do not deviate)" that published a hand-maintained colour table. By the time anyone noticed, it was still carrying
#FAFAFAas the page (the 1.044:1 inversion the separation law exists to correct),text.tertiaryat#888888(3.54:1) and success text at#1F8A4C(3.86:1) — three values the shared palette had already fixed as AA failures, under a heading telling people not to deviate from them. That section is gone, and values are now generated frompackages/design-tokens/tokens.tsso the same thing cannot happen twice.
What Konjo is
Konjo (根性 — Japanese sports slang for guts, fighting spirit) is a martial-arts platform with two sides: a mobile training app for students and instructors, and Konjo Studio, the desktop web dashboard where dojo owners run the business. Positioning line: "Train. Teach. Run the dojo."
The core loop: students log real training in the mobile app → instructors see readiness and gaps → the dojo operates from better data in Studio. Konjo is a martial-arts operating system, not a generic gym CRM — rank ladders, belt testing, curriculum, and instructor readiness are first-class. The launch community is Cuong Nhu (a karate-based style; its association is the CNMAA), but the platform is multi-style by design: each dojo can build or adopt its own style with its own belt ladder.
Competitors (Zen Planner, Kicksite, Gymdesk, MyStudio, Mindbody…) are known for dated UIs, fee opacity, and shallow reporting. Konjo Studio should feel like the opposite: modern, calm, transparent, data-dense without clutter.
What Konjo Studio is
A Next.js web dashboard at studio.getkonjo.com for dojo staff. Users sign in with the same account as the mobile app; students have no access.
Personas, in order of importance:
- Owner / head instructor — sees everything: money, roster, risk, reports.
- Instructor — reduced view: schedule, attendance, their teaching history, My pay.
- Front desk — members, kiosk, shop, leads, messages.
- App admin (Konjo staff) — additionally sees Registry and Dojo launches.
Navigation items appear/disappear per role, so screens must stand alone gracefully. Users with multiple dojos get dojo switcher chips near the page title; the active dojo scopes every screen.
Information architecture (frozen — keep unless asked)
Left rail, top to bottom. Sub-items indent under their parent. Rows appear per
capability, and this list is the rail as NAV in
apps/studio/src/app/(studio)/layout.tsx declares it —
scripts/verify/nav-gate-parity.mjs fails the build when a row's capability
stops matching what proxy.ts demands of its href.
Each section is ordered by how often a dojo opens the row, not by the order the rows were built — the 2026-08-30 close-out reordered Operate and Revenue after the audit found Team (monthly) and Incidents (rare) holding slots 3–4 while Attendance sat 6th and Follow-ups 10th.
Operate
- Home
- Families (default household list; “View members” beside the heading opens the roster. Staff without family access see Members instead.)
- Schedule → Private lessons (Archived classes is linked from the week grid, not the rail — un-archiving is a rare undo and was spending a permanent nav slot)
- Attendance
- Follow-ups
- Substitutes
- Testing
- Waivers
- Kiosk
- Team → Payroll · Staff & access · Audit history
- My pay (beside Team: the employee half of what Payroll runs from the employer side. It sat under Revenue until the audit found that an instructor-only account saw a "Revenue" section header introducing exactly one item — their own pay stub.)
- Incidents & safety
Revenue
- Shop → Catalog · Merch · Merch orders
- Billing → Plans · Family accounts · Payments
- Reports
- Event fees (prices events and opens public registration; it does not create them — events are made in the app, from the floor)
Grow
- Leads
- Messages → Templates · Automations · Scheduled
- Public page
Community (Konjo app-admins only)
- Registry
- Dojo launches
Setup
- Belt ladder
- Settings → Integrations
Screen inventory (the complete shipped surface)
Operate
Home — Daily action queue. Home is the documented exception to the page-header
contract at the bottom of this file, and carries two lines, not three: the eyebrow is the
dojo and the clock (KONJO AUTOMATED TESTS · SUNDAY · AUGUST 30, 2026 · 5:31 AM DOJO TIME), the title is the status line counting what is open (3 things need you today, Playwright.), and there is no page-sub — the queue underneath is the sub. See "Home is
the one exception" below before changing either line; the dojo belongs in the eyebrow, never
in the h1. Then dojo chips if the person has more than one, then six snapshot cards, each
with a "→" link into its section. No greeting — this said "Greeting" until round 8 read
it against the header convention below and against voice, which rules
out first person and cheerfulness. "Good morning, Galen!" is the app talking about itself on
a screen whose job is to say what needs doing. The sections are: Money (collected this month, past-due list),
Today (today's classes with booked counts, open sub requests), Needs attention
(at-risk students with reasons), Growth (new leads, join requests, trials),
Testing (test-ready count, next test, recent promotions), Birthdays (next 30
days).
Members — The alternate view within Families, reached with “View members” beside the heading. “View families” switches back; the Families rail row stays active on both routes. Staff without family access retain a Members rail row and see no family switch. The roster table: member (avatar, name, and a sub-line carrying
email + their family name, which links to that household), belt dot + label, role,
billing pill, last attended (with "21d+ absent" flag), joined. Members with no login
yet carry a small managed flag beside their name. Search, billing-status filter
chips, and the table share one bordered panel. CSV export, a heading switch to Families, and links to
join requests, Add member, Import CSV. Reveal paging, no round-trip — the whole
roster preloads and filters client-side and renders 25 rows at a time behind
Show 25 more / Show all N, per tables.
Families — The primary directory and sidebar destination. A single “View members” button beside the title opens the individual roster, keeping the selected dojo. Clicking Families in the rail always opens the household list. The household index, and the only list of them: family (member
count, distinguishing label, short code), members, payer, owed, billing roll-up
pill; the row opens the family workspace. Same Reveal paging as the roster;
search matches a family, a student, a payer or a short code. The payer and money
columns are dropped, not blanked, for a viewer without the capability that
owns them — a dash would read as "owes nothing". /members?view=families, the
tabbed grid this replaced, redirects here.
Member detail — The CRM record. Header (avatar, belt, role, membership).
Two-column body — left: billing summary card (plan, status, renewal, card on file,
actions: checkout link, freeze/unfreeze, assign plan), payments table, staff notes,
lifecycle timeline; right: contact info (editable phone/address), emergency contacts,
documents (upload/download), family links (guardian, payer account, managed children).
The Training tab opens on the Rank record — every promotion and the corrections and
voids that superseded them — and, for a head instructor or owner, a closed Correct or void a rank disclosure holding the two controls that can take a rank back. Correcting
names the rank the member should hold; voiding takes a record back entirely and
returns them to the rank that preceded it, which the RPC resolves so nobody types it. Both
write a superseding record and never delete the one they replace; a voided promotion stays
on the list marked Voided, a corrected one marked Superseded. Correcting is always
offered; voiding is offered only where the RPC would accept one — the standing record
is not itself a void, the database can name the rank that preceded it, and that record
conferred the rank the member holds now. Where it is not offered, a line in the disclosure
says which of the three is missing and sends the person to Correct instead.
Join requests — Pending self-signups claiming a role/belt at this dojo; approve or decline per row.
Follow-ups (/tasks) — The things that need a person rather than an email: raised
by automations, raised by attendance, or assigned by a colleague. Assigned to me,
the team's open list, snoozed and completed. Home's Needs your call queue is the
ranked, today-shaped view over the same population; where a follow-up already holds
a student, Home's row for them says who holds it and opens /tasks?subject=<id>
rather than starting a second conversation.
Team — Staff hub with tabs Overview / Payroll / Staff & access / Audit history. Overview: stat cards (active staff, classes taught 90d, est. hours) + a card per staff member (role pills, teaching stats, recent classes, pay summary). Per-instructor teaching-history page with export.
Payroll — Employer setup, workers & compensation rates, pay schedules, pay runs (lines by type, approve → lock → export CSV), discrepancy resolution.
Staff & access — Invite staff by email with role checkboxes (Instructor / Head instructor / Front desk), current-staff list with per-row role editing, mark departed, owner-change proposals with per-owner voting.
Audit history — Append-only log table: when, record, change, actor, source.
Incidents & safety — Incident queue (status + severity filters) → report form (category, severity, narrative, people involved) → detail page with review workflow (submit → review → close), follow-up tasks, safety/accommodation flags, evidence uploads, external-notification log, print/PDF.
Schedule — Week grid of recurring classes × 7 days with booked counts, prev/next week. Class-instance page: roster with check-ins, cancel-class-and-notify, book a member, waitlist with promote.
Per-class booking (toggle, capacity, cancellation window, trial capacity, default
instructor) lives on each class's Settings tab, alongside the name, day, time and
eligibility it belongs with. The standalone "Booking settings" screen this file used
to document was retired 2026-08-03 and its route is a 308 to /schedule.
Archived classes (/schedule/archived) — Classes taken off the week grid, with
un-archive. Reached from the week grid, not the rail.
Private lessons — Offerings (title, instructor, duration, price), recorded bookings with status. (Payments for these are informational only today.)
Attendance — Retention screen. "Needs attention" risk queue: student, risk-score pill, reasons, last attended, actions Message / Snooze / Mark away. Away & snoozed table, all-students table with search, attendance by class. Per-student attendance detail with stat cards.
Substitutes — Open coverage requests (assign an instructor, escalation flag), covered list, per-class instructor roster with teach/assist roles.
Kiosk — Front-desk check-in devices: create kiosk → one-time QR + link reveal, device table with last-seen, rename, revoke, regenerate link. (The kiosk itself is a public tap-your-name check-in board.)
Waivers — Templates table (versioned; editing bumps version and outdates signatures) + a signature matrix of students × active waivers with per-cell status (Signed / Outdated / Link sent / Missing) and send-link actions.
Testing — Schedule a belt test, per-test candidate table (current belt → testing for, pass/fail/absent result controls, a Fee pill per candidate — Paid / Processing / Unpaid, shown only for a test that has a fee — and a bulk Remind N unpaid that counts only the families it can actually reach, finalize → bulk promote), test-readiness table (requirements met per student), recent rank records (promotions and the corrections and voids that superseded them; a corrected or voided promotion stays on the list, marked). Correcting and voiding are done on the member record, not here — see Members below.
Revenue
Billing — Overview: Stripe onboarding CTA when unconnected; stat cards (active, trial, past due, frozen, collected this month), dunning queue (owed, attempts, next retry, invoice link), recent payments (with ACH "bank rail" badge), payouts card.
Plans — Membership plans: recurring (interval, trial days) or class packs (credits); price edits, subscriber counts, deactivate/reactivate.
Family accounts — Payer accounts holding multiple students: expandable cards with member list, add student, create managed child (no login), checkout links, billing portal, archive.
Shop register (/pos) — POS: product grid → cart with quantity steppers → buyer
picker → checkout as cash, payment link (QR, 30-min expiry), charge card on file, or
comp. "Sales today" KPI.
Catalog — Product CRUD: price, SKU, stock with low-stock threshold, inline stock adjust.
Payments (/billing/payments) — The one money ledger, per D-29: subscription
charges and register sales in one list with their tender, line items, status tabs
(All/Paid/Pending/Cancelled/Refunded), void / cancel-link / refund, CSV export.
/pos/sales redirects here — there is no second sales ledger.
Event fees (/event-fees) — Upcoming events with their fee (belt tests use the
testing fee), public registration toggle + slug + capacity, registrations list per
event with paid status. Studio prices events; it does not create them — every
write path for an event lives in the app, so the empty state is a direction rather
than a button.
My pay (/my-pay) — Any staff member's own approved pay runs: period, hours, gross, line
detail, report-a-discrepancy.
Reports — Eight tabs: Revenue · Growth · Attendance · Retention · Churn risk ·
Readiness · Lifetime value · Staff. Date-range presets (30d / 3mo / 12mo / YTD), KPI
cards, minimal SVG charts (monthly revenue, growth trend, attendance trend, belt
distribution), detail tables, CSV export per tab. The toolbar is also the index of
the other money exports — QuickBooks export (/reports/quickbooks, a one-dojo
journal-entry CSV, not a rail row) and the Payment ledger — because "export it
for my accountant" is one job and Reports is where an owner opens it.
Grow
Leads — Kanban board with six columns: New · Contacted · Trial scheduled · Trial completed · Converted · Lost. Drag-and-drop cards (name, email, age bracket, "Booked in app" badge). A right-side lead drawer opens per lead: schedule trial, assign staff, convert to member / create account & convert, send checkout link, notes, activity timeline. Copyable public trial-form URL at top.
Messages — Email delivery log (last 200: subject, channel, status, error,
recipient). Compose: channel toggle (Email/SMS), audience picker (all members / by
class / by belt range / parents of minors / custom selection), merge tags
({{first_name}}), preview recipient count, schedule or send now. Templates
(dojo + read-only Konjo defaults). Automations: toggles for birthday greeting,
win-back nudge, trial-ending-soon, cancellation save.
Public page — Editor for the dojo's public web page: publish toggle, description, contact, hero photo, per-instructor show/hide. Links to the live page.
Community (app-admin only)
Registry — CNMAA org-wide member list across all dojos: search, dues filter, member-number assignment, dues status, CSV export.
Dojo launches — Interest queue → launch cases: evidence verification checkboxes, 7-section checklist review, import proposals, final launch control.
Setup
Belt ladder (/style) — Style builder: create or adopt a martial-arts style; ordered
belt-ladder editor with colors/stripes; promotion pacing (expected days per rank);
curriculum by rank with quick-add (name, rank, category, plus an optional video link and
description). Both counts in the curriculum table are links: Test requirements opens
that rank's checklist in place — offered for every non-entry rank on any ladder, not
only the nineteen Cuong Nhu slugs — and Your additions opens Your curriculum filtered
to that rank. Rail label, page title and route gate all say the same thing
(curriculum.manage); the row lives in NAV like every other, and
scripts/verify/nav-gate-parity.mjs fails the build if it drifts from proxy.ts again.
Your curriculum (/style/curriculum) — the techniques a dojo wrote, which until now
could be created from Studio and then only ever edited in the mobile app. One panel:
rank filter, then a six-column table (technique, rank, category, video, order, actions)
with reveal at 25 rows. Editing opens a panel at ?item=<id> with six fields — name,
rank, category, group, description, video link — and saves in place, so a refusal keeps
the typing; a stale-version refusal (someone else edited the same technique) offers a
reload beside the retry. Archive arms then fires and states what it costs: past grades and
plans keep the technique, this dojo's belt tests lose it, and restoring does not put the
test requirements back. No rail row — it is reached from Belt ladder, which is the page
that gives it its meaning. Route gate is /style's (curriculum.manage), so no new
prefix in proxy.ts.
Settings — Stripe Connect card (onboard, status flags, open dashboard), location &
discovery, free-trial allowance. Integrations: webhook endpoints (events like
member.joined, payment.created; pause/test/rotate/delete), delivery log, API keys.
Costs & profit goal (/settings/expenses, linked from Settings, not a rail row):
monthly running costs and the owner's target draw, which is what Home's business-health
card measures the month against.
Public pages (no rail — lighter, centered layouts)
These are session-less pages reached by members of the public, not staff. They share the palette but drop the dashboard shell:
- Public dojo page (
/d/slug) — hero with dojo name + "Try a free class" CTA, about, weekly schedule, instructor grid, events. - Trial request form — the lead-capture form.
- Waiver signing — waiver text + draw-your-signature pad, token-gated.
- Event registration (
/e/slug) — fee, capacity, spots left; pays via Stripe. - Kiosk board — full-screen tap-your-name check-in for a tablet at the front desk.
- Unsubscribe / payment thanks / cancelled — small confirmation pages.
Recurring UI patterns (reuse these; don't invent parallel ones)
- Snapshot cards with a title, a few key numbers/rows, and a "→" link to the full section.
- Stat/KPI card rows — label, big value, small hint line.
- Tables with: sub-text under primary cell, status pills, right-aligned row
actions, one of the two sanctioned paging shapes (Reveal —
Show 25 more— for a preloaded collection, cursor —Next 50 →— for an unbounded one), and a matching empty state. See tables. - Inline forms in cards — label-over-input grids, primary red button, secondary bordered button, small inline buttons for row-level actions.
- Dojo switcher chips at the top of pages for multi-dojo users.
- In-page tab bars (Reports, Team, Student history) — underline or pill tabs under the page title.
- Member search pickers — debounced search input with dropdown results.
- Copy-link boxes — monospace URL in a bordered box with a Copy button (checkout links, kiosk links, trial-form URL).
- Notice/error banners at the top of the content area after actions.
- Eyebrow + page title + one-line sub as the standard page header.
The page header, exactly
Three lines, in this order, and the first two have a contract.
Eyebrow = <section anchor> · <scope>. One form, everywhere.
- The section anchor is the rail row this page hangs from: its own row when the
page is a rail destination (
Members · Blue Heron, plain text), the parent row when the page sits beneath one (Members · Blue Heronon/members/new, with Members a link back). It is the rail's word verbatim, so the row you clicked and the page you landed on introduce themselves with the same name. - The scope is whose data is on screen — the dojo. A page that is not dojo-scoped
names the scope it does have instead:
My pay · Private to Galen Jauss,Registry · CNMAA,Dojo launches · App admin.
Home is the one exception, and it is the whole header that is excepted — eyebrow,
title and sub, not the eyebrow alone. Its eyebrow is the dojo and the clock (BLUE HERON · SUNDAY · AUGUST 30, 2026 · 4:21 PM DOJO TIME), because the page you land on is
the one page you cannot be lost on, and the day and the time are what its queue is
measured against; its title is the status line (3 things need you today, Playwright.), which is the one h1 in Studio that replaces its rail noun instead of
carrying it — "Home" names a destination, and a person already standing on it needs the
count, not the name; and it has no sub, because the queue directly underneath is the
sub. Read this paragraph together with the title law below: Home is the single row that
law does not reach.
This replaced eight dialects the 2026-08 audit found shipping at once (bare dojo name,
SECTION · page, ← ATTENDANCE back-links, FAMILY 3DD8EB, none at all). The rail
is the only place the Operate/Revenue/Grow grouping is stated, and it collapses behind
a toggle on a narrow viewport — the eyebrow is what carries that grouping onto the page
itself. It is 11/800/+1.2 caps like every other eyebrow, and it is never red.
The page title carries the rail row's noun. Most rows repeat it exactly — Members
→ "Members", Payroll → "Payroll", Belt ladder → "Belt ladder". A title may qualify
it, with a modifier in front (Schedule → "Week schedule", Kiosk → "Front-desk
kiosk", Registry → "Style registry", Plans → "Membership plans") or a clarifier
after (Shop → "Shop register", Scheduled → "Scheduled — what's about to send",
Event fees → "Event fees & public registration"). It may not replace it: a reader
should never have to learn that Shop is where Register lives, which is what the bare
title "Register" made them do. Home is the one row this law does not reach — its
title is the status line, per the exception above; 37 of the 38 rail rows satisfy the
law, and Home is the 38th by design.
Two titles carry the noun in a different form rather than verbatim, and are the outer
edge of the rule rather than exceptions to it: Payments → "Payment history", and the
Merch orders child → "Print-on-demand orders", where the parent row Merch one line
up is what "print-on-demand" is naming.
URL parameters
?dojo= is the disciplined convention the codebase already keeps — 50-odd pages carry
it and NavLink forwards it on every rail click, so a rail click never silently
switches a multi-dojo user's tenant. Two more, in the same spirit:
?tab=names an in-page tab. It is what the member record, the family workspace, the register and the class detail already use. Reports (?report=) and the home dashboard (?metric=) predate the rule and still answer to their own names; new tabbed surfaces use?tab=.- Filters keep their own names (
?status=,?range=,?dues=,?billing=,?subject=) because a filter is not a tab — the distinction is worth the two vocabularies. What is not allowed is a cryptic one: a parameter a colleague cannot read out loud over the phone.
Domain vocabulary (use these words, not gym-generic ones)
- Dojo (never "gym", "studio location", "box"). Staff roles: owner, head instructor, instructor, front desk.
- Belt ladder (Cuong Nhu default, 19 ranks): White → One/Two Green Stripes → Green → One/Two Brown Stripes → Brown → One/Two Black Stripes → Black → Shodan → Nidan → Sandan → Yondan → Godan → Rokudan → Shichidan → Hachidan → Kudan. Other styles define their own ladders — never hardcode yellow/orange/purple belts.
- Testing / promotion — belt tests are scheduled events with candidates, requirements ("test readiness"), and finalization that promotes in bulk.
- Dunning — the past-due retry queue in billing.
- Family account — one payer covering multiple students; managed child — a student profile with no login, managed by a guardian.
- Lead → trial → member — the growth funnel.
- Waiver — versioned liability document; signatures go stale when the text changes.
- Kiosk — front-desk self-check-in tablet.
- Substitutes / coverage — filling in when an instructor can't teach.
- Registry — the style association's (CNMAA) org-wide member and dues list.
Hard boundaries — never design these into Studio
The mobile app (separate product) owns everything a student or an instructor does on the training floor: training logs, technique curriculum library, social feed, events browsing, coaching, achievements, class-mode attendance taking, class plans, student-side booking and payments. Studio is the desk, mobile is the floor. If a request seems to need a floor tool, flag it instead of designing it.
Also out of scope: the marketing website (getkonjo.com — a separate Next.js static-export app at apps/site/), native mobile screens, dark mode, and any signup/onboarding flow for students.
Planned but NOT built (design only when a request explicitly asks)
- Third-party integrations depth (Zapier, accounting/marketing sync)
- SMS as a mature channel (email is primary today; SMS is nascent)
- Richer parent communications
- Deeper lifetime-value and churn-prediction analytics
- Private-lesson payment collection
- Per-style curriculum schemas and terminology
- AI front-desk expansion (a staff AI assistant drawer exists; treat it as out of scope for redesigns unless named)
- Governing-body registry sync beyond CNMAA
- Multi-currency / i18n
How to respond to a redesign request
- Redesign only the named screen, at desktop width, with the dark rail visible and the correct nav item active.
- Preserve the screen's data and actions unless the request says otherwise. You may reorganize layout, grouping, hierarchy, and flow freely — that's the job.
- Stay strictly on the palette and design law above.
- Fill it with Blue Heron Martial Arts demo content — real-looking names, belts, dates, dollar amounts, and at least one non-happy-path state (past due, at-risk, empty state) so the design proves it handles them.
- If you're unsure whether something exists in the product, it's in this brief or it doesn't exist — say what you assumed rather than inventing new scope.