A starter project for building a full-stack application using Bun, TypeScript, ElysiaJS, Kysely with Postgres, and React.
This project uses Bun as its runtime and package manager. Bun provides faster installs, native TypeScript execution, and improved performance over Node.js.
- Bun-powered - Uses Bun for package management, script execution, and runtime.
- ElysiaJS API server with TypeScript.
- React frontend with TanStack Router and TanStack Query.
- Monorepo setup using
turboand Bun workspaces. - OpenAPI docs via Scalar UI at
/docs. - Type-safe client SDK via Eden Treaty.
- Sample REST tests using Vitest.
- Sample database migrations and repositories using Kysely.
- Shared error handler package for consistent API error responses.
- Code generators using
turbo gento scaffold new API endpoints and database tables.
| Package | Description |
|---|---|
apps/backend |
ElysiaJS API server |
apps/frontend |
React frontend (Vite, TanStack Router, TanStack Query, Tailwind CSS) |
packages/backend-client |
Type-safe Eden Treaty client generated from the backend |
packages/backend-errors |
Shared error types and handler for the backend |
packages/tsconfig |
Shared TypeScript configuration |
typescriptbunfor package management and runtimeturbofor monorepo managementelysiafor the API server framework@elysiajs/openapifor OpenAPI docs (Scalar UI)@elysiajs/edenfor type-safe API client (Eden Treaty)react+vitefor the frontend@tanstack/react-routerfor client-side routing@tanstack/react-queryfor data fetchingtailwindcssfor stylingkyselyfor the database query builderpostgresfor the databasetestcontainersfor testing with a sandboxed Postgres instancevitestfor testingloglayer+@loglayer/elysiafor request-scoped logginghash-runnerfor incremental dev buildsbiomefor linting and formattingsyncpackfor keeping package versions in synccommitlintfor commit message linting
-
Install Bun (if not already installed):
curl -fsSL https://bun.sh/install | bash -
Install dependencies:
bun install
-
Copy the example env file:
cp apps/backend/.env.example apps/backend/.env
-
Start the local Postgres server:
docker compose up -d
-
Run database migrations:
bun run db:migrate:latest
turbo watch dev| Service | URL |
|---|---|
| API server | http://localhost:3080 |
| OpenAPI docs | http://localhost:3080/docs |
| Frontend | http://localhost:5173 |
| PGAdmin | http://localhost:5050 |
Requires Docker — uses Testcontainers to spin up a temporary Postgres instance per test run.
turbo testturbo buildGenerators for new API endpoints + tests and database tables + repositories:
turbo genThe @internal/backend-client package provides a type-safe Eden Treaty client:
import { createBackendClient } from '@internal/backend-client'
const api = createBackendClient('http://localhost:3080')
const { data, error, status } = await api.users.email.post({
givenName: 'John',
familyName: 'Doe',
email: 'john@example.com',
password: 'securepass123',
})bun run db:migrate:create # Create a new migration
bun run db:migrate:latest # Apply all pending migrations
bun run db:migrate:undo # Roll back the last migrationbun run syncpack:update× failed to connect to daemon
╰─▶ server is unavailable: channel closed
or
× discovery failed: bad grpc status code: The operation was cancelled
Run turbo daemon clean and try again. If the second error persists, wait a minute and retry.
Related: vercel/turborepo#8491