Trip planner web app for group travel
9.4K
A full-stack PWA for collaborative group trip planning. Built for a Japan 2026 trip but easily configurable for any destination.
Core
Modules
Infrastructure
# Frontend
npm install
npm run dev # http://localhost:5173
# Backend (separate terminal)
cd server
npm install
npm start # http://localhost:3001
docker compose up -d
Or standalone:
docker run -d \
-p 3001:3001 \
-v trip-data:/app/server/data \
monxas/trip-planner:latest
The container serves both the API and the built frontend on port 3001.
Healthcheck: GET /api/health
┌─────────────────────────────────┐
│ React 19 SPA (Vite 7 build) │
│ TailwindCSS v4 + Lucide icons │
├─────────────────────────────────┤
│ Service Worker (vite-plugin-pwa)│
│ NetworkFirst: /api/* │
│ CacheFirst: tiles, photos │
├─────────────────────────────────┤
│ Express API (Node.js) │
│ SSE for real-time sync │
│ SQLite (better-sqlite3) │
└─────────────────────────────────┘
Auth model: Trip tokens grant full access; read-only tokens allow viewing without modification. Tokens are shared via QR code or link.
Enterprise-grade testing infrastructure with comprehensive coverage:
npm test # Run all tests
npm run test:watch # Watch mode
npm run test:coverage # Coverage report
npm run test:ci # CI mode (verbose + coverage)
src/
├── components/
│ ├── ui/ # Button, IconButton, Input, Select, Card, Badge, Toggle, Avatar
│ ├── map/ # CityFilterBar, FilterBar, MarkerPopup, icons, geocoding
│ ├── onboarding/ # InstallStep, AuthStep, CreateTrip, JoinTrip, Flights, Tutorial
│ ├── places/ # PlaceCard, PlaceDetails, PlaceNotes, PlaceSearch
│ ├── itinerary/ # AccordionView, EventCard, TransitIndicator, SortableEventCard
│ └── ... # Dashboard, Hotels, Translator, PackingList, Settings
├── store/ # 6 modular stores (trip, places, events, hotels, flights, packing)
├── hooks/ # useCurrentLocation, useKeyboardVisible, useInstallPrompt, etc.
├── utils/ # transit.ts, ics.ts, distance.ts
└── services/ # API client
server/
├── index.js # Express server + all routes
├── db.js # SQLite setup + migrations
├── seed.js # Initial data
├── scripts/ # backup-db.sh (daily cron, 7-day retention)
└── .env # VAPID keys, Google API key, config
Server (server/.env)
| Variable | Description |
|---|---|
PORT | Server port (default: 3001) |
VAPID_PUBLIC_KEY | Web push public key |
VAPID_PRIVATE_KEY | Web push private key |
VAPID_EMAIL | Contact email for VAPID |
GOOGLE_PLACES_API_KEY | Google Places API key |
Frontend (compile-time via Vite)
| Variable | Description |
|---|---|
VITE_API_URL | Backend URL (default: same origin) |
VITE_VAPID_PUBLIC_KEY | Web push public key (client-side) |
lint + build via GitHub Actions (ci.yml)master triggers a GitHub webhook → deploy-webhook container on the media server pulls, builds, and deploys the Docker container automaticallyNo SSH keys or self-hosted runners involved.
| Layer | Technology |
|---|---|
| Frontend | React 19, TypeScript 5.9, Vite 7, TailwindCSS v4 |
| UI | Lucide icons, dnd-kit, Leaflet + react-leaflet, QR code generation |
| Backend | Node.js, Express, better-sqlite3, web-push |
| Real-time | Server-Sent Events (SSE) |
| PWA | vite-plugin-pwa, Workbox strategies |
| External APIs | Google Places, FlightRadar24 (scraping), fawazahmed0/exchange-api |
| Infra | Docker, GitHub Actions |
Intentionally omitted. Dedicated apps do this better:
Keeping the app focused on planning, not accounting.
MIT License
Content type
Image
Digest
sha256:217774c57…
Size
140.7 MB
Last updated
about 1 hour ago
docker pull monxas/trip-planner