Official website for VOM Labs — vomlabs.com.
Built with TanStack Start (React 19 + TypeScript), styled with Tailwind CSS v4 and shadcn/ui, backed by Drizzle ORM + PostgreSQL, and authenticated with Better Auth.
| Layer | Technology |
|---|---|
| Framework | TanStack Start, React 19, TypeScript |
| Styling | Tailwind CSS v4, shadcn/ui (@base-ui/react) |
| Data | Drizzle ORM, PostgreSQL (postgres) |
| Auth | Better Auth (+ Drizzle adapter) |
| Tooling | Bun, Vite, Vitest, oxlint, oxfmt |
| Deploy | Docker → Docker Hub (vomlabs/website) |
- Bun
>= 1.3.14(pinned viapackageManagerinpackage.json) - Node.js
>= 22
# 1. Install dependencies
bun install
# 2. Configure environment
cp .opencode/env.example .env # or create .env with the values below
# 3. Start the dev server (http://localhost:3000)
bun run dev| Variable | Description |
|---|---|
DATABASE_URL |
PostgreSQL connection string used by Drizzle and Better Auth |
BETTER_AUTH_URL |
Public URL of the auth instance (e.g. https://vomlabs.com) |
Add any additional secrets required by your auth/email provider to .env. .env* files are gitignored.
| Command | Description |
|---|---|
bun run dev |
Start the Vite dev server on port 3000 |
bun run build |
Production build (Vite) |
bun run preview |
Preview the production build locally |
bun run start |
Serve the production build (port via $PORT, default 3000) |
bun run test |
Run Vitest (--passWithNoTests) |
bun run lint |
Lint with oxlint |
bun run fmt |
Format the workspace with oxfmt |
bun run fmt:check |
Verify formatting without writing |
bun run typecheck |
Type-check with tsc --noEmit |
bun run db:studio |
Open Drizzle Studio |
bun run db:push |
Push schema changes to the database |
bun run db:seed |
Seed the database (src/scripts/seed.ts) |
The workspace uses oxc tooling as the primary linter and formatter:
- oxlint — configuration in
.oxlintrc.json(correctnesserrors,perfwarnings; React, TypeScript, import, unicorn, and vitest plugins enabled) - oxfmt — configuration in
.oxfmtrc.json(print width 80, semicolons, double quotes, import and Tailwind class sorting)
Generated files (*.gen.*) are excluded from both tools. CI enforces all quality gates on every pull request.
src/
├── components/ # UI components (shadcn/ui in components/ui/) and app components
├── hooks/ # Shared React hooks
├── lib/ # Utilities, auth, and database access
│ └── db/ # Drizzle schema and connection
├── routes/ # TanStack Router routes (pages, API routes, blog)
│ └── api/auth/ # Better Auth API handlers
└── scripts/ # Database seed and tooling scripts
GitHub Actions workflows in .github/workflows/:
ci.yml— runs on every PR andmainpush: install (frozen lockfile) → lint → format check → typecheck → test → builddeploy.yml— onmainpushes, builds the multi-stage Bun Docker image and pushesvomlabs/websiteto Docker Hub (tags:latest+sha-<commit>), with Buildx layer caching
main is protected by a repository ruleset: pull requests with 1 approval and a passing ci check, squash-only merges, linear history, and no force-pushes.
Dependabot keeps Bun dependencies (weekly, grouped minor/patch) and GitHub Actions up to date via .github/dependabot.yml.
The multi-stage Dockerfile builds with Bun and runs the server as a non-root user on port 3000.
# Build and run locally
docker compose up --build
# Or push to Docker Hub manually
docker build -t vomlabs/website .
docker push vomlabs/website