This project was created with Better-T-Stack, a modern TypeScript stack that combines React, TanStack Router, Hono, ORPC, and more.
- TypeScript - For type safety and improved developer experience
- TanStack Router - File-based routing with full type safety
- React Native - Build mobile apps using React
- Expo - Tools for React Native development
- TailwindCSS - Utility-first CSS for rapid UI development
- shadcn/ui - Reusable UI components
- Hono - Lightweight, performant server framework
- oRPC - End-to-end type-safe APIs with OpenAPI integration
- Bun - Runtime environment
- Drizzle - TypeScript-first ORM
- PostgreSQL - Database engine
- Authentication - Better-Auth
- Husky - Git hooks for code quality
- Starlight - Documentation site with Astro
- Tauri - Build native desktop applications
- Turborepo - Optimized monorepo build system
This project includes a scripts/dev.sh script to manage the entire local development workflow.
On Windows cmd shell, use scripts\dev.cmd.
scripts/dev.sh initTo skip dependency installation during init:
scripts/dev.sh init --skip-steps deps-installThis will:
- Check dependencies (bun, docker, openssl)
- Install npm packages (unless
deps-installis skipped via--skip-steps) - Create environment files with auto-generated secrets
- Start Docker services (PostgreSQL, Redis, RabbitMQ, etc.)
- Run database migrations
- Seed baseline data
- Bootstrap the default dev organization, users, teams, channels, and credentials
- Prompt to start the development server
# Quick start - full setup (dependencies, env files, docker, migrations, seed, dev workspace bootstrap)
scripts/dev.sh init
# Quick start without dependency installation
scripts/dev.sh init --skip-steps deps-install
# View all init steps and dependencies
scripts/dev.sh init --list-steps
# Start everything (docker services + dev server)
scripts/dev.sh start
# Start only docker services (useful for running dev server separately)
scripts/dev.sh start --docker-only
# Start only dev server (auto-starts services if needed, includes Turbo TUI)
scripts/dev.sh start --dev-only
# Start specific apps/workers only (add studio to include Drizzle Studio)
scripts/dev.sh start --run web,read-receipt,message-indexer
# Start only web + server + Drizzle Studio
scripts/dev.sh start --run web,server,studio
# Start only Drizzle Studio
scripts/dev.sh start --run studio
# Stop all docker services
scripts/dev.sh stop-services
# Reset this project's services and volumes, then re-run init while skipping dependency install
scripts/dev.sh reset-services --skip-init-steps deps-install
# Check what's running
scripts/dev.sh status
# Check environment health
scripts/dev.sh doctor
# View service logs
scripts/dev.sh logs postgres| Command | Description |
|---|---|
init [--skip-steps step1,step2] [--list-steps] |
Full project setup with step controls. --skip-steps skips named init steps with dependency validation for the remaining init graph. deps-install can be skipped if dependencies were installed manually already. --list-steps prints all steps and dependencies. |
start |
Start Docker services and dev server (see options below) |
start --docker-only |
Start only Docker services |
start --dev-only |
Start only dev server (with Turbo TUI), auto-starts services if needed |
start --run target1,target2 |
Start Docker services and run only selected dev targets (all, web, www, server, studio, read-receipt, message-search, message-indexer alias, notification) |
stop-services |
Stop all Docker services without removing the containers |
status |
Show status of services, ports, and environment files |
reset-services [--skip-init-steps step1,step2] |
Destructive - Remove all containers, volumes, and re-run init. --skip-init-steps forwards the same step names supported by init --skip-steps, including dependency validation. |
update-packages |
Update all packages, remove node_modules, and fresh install |
doctor |
Check dependencies, env files, services, and ports |
logs [service] |
View Docker logs for a specific service (or all if no service specified) |
seed [--only=X] |
Run database seeds (optionally filter with --only) |
--run notes:
- Works with
startandstart --dev-only - Cannot be combined with
start --docker-only - Drizzle Studio starts by default with
start(runsdrizzle-kit studiodirectly, not via Turbo); addstudioto a filtered--runlist to include it - Type generators (
web,api,db) run automatically in watch mode alongside dev targets
--run supported values:
all— run default full dev graphweb— runapps/webwww— runapps/wwwserver— runapps/serverstudio— run Drizzle Studio (bun db:studio)read-receipt— runworkers/read-receiptmessage-search— runworkers/message-searchmessage-indexer— alias ofmessage-searchnotification— runworkers/notification(@work-holo/notification-worker)
After init, the workflow bootstraps a ready-to-use local workspace and writes the generated credentials to apps/server/.env as USER1..USER7 entries:
owner@gmail.comadmin1@gmail.comadmin2@gmail.commember1@gmail.commember2@gmail.commember3@gmail.commember4@gmail.com
The bootstrap step creates the default organization, the IT, Sales, HR, and Accounts teams, one team channel for each team, and a shared general channel so a clean database is immediately usable for development.
If you prefer not to use scripts/dev.sh:
-
Install dependencies:
bun install
-
Set up environment files in:
apps/server/.envapps/web/.envapps/www/.envworkers/notification/.envworkers/message-search/.envworkers/read-receipt/.env
-
Start Docker services:
docker compose up -d
-
Run database migrations:
bun db:migrate
-
Seed baseline data:
bun run --cwd apps/seeder src/index.ts
-
Bootstrap the default dev workspace:
bun run --cwd apps/seeder seed:dev-bootstrap
-
Run the development server:
bun dev
Open http://localhost:3001 in your browser to see the main web application. Open http://localhost:5100 to view the marketing site. Use the Expo Go app to run the mobile application. The API is running at http://localhost:3000.
work-holo/
├── apps/
│ ├── web/ # Frontend application (React + TanStack Router)
│ ├── www/ # Marketing site (Vite)
│ ├── native/ # Mobile application (React Native, Expo)
│ ├── docs/ # Documentation site (Astro Starlight)
│ └── server/ # Backend API (Hono, ORPC)
├── packages/
│ ├── api/ # API layer / business logic
│ ├── auth/ # Authentication configuration & logic
│ └── db/ # Database schema & queries
bun dev: Start all applications in development modebun build: Build all applicationsbun dev:web: Start only the web applicationbun dev:www: Start only the marketing sitebun dev:server: Start only the serverbun check-types: Check TypeScript types across all appsbun dev:native: Start the React Native/Expo development serverbun db:migrate: Run committed database migrationsbun db:push: Push schema changes directly to the database schemabun db:studio: Open database studio UI (also started automatically byscripts/dev.sh start)bun generate:types: Generate TypeScript types from Zod schemas (web, api, db)bun generate:types:watch: Watch and regenerate types on schema changescd apps/web && bun desktop:dev: Start Tauri desktop app in developmentcd apps/web && bun desktop:build: Build Tauri desktop appcd apps/docs && bun dev: Start documentation sitecd apps/docs && bun build: Build documentation site
This project auto-generates TypeScript types from Zod schemas. The type generators run automatically in watch mode when using scripts/dev.sh start.
| Package | Schema Directory | Output File |
|---|---|---|
apps/web |
src/lib/schemas/ |
src/lib/types.ts |
packages/api |
src/lib/schemas/ |
src/lib/types.ts |
packages/db |
src/lib/schemas/ |
src/lib/types.ts |
# Generate types once for a specific package
cd apps/web && bun run generate:types
cd packages/api && bun run generate:types
cd packages/db && bun run generate:types
# Watch mode (regenerates on schema changes)
cd apps/web && bun run generate:types:watch- Define Zod schemas in
src/lib/schemas/*.ts - Export schemas with names ending in
Schema,Input, orOutput - Run
generate:typesto create corresponding TypeScript types - Types are auto-generated as
z.infer<typeof SchemaName>exports - In watch mode, types regenerate automatically when schema files change