- Move all application env vars to repository-root .env (with .env.example as the committed template) and drop the per-app .env.example files. - Add @code/env subpaths (agent, convex) and consume validated exports everywhere instead of reading process.env directly. - Wire every dev/build/start script to load ../../.env via bun --env-file and point vite.config.ts envDir at the repo root.
code
This project was created with Better-T-Stack, a modern TypeScript stack that combines React, React Router, Convex, and more.
Features
- TypeScript - For type safety and improved developer experience
- React Router - Declarative routing for React
- React Native - Build mobile apps using React
- Expo - Tools for React Native development
- TailwindCSS - Utility-first CSS for rapid UI development
- Shared UI package - shadcn/ui primitives live in
packages/ui - Convex - Reactive backend-as-a-service platform
- Authentication - Better-Auth
- Electrobun - Lightweight desktop shell for web frontends
- Oxlint - Oxlint + Oxfmt (linting & formatting)
- Vite+ - Unified Vite toolchain, workspace task runner, linting, and formatting
Getting Started
First, install the dependencies:
bun install
Convex Setup
This project uses Convex as a backend. You'll need to set up Convex before running the app:
bun run dev:setup
Follow the prompts to create a new Convex project and connect it to your application.
Copy environment variables from packages/backend/.env.local to apps/*/.env.
Then, run the development server:
bun run dev
Open http://localhost:5173 in your browser to see the web application. Use the Expo Go app to run the mobile application. Your app will connect to the Convex cloud backend automatically.
UI Customization
React web apps in this stack share shadcn/ui primitives through packages/ui.
- Change design tokens and global styles in
packages/ui/src/styles/globals.css - Update shared primitives in
packages/ui/src/components/* - Adjust shadcn aliases or style config in
packages/ui/components.jsonandapps/web/components.json
Add more shared components
Run this from the project root to add more primitives to the shared UI package:
npx shadcn@latest add accordion dialog popover sheet table -c packages/ui
Import shared components like this:
import { Button } from "@code/ui/components/button";
Add app-specific blocks
If you want to add app-specific blocks instead of shared primitives, run the shadcn CLI from apps/web.
Git Hooks and Formatting
- Optional native Vite+ hooks:
bun run hooks:setup - Docs: Vite+ commit hooks
- Run checks:
bun run check
Project Structure
code/
├── apps/
│ ├── web/ # Frontend application (React + React Router)
│ ├── native/ # Mobile application (React Native, Expo)
├── packages/
│ ├── ui/ # Shared shadcn/ui components and styles
│ ├── backend/ # Convex backend functions and schema
Available Scripts
bun run dev: Start all applications in development modebun run build: Build all applicationsbun run dev:web: Start only the web applicationbun run dev:setup: Setup and configure your Convex projectbun run check-types: Check TypeScript types across all appsbun run dev:native: Start the React Native/Expo development serverbun run check: Run Vite+ format/lint checks and workspace TypeScript checksbun run lint: Run Vite+ lint checksbun run format: Run Vite+ formattingbun run staged: Run Vite+ checks against staged filesbun run hooks:setup: Install Vite+ native Git hooks withvp configbun run dev:desktop: Start the Electrobun desktop app with HMRbun run build:desktop: Build the stable Electrobun desktop appbun run build:desktop:canary: Build the canary Electrobun desktop appbun run docs:update [commit-or-range]: Ask a detected coding-agent CLI to update first-party documentation for a commit or revision range; use--dry-runto inspect the promptbun run subtree list: List configured vendored Git subtreesbun run subtree status [name]: Inspect subtree metadata and local dirtinessbun run subtree preview <name>: Fetch and display upstream commits not yet represented by the subtreebun run subtree update <name> --yes: Safely pull a configured subtree with squash semantics