A full-stack travel application with a Go backend and Next.js frontend, orchestrated with Tilt and backed by PostgreSQL.
The easiest way to run the entire stack is using Tilt.
- Docker & Docker Compose
- Tilt
- Go 1.21+ (for local builds)
- Node.js 18+ (for local frontend installs)
Simply run:
tilt upThis will:
- Spin up a PostgreSQL 15 container.
- Build and start the Go Backend (port 8080).
- Install and start the Next.js Frontend (port 3000).
- Automatically run Goose migrations to set up the database schema.
beyond/
├── backend/ # Go backend API
│ ├── cmd/server/ # Entry point (main.go)
│ ├── internal/
│ │ ├── data/ # DB logic & migrations (Goose)
│ │ ├── handlers/ # API endpoints
│ │ └── middleware/ # Shared logic (CORS)
├── frontend/ # Next.js Application
├── docker-compose.yml # Infrastructure (Postgres)
└── Tiltfile # Dev orchestration
We use PostgreSQL for storage. Migrations in backend/internal/data/migrations run automatically via Goose on startup.
Quick Commands:
- Explore DB:
docker exec -it beyond-db-1 psql -U beyond -d beyond(or connect your local tools directly topostgres://beyond:password@localhost:5432/beyond) - Reset DB:
docker-compose down -vto wipe the database volume.
The backend uses Supabase for secure authentication.
- JWT Verification: The backend dynamically fetches Supabase's Public Keys (JWKS) via OIDC discovery.
- Required Header: All protected endpoints require a
Bearertoken in theAuthorizationheader.Authorization: Bearer <your-supabase-jwt>
- User Scoping: The
subclaim (User ID) from the JWT is used to scope all database queries, ensuring users only access their own data.
GET /api/trips- List all user tripsPOST /api/trips- Create a new tripGET /api/trips/{id}- Get a specific trip and its checkpointsPUT /api/trips/{id}- Update a specific tripDELETE /api/trips/{id}- Delete a specific tripPOST /api/trips/{id}/checkpoints- Add a checkpoint to a trip
PUT /api/checkpoints/{id}- Update a checkpointDELETE /api/checkpoints/{id}- Delete a checkpoint
GET /api/plans- List all user planning sessionsPOST /api/plans- Create a new planning sessionGET /api/plans/{id}- Get plan details (including days and items)PUT /api/plans/{id}- Update plan metadataDELETE /api/plans/{id}- Delete a planPOST /api/plans/{id}/days- Add a new day to a planDELETE /api/plans/days/{id}- Remove a day from a planPOST /api/plans/{id}/items- Add an item (activity/flight/etc) to a plan dayPUT /api/plans/items/{id}- Update a plan itemDELETE /api/plans/items/{id}- Remove a plan itemPOST /api/plans/{id}/convert- Finalize! Convert a plan into a real Trip
POST /api/upload- Upload an image (Multipart Form, returns S3/MinIO URL)GET /api/image/{id}- Placeholder SVG generator (Public)
The backend requires the following variables (provided by Tilt in dev):
DATABASE_URL: Connection string for PostgreSQL.SUPABASE_URL: Your Supabase Project URL (for OIDC discovery).MINIO_ENDPOINT: MinIO server for file storage.MINIO_USER/MINIO_PASSWORD: MinIO credentials.MINIO_PUBLIC_URL: Public-facing URL for serving uploaded images.