Skip to content

Repository files navigation

kitcn-tanstack-bootstrap

A Bun + Turborepo monorepo template for shipping production apps on TanStack Start + Convex (via kitcn) with a custom session-token user system, a separate front-of-house app and admin dashboard sharing the same backend and design system.

Stack

Layer What it uses
Runtime Bun 1.3.11, Turborepo 2.9
Frontend TanStack Start (Vite, SPA mode on Cloudflare Workers), TanStack Router, TanStack Query
Backend Convex with kitcn procedure builders + ORM
Auth Custom session-token user system (scrypt credentials, localStorage token, role-gated apps)
UI Ant Design v6 (antd + @ant-design/icons), no CSS framework
Tooling oxc (oxfmt + oxlint --type-aware), portless named-localhost dev URLs
Deploy Cloudflare Workers via @cloudflare/vite-plugin (per-app wrangler.jsonc)

Two apps share the backend:

  • apps/web — front-of-house, gates role === "user"
  • apps/dashboard — admin, gates role === "admin"

Prerequisites

  • Bun ≥ 1.3.11 (required — packageManager is pinned)
  • portless — npm i -g portless
  • A Convex account
  • (production) A Cloudflare Workers account (wrangler is bundled as a dependency)

Setup

1. Clone and install

git clone git@github.com:MikeyZhang75/kitcn-tanstack-bootstrap.git my-app
cd my-app
bun install

2. Provision your Convex deployment

cd packages/backend
bunx convex dev --once

This walks you through Convex login + project creation and writes CONVEX_DEPLOYMENT + CONVEX_URL to packages/backend/.env.local. Note the deployment URL; you'll wire it into the frontend next.

3. Push the backend to your deployment

# from packages/backend/
bunx kitcn dev --once

bunx kitcn dev --once pushes the schema + functions to your new deployment. There are no runtime env vars or auth secrets to provision — the app uses its own session-token system (scrypt password hashing in Convex), not Better Auth or JWTs.

4. Configure frontend env files

Create apps/web/.env.local:

VITE_CONVEX_URL=https://your-deployment.convex.cloud
VITE_CONVEX_SITE_URL=https://your-deployment.convex.site
VITE_SITE_URL=https://web.localhost

Create apps/dashboard/.env.local (same VITE_CONVEX_* values, different VITE_SITE_URL):

VITE_CONVEX_URL=https://your-deployment.convex.cloud
VITE_CONVEX_SITE_URL=https://your-deployment.convex.site
VITE_SITE_URL=https://dashboard.localhost

5. Start the portless proxy

portless routes *.localhost HTTPS through a daemon on port 443. It needs sudo once per machine boot — bun dev will register routes automatically but the proxy itself doesn't auto-start without elevation:

sudo portless proxy start

The proxy generates a local CA on first run and adds it to your system trust store, so no browser warnings. See docs/dev-environment.md for details.

6. Run dev

From the repo root:

bun run dev

This launches three Turbo tasks in parallel:

7. Bootstrap the first admin

Signups always land as role: "user", so the dashboard (role === "admin") has no client signup path on a fresh deployment. Use the cold-start mutation once:

cd packages/backend
bunx convex run users:bootstrapAdmin '{"username":"admin","password":"<your-password>"}'

Then sign in at https://dashboard.localhost with that username and password. See docs/auth.md for prod variants and the safety net (refuses to run if any admin already exists).

Common scripts

Command What it does
bun run dev Run all dev servers (web + dashboard + backend codegen watcher)
bun run build Production build of both apps
bun run typecheck Type-check across all workspaces — the canonical correctness gate
bun run check:fix Format with oxfmt + lint with oxlint --type-aware --fix
bun run codegen Regenerate kitcn / Convex bindings (run after editing convex/functions/* or schema.ts)

Backend-only:

cd packages/backend
bun run dev      # kitcn dev (Convex + codegen watcher)
bun run deploy   # kitcn deploy --yes (prod)

UI

Components come from Ant Design v6, imported directly in each app. There is no shared UI workspace and no CSS framework — no Tailwind, no className styling:

import { DashboardOutlined } from "@ant-design/icons";
import { Button, Flex, theme, Typography } from "antd";

const { token } = theme.useToken();

Layout goes through antd's own primitives (Flex, Layout, Typography); everything else is an inline style fed by theme.useToken(). Locale (zh_CN) and theme are configured once in each app's src/components/providers.tsx, and toasts come from App.useApp() rather than the static message export.

See docs/ui-components.md for the shell, table, and form patterns plus the antd v6 API notes.

Production deployment

CI deploys on push to main (when the workflow is wired up):

  1. Convex via kitcn deploy.
  2. Both apps to Cloudflare Workers — each app's deploy script runs vite build && wrangler deploy, reading apps/web/wrangler.jsonc / apps/dashboard/wrangler.jsonc.

Each app is built with its own VITE_SITE_URL (its public origin, validated in src/env.ts):

bun run build --filter=@repo/web        # with VITE_SITE_URL=https://app.example.com
bun run build --filter=@repo/dashboard  # with VITE_SITE_URL=https://dash.example.com

For schema changes that need a backfill (e.g. adding a .notNull() column), follow docs/MIGRATION.md — never deploy a .notNull() column before existing rows have the value set.

Documentation

License

MIT.

About

TanStack Start + kitcn (Convex) + Better Auth bootstrap monorepo. Bun + Turborepo, oxc tooling, Cloudflare Pages deploy.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages