Skip to content

parlor

parlor is the front door of every product built on cafaye: a Next.js app shell — signup, login, accounts and tenancy, team and invitation management, and the billing screens — plus the admin surface they all inherit. It is Next.js, because it is the web and nothing else needs to be.

It is a template, not a platform dependency

Section titled “It is a template, not a platform dependency”

That is the design decision to understand before using it. You clone it, you read all of it, you change what you need and ship your fork: no license key, no feature gate, no call home, and no vendor who can raise your prices or pull the rug later. Anything cafaye adds to the shell arrives as code in your repository, not as a runtime dependency, and upstream improvements come back as a merge rather than a migration.

The test of whether that is real: if cafaye disappeared tomorrow, a parlor-based product would keep shipping.

The tenancy surface is gated by role, transcribed from identity

Section titled “The tenancy surface is gated by role, transcribed from identity”

src/lib/roles.ts is the capability matrix, transcribed from identity’s own authorization — so the UI hides what the API would refuse, and the API is still the authority. Each account call declares the minimum role its route needs:

Call Minimum role
listAccounts(token) any session
read one account, list members member
create a tenant any session
rename, invite, remove a member admin
change a role, delete the account owner

The invitation route does not accept on load — it takes a deliberate click, because an invitation token redeemed by a prefetch or a crawler is an account created for whoever the link was forwarded to.

src/lib/money.ts takes integer minor units in and gives a price out, and the billing client has its own error type rather than borrowing identity’s. The rule is the platform’s rule and the shell follows it, so a fork does not start with a Float.

Session handling is settled in the repository, not the template

Section titled “Session handling is settled in the repository, not the template”

Because the browser reaches identity cross-origin, session handling is a deliberate decision here: a BFF route owns the cookie before it can be one. The token is in an injectable localStorage store rather than a hard-coded access, which is what makes the test rig possible and a future cookie-based BFF a change rather than a rewrite.

The Playwright suite (signup, login, MFA, invites, checkout) is born here and is not written yet.

  • Repository: github.com/cafaye/parlor
  • Language: Next.js / TypeScript
  • Local port: 3000 · bun run dev
  • Health: GET /healthz → {"status":"ok"} · GET /readyz → {"status":"ok","deps":"none"}, where deps is a reserved placeholder