A MONOREPO, NOT A SERVICE

Start your app at feature one.

Bones is a TypeScript monorepo with everything around your product already built, tested, and wired together: sign-in, organizations, permissions, an admin console, logging, email, a blog, docs, and four languages, across a web app, a desktop app, and three public sites. Clone it, and the first thing you write is the part that is actually your product.

bones/admin/permissions
Permissions34 FEATURES · 3 ROLES
FEATUREowneradministratorstandard
page.admin.viewgrantedgrantednot granted
admin.users.viewgrantedgrantednot granted
admin.roles.creategrantednot grantednot granted
admin.terms.updategrantednot grantednot granted
application.organizations.creategrantedgrantedgranted
chatbotgrantedgrantedgranted
WORKSPACES
9
SHARED COMPONENTS
36
TRPC ROUTERS
18
CLIENTS
5
What's inside

The six months of plumbing, already written down.

Fifteen parts every app needs, each one built, tested, and documented. Every card links to a page on the problem it solves and how it compares.

01 · AUTH

Sign-in that already works

Email and password or Google, on better-auth. Verification and reset mail, session handling, bearer tokens for the desktop build, and a switch in the admin console that turns a sign-in method off without a deploy.

02 · PERMISSIONS

Two tiers of access control

Features granted to platform roles, and a separate per-organization grid on top of it. Both are enforced in tRPC middleware and resolved into the session, so the screen and the server read the same answer.

03 · ORGANIZATIONS

Organizations with real membership

Members, avatars, and a profile per organization. Roles are scoped to the organization, the last admin cannot be removed, and membership is soft-deleted rather than dropped.

04 · ADMIN

A console that comes with it

Users, organizations, roles, permissions, feature flags, sign-in methods, site settings, and versioned terms with per-user acceptance — built, not sketched.

05 · OPS

Logs you can hand to a reviewer

Every database write and every request, structured and redacted, rotated on disk and archived to S3 on a schedule. Health checks and a seeded owner account from the first migration.

06 · BLOG

A blog that ships as static files

Draft, edit and publish from the admin console. Metadata in Postgres, post bodies and media in S3, and a separate static build that renders every post to a real HTML file — indexable without running a line of JavaScript.

07 · DOCS

Docs that change with the code

Why, what, and how for every feature, as MDX in the repository, edited in the same pull request as the code. A static site with search built in, and every page available as Markdown for AI tools.

08 · EMAIL

Email that matches the product

Templates written in React and rendered to the tables and inline styles real email clients need, with tokens generated from the design system. Mailpit catches every message in development, and SES sends in production.

09 · CHATBOT

A chatbot already pointed at a model

Claude on Bedrock in production and a local Ollama model in development, behind one provider interface. Replies stream token by token, conversations persist per organization, and access runs through the same permission grid as everything else.

10 · CLIENTS

One backend, five clients

A web app, a desktop app with its own routes, this site, the blog, and the docs, all calling one backend. The apps call it through tRPC with full types, so a renamed field breaks the build, not production.

11 · DESIGN

Aggressively cohesive

One token file behind the web app, the desktop app, this site, the blog, the docs, and every email. Shared components are specified in COMPONENTS.md and drawn in Storybook, and a control written twice gets hoisted rather than copied.

12 · LANGUAGES

Four languages, right to left included

English, French, Spanish, and Hebrew on every surface, from the apps to the emails and error messages. Hebrew mirrors every layout, and CI fails on interface text that skips translation.

13 · ACCESSIBILITY

Checked against WCAG 2.2 AA

The marketing site, the blog, the docs, and every Storybook story, in light and dark, on every pull request. axe runs its rules, and a second check confirms the landmarks, headings, and labels a screen reader relies on.

14 · SECURITY

Protections in the code, scanned on every change

Bounded inputs, parameterized queries, rate limits, checked uploads, and a CSP on every page. Semgrep, OWASP ZAP, a CSP check, and a secrets check run on every pull request.

15 · CI/CD

Tests that run against the real thing

Backend tests against a real Postgres in a throwaway container, every Storybook story in real Chromium, and a build of every site. Each pull request runs only the jobs its change touches.

How it works

Three steps, and none of them is "wait for a build."

01

Up and running fast

A cohesive dev environment means it's just a few commands to get working. One of them starts the backend, the web app, the marketing site, the blog, and the docs together.

02

Make it your SaaS

Whatever you're building, you're already that much closer. Sign-in, organizations, permissions, an admin console, email, and four languages are done, and every router and page you add gets them.

03

Deploy it

Ship it to production and start getting users. Everything is in AWS, with easy tier toggles as your app grows: Starter, Growth, and High availability, each a one-line change.

The code

A repository a developer would be happy to inherit. A repository an AI can pick up.

Every permission in Bones is a row in a table and a middleware call on a procedure. Nothing is enforced only in the interface, and nothing is hidden behind a service you cannot read.

The same holds for the parts a model has to read. The rules, the specs and the reasons are in the repository, so an agent works from what the code does instead of inferring it.

For a developer
  • Standard frameworks — Fastify, tRPC, Drizzle, React. No proprietary runtime to call.
  • Permissions enforced in server middleware, not hidden in the interface.
  • Migrations you run yourself, against your own Postgres.
  • Tests that run against a real database in a throwaway container, not a mock.
For an AI
  • Conventions written down rather than inferred: nine hard rules in CLAUDE.md, thirty-four component specs in COMPONENTS.md.
  • Comments explain why a decision was made, never what the next line does.
  • Finished work recorded in NOTES.md, open work numbered in TODOS.md — context on disk, not in someone's head.
  • Every component and page in Storybook, so a change can be checked rather than guessed at.
  • Every docs page as Markdown, and the whole site at /llms.txt, so an agent can read why a part was built before it changes it.
backend/src/trpc/routers/roles.ts
export const rolesRouter = router({
  list: protectedProcedure.query(() =>
    db.select().from(roles)
  ),

  create: requirePermission("admin.roles.create")
    .input(z.object({ name: z.string().min(1) }))
    .mutation(async ({ input }) => {
      const [created] = await db
        .insert(roles)
        .values({ name: input.name })
        .returning();

      return created;
    }),
});
The stack

Mainstream, well-documented tools. Anyone you hire, and any AI you use, already knows them.

  • TypeScript
  • Fastify
  • tRPC
  • Zod
  • Drizzle
  • Postgres
  • Better Auth
  • Pino
  • React
  • Vite
  • Mantine
  • Tauri
  • Next.js
  • Fumadocs
  • React Email
  • i18next
  • Storybook
  • Vitest
  • Testcontainers
  • Playwright
  • oxlint
  • Docker
  • GitHub Actions
  • AWS

The foundation is done. Build the rest.

Sign in and start from a stack that already works — then keep every file of it.

Sign Up for Updates

New releases and posts, by email. Unsubscribe from any message.