S10N Base is a Bun + Turbo monorepo scaffold for a local-first app with a typed server boundary, web client, and optional desktop host.
It was derived from t3code, keeping the overall repo shape and developer workflow while removing product-specific coding-agent behavior.
- Bun workspaces + Turbo
- Strict TypeScript across apps and packages
apps/server: Node HTTP server with typed RPC, WebSocket activity stream, and SQLite persistence viabetter-sqlite3apps/web: React 19 + Vite + Tailwind CSS v4 + TanStack Router + TanStack Queryapps/desktop: thin Electron wrapper around the server and web UIpackages/contracts: shared Effect schemas and RPC contractspackages/shared: small cross-runtime helpers- Oxlint + Oxfmt + Vitest
apps/
desktop/
server/
web/
packages/
contracts/
shared/
scripts/
- Bun
>=1.3.0 - Node
>=24
Install dependencies:
bun installRun the server and web app in development:
bun run devRun individual apps:
bun run dev:server
bun run dev:web
bun run dev:desktopBuild everything:
bun run buildStart built apps:
bun run start:server
bun run start:web
bun run start:desktopRun checks:
bun run fmt
bun run fmt:check
bun run lint
bun run typecheck
bun run testClean generated output:
bun run clean- Server:
http://127.0.0.1:4210 - Web dev server:
http://127.0.0.1:5173
In development, the Vite app proxies /health, /config, /rpc, and /ws to the server.
HOST: host for the server and Vite dev server. Default:127.0.0.1PORT: fallback server port. Default:4210S10N_BASE_PORT: preferred server port overrideS10N_BASE_HOME: runtime directory for server data and logs. Default:~/.s10n-baseVITE_SERVER_URL: server URL used by the Vite dev proxy. Default:http://127.0.0.1:4210S10N_BASE_SERVER_URL: server URL the desktop app should connect to. Default:http://127.0.0.1:4210VITE_DEV_SERVER_URL: web dev server URL the desktop app should load in development. Default:http://127.0.0.1:5173
The server creates and uses this runtime layout under S10N_BASE_HOME:
~/.s10n-base/
data/
app.db
settings.json
logs/
server.log
The server currently exposes:
GET /healthGET /configPOST /rpcGET /wsvia WebSocket upgrade
When apps/web/dist exists, the server also serves the built web app.
The scaffold currently proves the stack with a small example domain:
- projects
- notes within projects
- server-persisted app settings
- live activity events over WebSocket
- a few client-only UI settings persisted with Zustand
If you are turning this into a new product, start with CUSTOMIZATION_GUIDE.md.