Plan it together, properly.
Junto is a real-time collaborative trip planning app. Groups propose places, vote on them, split costs, and discuss decisions — all in a shared itinerary that updates for everyone the moment anyone changes it.
- Shared Itinerary — Organize days, time slots, and activities with drag-and-drop ordering via fractional indexing.
- Propose & Vote — Anyone can suggest options for a slot; the group votes, and an organizer makes the final call.
- Live Presence & Real-time Sync — WebSocket-powered updates: see who's online, watch votes and comments appear instantly across browsers.
- Budget & Split — Track expenses, assign payers, split costs per-person, and see who owes whom with minimum-transfer settlement.
- Invite by Email — Token-based invitations with role-based access (editor/viewer).
- Memories — After the trip, browse every decision the group settled on, organized by day.
- File Attachments — S3-compatible presigned uploads (MinIO locally, S3/R2 in production).
- Auth — Email/password with Argon2id hashing, JWT access/refresh tokens, email verification, and password reset.
| Itinerary | Voting & Discussion | Budget |
|---|---|---|
![]() |
![]() |
![]() |
| Trip Home | Memories |
|---|---|
![]() |
![]() |
| Layer | Technology |
|---|---|
| Backend | Go 1.26, Chi router, pgx (PostgreSQL), Redis pub/sub |
| Frontend | Next.js 16, React 19, TypeScript, Tailwind CSS 4 |
| Database | PostgreSQL 16 (migrations via golang-migrate) |
| Real-time | WebSockets with ticket-based auth, Redis fan-out for multi-instance |
| Storage | MinIO / S3 / Cloudflare R2 (presigned uploads) |
| Auth | JWT (HS256), Argon2id password hashing, secure session management |
| SMTP (Mailpit locally, any provider in production) | |
| Deploy | Docker (multi-stage scratch image), Render, Vercel |
- Docker (for Postgres, Redis, MinIO, Mailpit)
- Go 1.26+
- Node.js 20+
git clone https://github.com/Sachith77/Junto.git
cd Junto
cp .env.example .envdocker compose up -dThis brings up:
| Service | Port |
|---|---|
| PostgreSQL | localhost:5433 |
| Redis | localhost:6380 |
| MinIO (S3) | localhost:9000 (API), localhost:9001 (console) |
| Mailpit | localhost:1025 (SMTP), localhost:8025 (UI) |
go run ./cmd/migrate upgo run ./cmd/apiAPI is now at http://localhost:8080
cd web
npm install
npm run devApp is now at http://localhost:3000
cd web
npm run seedThis creates three demo accounts and a sample trip with itinerary, votes, comments, and budget entries.
Demo Accounts:
| Name | Password | |
|---|---|---|
| Alice Moreau | alice@junto.local |
correct horse battery staple |
| Bruno Alves | bruno@junto.local |
correct horse battery staple |
| Mira Sethi | mira@junto.local |
correct horse battery staple |
.
├── cmd/
│ ├── api/ # HTTP + WebSocket server entrypoint
│ └── migrate/ # Database migration CLI
├── internal/
│ ├── domain/ # Core types and interfaces
│ ├── service/ # Business logic layer
│ ├── repository/ # PostgreSQL queries (sqlc-generated)
│ ├── transport/
│ │ ├── http/ # REST API handlers (Chi)
│ │ └── ws/ # WebSocket connection management
│ ├── syncengine/ # Real-time operation broadcast & rooms
│ ├── pubsub/ # Redis pub/sub abstraction
│ ├── security/ # JWT, Argon2id, rate limiting
│ ├── email/ # SMTP email sending
│ ├── storage/ # S3/MinIO object storage
│ └── middleware/ # Auth, CORS, request logging
├── migrations/ # SQL migration files (embedded at build)
├── tests/ # Integration tests (testcontainers)
├── web/ # Next.js frontend
│ ├── app/ # App router pages
│ ├── components/ # React components
│ ├── lib/ # API client, WebSocket client, utilities
│ ├── context/ # Auth & sync React contexts
│ └── e2e/ # Playwright end-to-end tests
├── docker-compose.yml # Local dev infrastructure
├── Dockerfile # Multi-stage production build (scratch)
└── render.yaml # Render deployment blueprint
# Go unit & integration tests
go test ./...
# Go tests with race detector (what CI runs)
go test ./... -race
# Frontend unit tests
cd web && npm test
# End-to-end tests (requires running API + frontend)
cd web && npm run test:e2eThe API ships as a static Go binary in a scratch Docker image. See docs/deploy.md for the full deployment guide covering Render, secrets configuration, and migration procedures.
This project is for educational and portfolio purposes.





