尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證正在載入完整 README。 以下為已儲存的摘錄。
A full-stack trip-planning app: travelers build day-by-day itineraries from a shared,
crowdsourced attraction database, schedule them on a per-day calendar (including flights,
accommodation stays, and free-form time slots), track a multi-currency budget, and
collaborate on a trip with other users.
Live app: https://trip-planner-beta-dusky.vercel.app/
API docs: /api-docs (Swagger UI) — see also swagger.yaml
See also: SPEC.md (system spec, ERD, full endpoint table), PRD.md
(product requirements), DESIGN.md, FLOWS.md,
WIREFRAMES.md, PRESENTATION.md.檢視完整 README ↗A full-stack trip-planning app: travelers build day-by-day itineraries from a shared, crowdsourced attraction database, schedule them on a per-day calendar (including flights, accommodation stays, and free-form time slots), track a multi-currency budget, and collaborate on a trip with other users.
Live app: https://trip-planner-beta-dusky.vercel.app/
API docs: /api-docs (Swagger UI) — see also swagger.yaml
See also: SPEC.md (system spec, ERD, full endpoint table), PRD.md
(product requirements), DESIGN.md, FLOWS.md,
WIREFRAMES.md, PRESENTATION.md.
TripPlanner is built around one idea: attractions are global, shared, crowdsourced objects (name, location, category, "mood" tags), while trips are where an attraction gets a schedule (planned date/time, duration, and — for residences — trip-specific stay dates and price). The same museum can be linked into many different users' trips without duplicating its data; only the per-trip scheduling is trip-specific.
Core features:
CalendarSection) that places
attractions, flights, and free-form time slots on a timeline, including overnight-spanning
blocks (e.g. a hotel stay or overnight flight) and an auto-fit day window.Attraction document, while
stay dates/price/notes live on the trip's schedule entry so the same residence can be
reused across trips with different dates each time./analytics page./admin,
restricted to users with role: "admin".Next.js 16 (App Router) serves as both frontend and backend — there is no separate
Node server. Pages under src/app/** are the frontend; route handlers under
src/app/api/** are the REST API, backed by MongoDB via Mongoose. See
PRESENTATION.md for the full architecture writeup.
DESIGN.md), Context API for auth/attraction-taxonomy state, Leaflet for
maps.api/trips, api/attractions, api/auth, api/users, api/attraction-types,
api/attraction-categories, api/mood-tags, api/analytics, api/explore, plus
api/geo and api/route proxies for map boundary/routing lookups). Business logic for
the two largest domains (trips, attractions) lives in src/lib/services/; every route is
wrapped in a shared error-handling/logging/CORS layer (src/lib/withApiHandler.ts).src/models/*.ts). See SPEC.md for the
full ERD.jsonwebtoken) + bcrypt-hashed passwords (bcryptjs). Sessions are a
7-day JWT in Authorization: Bearer <token>; there is no server-side session store.Map features are built from four external services, proxied through Next.js API routes
(api/geo/*, api/route/*) to avoid CORS and to attach required headers (e.g. a custom
User-Agent, which these free public instances require):
GET /api/geo/city and GET /api/geo/country
(src/app/api/geo/{city,country}/route.ts).GET /api/route/valhalla (src/app/api/route/valhalla/route.ts), which actually calls
OSRM instances at routing.openstreetmap.de (the public Valhalla demo is unreliable).
Returns turn-by-turn geometry and duration.GET /api/route/transit (src/app/api/route/transit/route.ts). Returns
itineraries with per-leg transit lines and encoded polylines; falls back to Valhalla
walk, then car, when no transit route is available.Client-side consumers: src/services/geo.service.ts (boundaries) and
src/services/routeTransit.service.ts (point-to-point routing, exposing fetchRouteLeg
and fetchAirportLeg).
User 1──N Trip (owner) Trip N──N User (collaborators)
Trip N──N Attraction (attractionIds, shared/global entity)
Trip 1──N ScheduleEntry (Trip.schedules — keyed by attractionId, or a synthetic
"cs-*"/"fl-*" id for schedule-only custom-slots/flights)
Attraction N──N AttractionType ──1 AttractionCategory
Full field-level ERD: SPEC.md.
npm install
cp .env.example .env.local # then fill in the values below
npm run dev
Open http://localhost:3000.
See .env.example — the app reads exactly these:
| Variable | Required | Description |
|---|---|---|
MONGODB_URI | Yes | MongoDB connection string. Read at import time by src/lib/mongoose.ts — the app throws on startup if missing. |
JWT_SECRET | Yes | Secret used to sign/verify session JWTs (src/lib/auth.ts). |
ALLOWED_ORIGINS | No | Comma-separated extra origins allowed to call the API cross-origin (src/lib/cors.ts). Empty = same-origin only (the default; the app serves its own frontend and API). |
Attraction categories, attraction types, and mood tags are shared reference data (used to tag attractions and trips). Two admin-only endpoints seed sensible defaults on a fresh database — call them once, authenticated as an admin user:
POST /api/mood-tags/seedPOST /api/attraction-categories/seed-from-types| Command | What it does |
|---|---|
npm run dev | Start the Next.js dev server |
npm run build | Production build (also type-checks) |
npm run start | Run the production build |
npm run lint | ESLint |
MONGODB_URI and
JWT_SECRET as project environment variables.Dockerfile and
render.yaml are included for deploying to Render/Railway/Fly.io instead.
next.config.ts sets output: "standalone" to keep the Docker image minimal.Full OpenAPI 3.0 spec: swagger.yaml, served live at
/api-docs via Swagger UI
(src/app/api-docs/, backed by GET /api/openapi). See SPEC.md
for a condensed endpoint table.
Commit history to date is linear on master (no feature-branch/PR workflow has been used
yet) — noted here rather than glossed over, since accurate documentation matters more than
a tidy story.