diff --git a/.env.example b/.env.example
index d286b4c..f097000 100644
--- a/.env.example
+++ b/.env.example
@@ -12,17 +12,19 @@ POSTGRES_USER=betterbase
POSTGRES_PASSWORD=your_secure_password_here
POSTGRES_DB=betterbase
-DATABASE_URL=postgresql://betterbase:your_secure_password_here@localhost:5432/betterbase
+# Connection string for applications
+# Format: postgresql://user:password@host:port/database
+DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:5432/${POSTGRES_DB}
# ----------------------------------------------------------------------------
# Authentication
# ----------------------------------------------------------------------------
-# Generate: openssl rand -base64 32
-AUTH_SECRET=your-super-secret-key-min-32-chars-long
-AUTH_URL=http://localhost:3000
+# Generate a secure secret: openssl rand -base64 32
+BETTERBASE_JWT_SECRET=your-super-secret-key-min-32-chars-long
+BETTERBASE_PUBLIC_URL=http://localhost:3000
# ----------------------------------------------------------------------------
-# MinIO (S3-compatible storage)
+# MinIO (S3-compatible storage for local development)
# ----------------------------------------------------------------------------
MINIO_ROOT_USER=minioadmin
MINIO_ROOT_PASSWORD=minioadmin_password
@@ -36,9 +38,9 @@ STORAGE_BUCKET=betterbase
# Inngest (Durable Workflow Engine)
# ----------------------------------------------------------------------------
INNGEST_LOG_LEVEL=info
-# Generate: openssl rand -hex 32
+# Generate signing key: openssl rand -hex 32
INNGEST_SIGNING_KEY=
-# Generate: openssl rand -hex 16
+# Generate event key: openssl rand -hex 16
INNGEST_EVENT_KEY=
# ----------------------------------------------------------------------------
@@ -48,19 +50,21 @@ NODE_ENV=development
PORT=3001
HOST=0.0.0.0
-CORS_ORIGIN=http://localhost:3000,http://localhost:5173
+CORS_ORIGINS=http://localhost:3000,http://localhost:5173
LOG_LEVEL=debug
# ----------------------------------------------------------------------------
-# Storage (S3-compatible - for production with external services)
+# Production Settings
# ----------------------------------------------------------------------------
-# STORAGE_PROVIDER=r2
-# STORAGE_BUCKET=betterbase-storage
-# STORAGE_REGION=auto
+# HTTP port for nginx proxy (default: 80)
+# HTTP_PORT=80
+
+# Use external managed services instead of Docker (uncomment):
+# DATABASE_URL=postgres://user:password@host:5432/database
# STORAGE_ENDPOINT=https://your-r2-endpoint.r2.cloudflarestorage.com
-# STORAGE_ACCESS_KEY_ID=your-access-key
-# STORAGE_SECRET_ACCESS_KEY=your-secret-key
+# STORAGE_ACCESS_KEY=your-access-key
+# STORAGE_SECRET_KEY=your-secret-key
# ----------------------------------------------------------------------------
# Email (optional)
@@ -83,12 +87,15 @@ LOG_LEVEL=debug
# ----------------------------------------------------------------------------
# Phone Auth (optional - Twilio)
# ----------------------------------------------------------------------------
-# TWILIO_ACCOUNT_SID=your-twilio-sid
-# TWILIO_AUTH_TOKEN=your-twilio-token
-# TWILIO_PHONE_NUMBER=+1234567890
+# STORAGE_PROVIDER=r2
+# STORAGE_BUCKET=betterbase-storage
+# STORAGE_REGION=auto
+# STORAGE_ENDPOINT=https://your-r2-endpoint.r2.cloudflarestorage.com
+# STORAGE_ACCESS_KEY_ID=your-access-key
+# STORAGE_SECRET_ACCESS_KEY=your-secret-key
# ----------------------------------------------------------------------------
# Vector Search (optional)
# ----------------------------------------------------------------------------
# VECTOR_PROVIDER=openai
-# OPENAI_API_KEY=your-openai-api-key
\ No newline at end of file
+# OPENAI_API_KEY=your-openai-api-key
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..d4ca892
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,84 @@
+# Contributing to Betterbase
+
+Thank you for your interest in contributing to Betterbase!
+
+## Getting Started
+
+1. **Fork** the repository
+2. **Clone** your fork: `git clone https://github.com/your-username/betterbase.git`
+3. **Install** dependencies: `bun install`
+4. **Create** a branch: `git checkout -b feature/my-feature`
+
+## Development Setup
+
+```bash
+# Install dependencies
+bun install
+
+# Build all packages
+bun run build
+
+# Run tests
+bun test
+
+# Run linting
+bun run lint
+```
+
+## Code Style
+
+We use Biome for code formatting and linting:
+
+```bash
+# Format code
+bun run format
+
+# Lint code
+bun run lint
+
+# Fix auto-fixable issues
+bun run lint:fix
+```
+
+## Testing
+
+```bash
+# Run all tests
+bun test
+
+# Run tests for specific package
+bun test --filter=@betterbase/cli
+
+# Run tests in watch mode
+bun test --watch
+```
+
+## Commit Messages
+
+Follow Conventional Commits:
+
+```
+feat: add new feature
+fix: resolve bug
+docs: update documentation
+refactor: restructure code
+test: add tests
+chore: maintenance
+```
+
+## Submitting Changes
+
+1. Push your branch: `git push origin feature/my-feature`
+2. Open a **Pull Request**
+3. Fill out the PR template
+4. Wait for review
+
+## Good First Issues
+
+Looking for a way to contribute? Check out our [Good First Issues](https://github.com/weroperking/Betterbase/labels/good-first-issue) label on GitHub.
+
+## Community
+
+Join our community:
+- **Discord**: https://discord.gg/R6Dm6Cgy2E
+- **GitHub Discussions**: https://github.com/weroperking/Betterbase/discussions
diff --git a/README.md b/README.md
index 15febfb..e4f7190 100644
--- a/README.md
+++ b/README.md
@@ -1,48 +1,71 @@
-# Betterbase
-
+[](https://deepwiki.com/weroperking/Betterbase)
+
+```
+██████╗ ██╗ ██╗ ██████╗ ██████╗ ██╗ ███████╗ ██████╗ ██╗ ██╗███████╗
+██╔══██╗██║ ██║██╔════╝██╔═══██╗██║ ██╔════╝ ██╔═══██╗██║ ██║██╔════╝
+██████╔╝███████║██║ ██║ ██║██║ █████╗ ██║ ██║██║ █╗ ██║█████╗
+██╔══██╗██╔══██║██║ ██║ ██║██║ ██╔══╝ ██║ ██║██║███╗██║██╔══╝
+██║ ██║██║ ██║╚██████╗╚██████╔╝███████╗███████╗ ╚██████╔╝╚███╔███╔╝███████╗
+╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝╚══════╝ ╚═════╝ ╚══╝ ╚══╝ ╚══════╝
+```
+
**The AI-Native Backend-as-a-Service Platform**
-Betterbase is an open-source alternative to Supabase, built with Bun for blazing-fast performance. It provides database, authentication, realtime subscriptions, storage, and serverless functions with sub-100ms local dev using Bun + SQLite.
+Blazing-fast backend development with Sub-100ms Local Dev — Built on Bun + SQLite, deploy anywhere with PostgreSQL support.
-**Last Updated: 2026-03-28**
+*Database • Authentication • Realtime Subscriptions • Storage • Serverless Functions • Vector Search*
-[](https://deepwiki.com/weroperking/Betterbase)
+**Last Updated: 2026-03-29**
---
-## Why Betterbase?
-
-Traditional backend development is slow. You spend weeks setting up databases, authentication, APIs, and infrastructure before writing business logic. Betterbase changes that.
-
-```
-┌────────────────────────────────────────────────────────────────────────────────┐
-│ BETTERBASE ARCHITECTURE │
-├────────────────────────────────────────────────────────────────────────────────┤
-│ │
-│ ┌─────────────────┐ ┌──────-──────────────────────┐ ┌────────────┐ │
-│ │ Frontend │ │ Betterbase Core │ │ Database │ │
-│ │ (React, │─────▶ | │───▶│ (SQLite, │ │
-│ │ Vue, │ │ Auth │ Realtime │ Storage │ │ Postgres)│ │
-│ │ Mobile) │ │ RLS │ Vector │ Functions│ └────────────┘ │
-│ └─────────────────┘ └────────────────────────────┘ │
-│ │ │
-│ ┌──────▼──────┐ │
-│ │ IaC Layer │ (Convex-inspired) │
-│ │ betterbase/ │ (Convex-inspired) │
-│ └─────────────┘ │
-└────────────────────────────────────────────────────────────────────────────────┘
-```
+## Why Choose Betterbase?
+
+```
+┌─────────────────────────────────────────────────────────────────────────────────────────────┐
+│ ✦ BETTERBASE ARCHITECTURE ✦ │
+├─────────────────────────────────────────────────────────────────────────────────────────────┤
+│ │
+│ ┌──────────────┐ ┌──────────────────────────────┐ ┌─────────┐ │
+│ │ Frontend │ │ │ │ │ │
+│ │ (React, Vue, │──────────▶│ BETTERBASE CORE │──────────▶│ DB │ │
+│ │ Mobile, │ │ │ │ SQLite/ │ │
+│ │ Svelte) │ │ Auth │ Realtime │ Storage │ │ Postgres│ │
+│ └──────────────┘ │ RLS │ Vector │ Fns │ └─────────┘ │
+│ └──────────────────────────────┘ │ │
+│ │ │ │
+│ ┌──────▼──────┐ │ │
+│ │ IaC │◀──── (Infrastructure as Code) │ │
+│ │ Layer │ │ │
+│ │ Convex-ish │ │ │
+│ └───────────┘ │ │
+│ │ │
+│ ┌──────▼──────┐│
+│ │ Inngest ││
+│ │ Workflows ││
+│ └────────────┘│
+└─────────────────────────────────────────────────────────────────────────────────────────────┘
+```
+
+| | TraditionalBAAS | Betterbase |
+|--|------------------|------------|
+| ⚡ | Slow local dev | **Sub-100ms dev** with Bun + SQLite |
+| 🗄️ | Black box DB | **Full PostgreSQL** with raw SQL access |
+| 🔍 | Basic search | **Full-text + Vector search** built-in |
+| 🚀 | Cloud lock-in | **Self-host anywhere** with Docker |
+| 📊 | Limited analytics | **Full observability** out of the box |
+| 🔐 | Closed source | **100% open source** - deploy anywhere |
---
## Quick Start
```bash
-# Install CLI
+# Install the CLI
bun install -g @betterbase/cli
# Create a new project (IaC mode - recommended)
@@ -52,36 +75,6 @@ bun install
bb dev
```
-## Inngest Integration
-
-Betterbase uses [Inngest](https://www.inngest.com/) for durable workflows and background jobs.
-
-### Deployment Modes
-
-| Mode | Inngest Backend | Used By |
-|------|----------------|---------|
-| Cloud | `https://api.inngest.com` | BetterBase Cloud offering |
-| Self-Hosted | `http://inngest:8288` | Docker deployment |
-| Local Dev | `http://localhost:8288` | Development and testing |
-
-### Environment Variables
-
-```bash
-# For local development
-INNGEST_BASE_URL=http://localhost:8288
-
-# For self-hosted production
-INNGEST_BASE_URL=http://inngest:8288
-INNGEST_SIGNING_KEY=your-signing-key
-INNGEST_EVENT_KEY=your-event-key
-```
-
-### Features
-
-- **Webhook Delivery**: Retryable, observable webhook delivery with automatic backoff
-- **Notification Rules**: Cron-based metric polling with fan-out notifications
-- **Background Exports**: Async CSV export with progress tracking
-
Your project structure:
```
@@ -163,22 +156,7 @@ Your backend runs at `http://localhost:3000`. The dashboard is at `http://localh
---
-## BetterBase vs Convex
-
-| Feature | Convex | BetterBase |
-|---------|--------|------------|
-| Database | Black box | Full PostgreSQL |
-| Raw SQL | Not available | `ctx.db.execute()` |
-| Full-Text Search | Not built-in | PostgreSQL FTS |
-| Vector Search | Limited | pgvector + HNSW |
-| Self-Hosting | Not supported | Docker to your infra |
-| Migration | — | `bb migrate from-convex` |
-
-**BetterBase gives you Convex simplicity with full SQL power.**
-
----
-
-## Features
+## Key Features
| Feature | Description |
|---------|-------------|
@@ -198,9 +176,56 @@ Your backend runs at `http://localhost:3000`. The dashboard is at `http://localh
---
+## Betterbase vs Convex
+
+| Feature | Convex | Betterbase |
+|---------|--------|------------|
+| Database | Black box | Full PostgreSQL |
+| Raw SQL | Not available | `ctx.db.execute()` |
+| Full-Text Search | Not built-in | PostgreSQL FTS |
+| Vector Search | Limited | pgvector + HNSW |
+| Self-Hosting | Not supported | Docker to your infra |
+| Migration | — | `bb migrate from-convex` |
+
+**Betterbase gives you Convex simplicity with full SQL power.**
+
+---
+
+## Inngest Integration
+
+Betterbase uses [Inngest](https://www.inngest.com/) for durable workflows and background jobs.
+
+### Deployment Modes
+
+| Mode | Inngest Backend | Used By |
+|------|----------------|---------|
+| Cloud | `https://api.inngest.com` | BetterBase Cloud offering |
+| Self-Hosted | `http://inngest:8288` | Docker deployment |
+| Local Dev | `http://localhost:8288` | Development and testing |
+
+### Environment Variables
+
+```bash
+# For local development
+INNGEST_BASE_URL=http://localhost:8288
+
+# For self-hosted production
+INNGEST_BASE_URL=http://inngest:8288
+INNGEST_SIGNING_KEY=your-signing-key
+INNGEST_EVENT_KEY=your-event-key
+```
+
+### Features
+
+- **Webhook Delivery**: Retryable, observable webhook delivery with automatic backoff
+- **Notification Rules**: Cron-based metric polling with fan-out notifications
+- **Background Exports**: Async CSV export with progress tracking
+
+---
+
## Project Structure
-BetterBase supports two patterns:
+Betterbase supports two patterns:
### 1. IaC Pattern (Recommended)
@@ -211,7 +236,7 @@ my-app/
│ ├── queries/ # query() functions
│ ├── mutations/ # mutation() functions
│ ├── actions/ # action() functions
-│ └── cron.ts # scheduled functions
+│ └── cron.ts # scheduled functions
├── betterbase.config.ts # Optional config
└── package.json
```
@@ -225,7 +250,7 @@ my-app/
│ │ ├── schema.ts # Drizzle schema
│ │ └── migrate.ts # Migration runner
│ ├── routes/ # Hono routes
-│ └── functions/ # Serverless functions
+│ └── functions/ # Serverless functions
├── betterbase.config.ts
└── package.json
```
@@ -397,6 +422,28 @@ This ensures users can only access their own data.
---
+## Ask Deepwiki
+
+> *Your AI-powered development assistant, integrated directly into Betterbase.*
+
+Ask Deepwiki provides intelligent context for AI-assisted development:
+
+- **Smart Code Context**: Automatic `.betterbase-context.json` generation
+- **IaC Analysis**: Understand your schema, queries, and mutations
+- **Query Optimization**: Get recommendations for better performance
+- **Documentation Generation**: Auto-generate docs from your code
+
+**Deepwiki Badge**: The badge at the top of this README links to [Ask Deepwiki](https://deepwiki.com/weroperking/Betterbase), where you can chat with an AI that understands your entire Betterbase project.
+
+### Using Ask Deepwiki
+
+1. **Development**: Get instant answers about your IaC layer
+2. **Debugging**: Understand query behavior and optimization
+3. **Onboarding**: New team members can ask about your architecture
+4. **Refactoring**: Get AI suggestions for improving your code
+
+---
+
## Contributing
We welcome contributions! Please follow these steps:
@@ -431,11 +478,11 @@ betterbase/
├── apps/
│ └── test-project/ # Example/test project
├── packages/
-│ ├── cli/ # @betterbase/cli
-│ ├── client/ # @betterbase/client
-│ └── core/ # @betterbase/core
-├── templates/ # Project templates
-└── turbo.json # Turborepo configuration
+│ ├── cli/ # @betterbase/cli
+│ ├── client/ # @betterbase/client
+│ └── core/ # @betterbase/core
+├── templates/ # Project templates
+└── turbo.json # Turborepo configuration
```
### Code Style
@@ -521,6 +568,7 @@ All notable changes to this project will be documented in this section.
### [1.0.0] - 2026-03-19
#### Added
+
- **AI Context Generation**: Automatic `.betterbase-context.json` generation for AI-assisted development
- **Branch Management**: New `bb branch` command for creating isolated preview environments
- **Vector Search**: pgvector-powered similarity search with embeddings support
@@ -528,12 +576,14 @@ All notable changes to this project will be documented in this section.
- **Enhanced CLI**: Added 12 commands including branch, webhook management, and storage operations
#### Updated
+
- Updated copyright year to 2026
- Improved documentation with Last Updated timestamp
- Verified all features against current codebase structure
- Removed deprecated @betterbase/shared package references
#### Security
+
- Improved webhook signature verification
- Enhanced RLS policy engine
@@ -575,26 +625,16 @@ SOFTWARE.
| Resource | Link |
|----------|------|
-| **Documentation** | [docs.betterbase.io](https://docs.betterbase.io) |
-| **Discord** | [discord.gg/betterbase](https://discord.gg/betterbase) |
-| **GitHub Issues** | [github.com/betterbase/betterbase/issues](https://github.com/betterbase/betterbase/issues) |
-| **Stack Overflow** | [stackoverflow.com/questions/tagged/betterbase](https://stackoverflow.com/questions/tagged/betterbase) |
-
-### Stay Updated
-
-| Channel | Link |
-|---------|------|
-| **Twitter** | [@betterbase](https://twitter.com/betterbase) |
-| **Blog** | [blog.betterbase.io](https://blog.betterbase.io) |
-| **Newsletter** | [subscribe.betterbase.io](https://subscribe.betterbase.io) |
+| **Discord** | [Discord](https://discord.gg/R6Dm6Cgy2E) |
+| **GitHub Issues** | [GitHub Issues](https://github.com/weroperking/Betterbase/issues) |
### Contribute
| Resource | Link |
|----------|------|
-| **GitHub** | [github.com/betterbase/betterbase](https://github.com/betterbase/betterbase) |
+| **GitHub** | [GitHub](https://github.com/weroperking/Betterbase) |
| **Contributing Guide** | [CONTRIBUTING.md](CONTRIBUTING.md) |
-| **Good First Issues** | [github.com/betterbase/betterbase/labels/good%20first%20issue](https://github.com/betterbase/betterbase/labels/good%20first%20issue) |
+| **Good First Issues** | [Good First Issues](https://github.com/weroperking/Betterbase/labels/good-first-issue) |
---
@@ -602,6 +642,6 @@ SOFTWARE.
**Built with ❤️ by Weroperking**
-[Website](https://betterbase.io) • [Documentation](https://docs.betterbase.io) • [Discord](https://discord.gg/betterbase) • [Twitter](https://twitter.com/betterbase)
+[Website](#) • [Documentation](docs/README.md) • [Discord](https://discord.gg/R6Dm6Cgy2E) • [GitHub](https://github.com/weroperking/Betterbase) • [Twitter](#)
-
+
\ No newline at end of file
diff --git a/apps/dashboard/Dockerfile b/apps/dashboard/Dockerfile
index 5cf0545..45e3c23 100644
--- a/apps/dashboard/Dockerfile
+++ b/apps/dashboard/Dockerfile
@@ -10,9 +10,9 @@
FROM oven/bun:1.3.9-debian AS builder
-WORKDIR /app
+WORKDIR /app/apps/dashboard
-COPY package.json bun.lock* ./
+COPY apps/dashboard/package.json apps/dashboard/bun.lock* ./
RUN bun install --frozen-lockfile
@@ -25,7 +25,11 @@ RUN bun run build
FROM nginx:alpine
-COPY --from=builder /app/dist /usr/share/nginx/html
+RUN addgroup -g 101 -S nginx && adduser -S nginx -u 101
+
+COPY --from=builder /app/apps/dashboard/dist /usr/share/nginx/html
+
+RUN chown -R nginx:nginx /usr/share/nginx/html
RUN cat > /etc/nginx/conf.d/default.conf << 'EOF'
server {
@@ -34,15 +38,24 @@ server {
root /usr/share/nginx/html;
index index.html;
+ # Health check endpoint
+ location /health {
+ return 200 'OK';
+ add_header Content-Type text/plain;
+ }
+
+ # Cache static assets
location /assets/ {
expires 1y;
add_header Cache-Control "public, immutable";
}
+ # SPA fallback - all routes go to index.html
location / {
try_files $uri $uri/ /index.html;
}
+ # Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
}
@@ -50,4 +63,8 @@ EOF
EXPOSE 80
+HEALTHCHECK --interval=10s --timeout=5s --start-period=10s --retries=3 CMD wget -qO- http://localhost:80/health || exit 1
+
+USER nginx
+
CMD ["nginx", "-g", "daemon off;"]
\ No newline at end of file
diff --git a/docker-compose.production.yml b/docker-compose.production.yml
index 7c1fdf6..c6d913e 100644
--- a/docker-compose.production.yml
+++ b/docker-compose.production.yml
@@ -1,163 +1,132 @@
# ============================================================================
# Betterbase Production Docker Compose
#
-# Production-ready configuration with:
-# - PostgreSQL (managed externally or via this compose)
-# - S3-compatible storage (Cloudflare R2, MinIO, etc.)
-# - Health checks
-# - Proper security settings
+# Production-ready configuration with all services.
+# Requires .env file with proper values.
#
# Usage:
-# docker-compose -f docker-compose.production.yml up -d
-#
-# For production, it's recommended to:
-# 1. Use external managed database (Neon, Supabase, RDS, etc.)
-# 2. Use external S3 storage (R2, S3, B2)
-# 3. Use a reverse proxy (Caddy, Nginx, Traefik)
-# 4. Enable SSL/TLS
+# cp .env.example .env
+# # Edit .env with your values
+# docker compose -f docker-compose.production.yml up -d
# ============================================================================
services:
- # --------------------------------------------------------------------------
- # Betterbase Application
- # --------------------------------------------------------------------------
- app:
- build:
- context: .
- dockerfile: Dockerfile.project
- args:
- # Build arguments
- NODE_ENV: production
- expose:
- - "3000"
+ postgres:
+ image: postgres:16-alpine
+ container_name: betterbase-postgres
+ restart: unless-stopped
environment:
- # Database - UPDATE THIS for your managed PostgreSQL
- DATABASE_URL: ${DATABASE_URL}
-
- # Auth - IMPORTANT: Generate a secure secret in production
- AUTH_SECRET: ${AUTH_SECRET}
- AUTH_URL: ${AUTH_URL:-https://your-domain.com}
-
- # Storage - S3-compatible
- STORAGE_PROVIDER: ${STORAGE_PROVIDER:-r2}
- STORAGE_BUCKET: ${STORAGE_BUCKET:-betterbase-storage}
- STORAGE_REGION: ${STORAGE_REGION:-auto}
- # For R2/S3-compatible
- STORAGE_ENDPOINT: ${STORAGE_ENDPOINT:-https://your-r2-endpoint.r2.cloudflarestorage.com}
- STORAGE_ACCESS_KEY_ID: ${STORAGE_ACCESS_KEY_ID}
- STORAGE_SECRET_ACCESS_KEY: ${STORAGE_SECRET_ACCESS_KEY}
-
- # Node environment
- NODE_ENV: production
- PORT: "3000"
- HOST: "0.0.0.0"
-
- # Security
- CORS_ORIGIN: ${CORS_ORIGIN:-https://your-domain.com}
-
- # Optional: Logging
- LOG_LEVEL: ${LOG_LEVEL:-info}
-
- restart: always
+ POSTGRES_USER: ${POSTGRES_USER:-betterbase}
+ POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-betterbase}
+ POSTGRES_DB: ${POSTGRES_DB:-betterbase}
+ volumes:
+ - postgres_data:/var/lib/postgresql/data
healthcheck:
- test: ["CMD", "curl", "-f", "http://localhost:3000/api/health"]
- interval: 30s
- timeout: 10s
- retries: 3
- start_period: 40s
+ test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-betterbase}"]
+ interval: 10s
+ timeout: 5s
+ retries: 5
networks:
- - betterbase-prod
+ - betterbase-network
- # --------------------------------------------------------------------------
- # Optional: Self-hosted PostgreSQL (if not using managed)
- # Remove this service if using Neon, Supabase, RDS, etc.
- # --------------------------------------------------------------------------
- # postgres:
- # image: postgres:16-alpine
- # environment:
- # POSTGRES_USER: ${DB_USER:-betterbase}
- # POSTGRES_PASSWORD: ${DB_PASSWORD}
- # POSTGRES_DB: ${DB_NAME:-betterbase}
- # volumes:
- # - postgres_data:/var/lib/postgresql/data
- # restart: always
- # healthcheck:
- # test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-betterbase} -d ${DB_NAME:-betterbase}"]
- # interval: 10s
- # timeout: 5s
- # retries: 5
- # networks:
- # - betterbase-prod
- # # Only expose ports if needed for debugging
- # # ports:
- # # - "5432:5432"
+ minio:
+ image: minio/minio:latest
+ container_name: betterbase-minio
+ restart: unless-stopped
+ command: server /data --console-address ":9001"
+ environment:
+ MINIO_ROOT_USER: ${STORAGE_ACCESS_KEY:-minioadmin}
+ MINIO_ROOT_PASSWORD: ${STORAGE_SECRET_KEY:-minioadmin}
+ volumes:
+ - minio_data:/data
+ healthcheck:
+ test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
+ interval: 10s
+ timeout: 5s
+ retries: 5
+ networks:
+ - betterbase-network
- # --------------------------------------------------------------------------
- # Optional: MinIO for self-hosted S3 storage
- # Remove this service if using R2, S3, B2
- # --------------------------------------------------------------------------
- # minio:
- # image: minio/minio:latest
- # command: server /data --console-address ":9001"
- # environment:
- # MINIO_ROOT_USER: ${MINIO_ROOT_USER}
- # MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
- # volumes:
- # - minio_data:/data
- # restart: always
- # networks:
- # - betterbase-prod
+ minio-init:
+ image: minio/mc:latest
+ container_name: betterbase-minio-init
+ depends_on:
+ minio:
+ condition: service_healthy
+ entrypoint: >
+ /bin/sh -c "
+ mc alias set local http://minio:9000 ${STORAGE_ACCESS_KEY:-minioadmin} ${STORAGE_SECRET_KEY:-minioadmin};
+ mc mb --ignore-existing local/betterbase;
+ echo 'MinIO bucket initialized.';
+ "
+ networks:
+ - betterbase-network
- # --------------------------------------------------------------------------
- # Optional: Traefik reverse proxy (uncomment for automatic HTTPS)
- # --------------------------------------------------------------------------
- # traefik:
- # image: traefik:v3.0
- # command:
- # - "--api.insecure=true"
- # - "--providers.docker=true"
- # - "--providers.docker.exposedbydefault=false"
- # - "--entrypoints.web.address=:80"
- # - "--entrypoints.websecure.address=:443"
- # - "--certificatesresolvers.letsencrypt.acme.email=your@email.com"
- # - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
- # - "--certificatesresolvers.letsencrypt.acme.tlschallenge=true"
- # ports:
- # - "80:80"
- # - "443:443"
- # - "8080:8080"
- # volumes:
- # - /var/run/docker.sock:/var/run/docker.sock:ro
- # - letsencrypt_data:/letsencrypt
- # networks:
- # - betterbase-prod
+ inngest:
+ image: inngest/inngest:v1.17.5
+ container_name: betterbase-inngest
+ restart: unless-stopped
+ command: inngest dev --host 0.0.0.0 --port 8288
+ environment:
+ INNGEST_LOG_LEVEL: ${INNGEST_LOG_LEVEL:-info}
+ volumes:
+ - inngest_data:/data
+ networks:
+ - betterbase-network
- # --------------------------------------------------------------------------
- # Optional: Caddy reverse proxy (simpler than Traefik)
- # --------------------------------------------------------------------------
- # caddy:
- # image: caddy:2-alpine
- # volumes:
- # - ./Caddyfile:/etc/caddy/Caddyfile
- # - caddy_data:/data
- # ports:
- # - "80:80"
- # - "443:443"
- # networks:
- # - betterbase-prod
+ betterbase-server:
+ build:
+ context: .
+ dockerfile: packages/server/Dockerfile
+ container_name: betterbase-server
+ restart: unless-stopped
+ depends_on:
+ postgres:
+ condition: service_healthy
+ minio:
+ condition: service_healthy
+ minio-init:
+ condition: service_completed_successfully
+ inngest:
+ condition: service_started
+ environment:
+ DATABASE_URL: postgresql://${POSTGRES_USER:-betterbase}:${POSTGRES_PASSWORD:-betterbase}@postgres:5432/${POSTGRES_DB:-betterbase}
+ AUTH_SECRET: ${AUTH_SECRET:-change-this-in-production}
+ AUTH_URL: ${AUTH_URL:-http://localhost:3000}
+ STORAGE_ENDPOINT: http://minio:9000
+ STORAGE_ACCESS_KEY: ${STORAGE_ACCESS_KEY:-minioadmin}
+ STORAGE_SECRET_KEY: ${STORAGE_SECRET_KEY:-minioadmin}
+ STORAGE_BUCKET: betterbase
+ PORT: "3001"
+ NODE_ENV: production
+ CORS_ORIGIN: ${CORS_ORIGIN:-http://localhost}
+ INNGEST_BASE_URL: http://inngest:8288
+ INNGEST_SIGNING_KEY: ${INNGEST_SIGNING_KEY:-}
+ INNGEST_EVENT_KEY: ${INNGEST_EVENT_KEY:-}
+ healthcheck:
+ test: ["CMD-SHELL", "wget -qO- http://localhost:3001/health || exit 1"]
+ interval: 10s
+ timeout: 5s
+ retries: 5
+ networks:
+ - betterbase-network
-# ----------------------------------------------------------------------------
-# Networks
-# ----------------------------------------------------------------------------
-networks:
- betterbase-prod:
- driver: bridge
+ dashboard:
+ image: nginx:alpine
+ container_name: betterbase-dashboard
+ restart: unless-stopped
+ volumes:
+ - ./apps/dashboard/dist:/usr/share/nginx/html:ro
+ depends_on:
+ - betterbase-server
+ networks:
+ - betterbase-network
-# ----------------------------------------------------------------------------
-# Volumes
-# ----------------------------------------------------------------------------
volumes:
- # postgres_data:
- # minio_data:
- # letsencrypt_data:
- # caddy_data:
+ postgres_data:
+ minio_data:
+ inngest_data:
+
+networks:
+ betterbase-network:
+ driver: bridge
\ No newline at end of file
diff --git a/docker-compose.self-hosted.yml b/docker-compose.self-hosted.yml
index f792916..e2ad9cd 100644
--- a/docker-compose.self-hosted.yml
+++ b/docker-compose.self-hosted.yml
@@ -5,16 +5,18 @@
# No external dependencies required.
#
# Usage:
-# 1. Build: bun run build
-# 2. cp .env.example .env && edit .env
-# 3. docker compose -f docker-compose.self-hosted.yml up -d
+# 1. Build the dashboard: bun --cwd apps/dashboard run build
+# (Produces ./apps/dashboard/dist - required before starting)
+# 2. Build the server: bun run build
+# 3. cp .env.example .env
+# 4. docker compose -f docker-compose.self-hosted.yml up -d
#
# Services:
-# - PostgreSQL: localhost:5432
-# - MinIO: localhost:9000 (console: localhost:9001)
-# - Inngest: localhost:8288
-# - Server: localhost:3001
-# - Dashboard: localhost (via nginx)
+# - PostgreSQL: http://localhost:5432
+# - MinIO: http://localhost:9000 (console: http://localhost:9001)
+# - Inngest: http://localhost:8288
+# - Server: http://localhost:3000
+# - Dashboard: http://localhost:3000 (root)
# ============================================================================
services:
@@ -37,7 +39,7 @@ services:
- betterbase-internal
minio:
- image: minio/minio:latest
+ image: minio/minio:RELEASE.2024-11-07T19-31-41Z
container_name: betterbase-minio
restart: unless-stopped
command: server /data --console-address ":9001"
@@ -55,7 +57,7 @@ services:
- betterbase-internal
minio-init:
- image: minio/mc:latest
+ image: minio/mc:RELEASE.2024-11-08T03-47-05Z
container_name: betterbase-minio-init
depends_on:
minio:
@@ -98,8 +100,8 @@ services:
condition: service_started
environment:
DATABASE_URL: postgresql://${POSTGRES_USER:-betterbase}:${POSTGRES_PASSWORD:-betterbase}@postgres:5432/${POSTGRES_DB:-betterbase}
- AUTH_SECRET: ${AUTH_SECRET:?JWT secret required - set AUTH_SECRET in .env}
- AUTH_URL: ${AUTH_URL:-http://localhost:3000}
+ BETTERBASE_JWT_SECRET: ${BETTERBASE_JWT_SECRET:?JWT secret required - set BETTERBASE_JWT_SECRET in .env}
+ BETTERBASE_PUBLIC_URL: ${BETTERBASE_PUBLIC_URL:-http://localhost:3000}
STORAGE_ENDPOINT: http://minio:9000
STORAGE_ACCESS_KEY: ${MINIO_ROOT_USER:-minioadmin}
STORAGE_SECRET_KEY: ${MINIO_ROOT_PASSWORD:-minioadmin}
diff --git a/docker-compose.yml b/docker-compose.yml
index e76a2c1..111aa14 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -5,7 +5,7 @@
# Betterbase server runs locally with hot-reload.
#
# Usage:
-# docker compose up -d
+# docker compose up -d postgres minio inngest
# bun run dev
# ============================================================================
@@ -36,8 +36,8 @@ services:
restart: unless-stopped
command: server /data --console-address ":9001"
environment:
- MINIO_ROOT_USER: betterbase
- MINIO_ROOT_PASSWORD: betterbase_dev_password
+ MINIO_ROOT_USER: ${MINIO_ROOT_USER:-betterbase}
+ MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-betterbase_dev_password}
ports:
- "9000:9000"
- "9001:9001"
@@ -49,6 +49,20 @@ services:
timeout: 5s
retries: 5
+ # MinIO Init (Create bucket on startup)
+ minio-init:
+ image: minio/mc:latest
+ container_name: betterbase-minio-init-local
+ depends_on:
+ minio:
+ condition: service_healthy
+ entrypoint: >
+ /bin/sh -c "
+ mc alias set local http://minio:9000 ${MINIO_ROOT_USER:-betterbase} ${MINIO_ROOT_PASSWORD:-betterbase_dev_password};
+ mc mb --ignore-existing local/betterbase;
+ echo 'MinIO bucket initialized.';
+ "
+
# Inngest (Durable Workflow Engine)
inngest:
image: inngest/inngest:v1.17.5
diff --git a/docs/docker-setup.md b/docs/docker-setup.md
index 8148b17..88c0a43 100644
--- a/docs/docker-setup.md
+++ b/docs/docker-setup.md
@@ -68,7 +68,7 @@ INNGEST_EVENT_KEY=$(openssl rand -hex 16)
|---------|-----|--------------|
| Betterbase API | http://localhost | Through nginx |
| Dashboard | http://localhost | Admin login |
-| MinIO Console | http://localhost:9001 | minioadmin/minioadmin_password |
+| MinIO Console | http://localhost:9001 | Local dev: `betterbase/betterbase_dev_password`
Self-hosted: `minioadmin/minioadmin` |
## Common Issues
@@ -87,8 +87,12 @@ docker compose logs postgres
The `minio-init` service creates the bucket automatically. If it fails:
```bash
-# Manually create bucket
-docker compose exec minio mc alias set local http://localhost:9000 minioadmin minioadmin_password
+# For local development (docker-compose.yml)
+docker compose exec minio mc alias set local http://localhost:9000 betterbase betterbase_dev_password
+docker compose exec minio mc mb local/betterbase
+
+# For self-hosted (docker-compose.self-hosted.yml)
+docker compose exec minio mc alias set local http://localhost:9000 minioadmin minioadmin
docker compose exec minio mc mb local/betterbase
```
@@ -154,4 +158,16 @@ docker compose up -d --build betterbase-server
| Database | Docker PostgreSQL | Docker or managed |
| Storage | Docker MinIO | Docker, R2, S3, or B2 |
| SSL/TLS | Not needed | Required (use Traefik/Caddy) |
-| Inngest | Dev mode | Production mode |
\ No newline at end of file
+| Inngest | Dev mode | Production mode |
+
+## Alternative: External Services
+
+Instead of running everything with Docker, you can use managed services:
+
+```yaml
+# docker-compose.production.yml
+# Use external PostgreSQL (Neon, Supabase, RDS)
+# Use external storage (Cloudflare R2, AWS S3)
+```
+
+See `docker-compose.production.yml` for a configuration that assumes external services.
diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md
index 6219169..6482dce 100644
--- a/docs/getting-started/installation.md
+++ b/docs/getting-started/installation.md
@@ -49,6 +49,12 @@ docker --version
docker compose version
```
+Verify the installation:
+
+```bash
+bun --version
+```
+
## Installing BetterBase CLI
The BetterBase CLI (`bb`) is your primary tool for managing projects and deployments.
@@ -122,7 +128,7 @@ bun run dev
This creates the following project structure:
-```
+```text
betterbase/
├── packages/
│ ├── core/ # Core framework
diff --git a/packages/server/Dockerfile b/packages/server/Dockerfile
index 53a5941..9a74de5 100644
--- a/packages/server/Dockerfile
+++ b/packages/server/Dockerfile
@@ -4,6 +4,7 @@ WORKDIR /app
RUN apk add --no-cache git
+# Copy monorepo structure (only what server needs)
COPY package.json turbo.json bun.lock ./
COPY packages/server/package.json ./packages/server/
COPY packages/core/package.json ./packages/core/
@@ -18,11 +19,12 @@ COPY tsconfig.base.json ./
RUN cd packages/server && bun build src/index.ts --outdir dist --target bun
+# --- Runtime stage ---
FROM oven/bun:1.3.9-alpine
WORKDIR /app
-RUN apk add --no-cache wget
+RUN apk add --no-cache wget=1.25.0-r1
COPY --from=builder /app/packages/server/dist ./dist