リポジトリ情報はまだ収集していません。
No updates detected yet. GitHub releases will appear here.
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗Meri is a personal outdoor intelligence companion: a Next.js PWA where a Journey starts from one sentence of natural language and stays useful as the plan gets clearer.
The product goals and principles live in docs/PROJECT.md. The layer contracts and request flows live in docs/ARCHITECTURE.md. This file covers how to run the project and how to find your way around it.
The complete Chinese directory/layer and file guide lives in docs/CODEBASE_GUIDE.md. Detailed user operations, state changes, APIs, and failure boundaries live in docs/USER_FLOW_CURRENT.md. The database table/field directory and relationships live in docs/DATABASE_SCHEMA.md.
npm install
cp .env.example .env.local # then fill in the values below
npm run dev
Open http://localhost:3000.
Every variable is server-side only. None of them may use the NEXT_PUBLIC_
prefix, because that would ship the value to the browser.
Required:
| Variable | Used for |
|---|---|
MOONSHOT_API_KEY | The LLM behind conversation, extraction, and recommendation |
DATABASE_URL | Neon Postgres connection string |
TIANDITU_API_KEY | Tianditu, the national map platform, which validates that a destination really exists and suggests places as you type |
Optional. Recommendation degrades without it rather than failing:
| Variable | Missing means |
|---|---|
BOCHA_API_KEY | Recommendations are generated without discovery search context; access checks and image enrichment are not connected to the current workflow |
The remaining variables in .env.example override defaults:
LLM_MODEL, MOONSHOT_BASE_URL, MERI_TIMEZONE, LLM_DEBUG_OUTPUT, and
LOG_LEVEL.
Meri verifies places with Tianditu. Amap was removed in 1.0702: its free tier for
individual developers ends a year after sign-up and a public deployment needs a paid
licence. Tianditu has no popularity signal — it ranks same-named places by text, so
苍山 may lead with the village in 广西 rather than the mountain in 大理 — and it has no
photo API. Cards and covers use the reviewed catalog in public/photos, and
recommendation cards the catalog misses may be filled at run time from Wikimedia
Commons and, with PIXABAY_API_KEY, Pixabay; those downloads are kept in
MERI_MEDIA_DIR (required in production, outside the release directory and kept across
deploys; development falls back to .cache/media), capped by MERI_MEDIA_MAX_BYTES
(default 500 MB).
The block near the end of .env.example (QWEATHER_API_KEY, QWEATHER_API_HOST,
TUNIU_API_KEY, ROLLINGGO_API_KEY) holds keys Generate plan is planned to use; the
app does not read them yet.
npm run lint
npm run typecheck
npm test
npm run build
npm test runs every *.test.ts and *.test.tsx file under src/ through the
Node test runner. Tests sit next to the code they cover.
Database schema changes go through Drizzle Kit:
npx drizzle-kit generate
npx drizzle-kit migrate
Each top-level directory answers one question.
docs/ Product and architecture documents
src/app/ What the URLs are: App Router pages and route handlers
src/components/ What the screen looks like: React components
src/domain/ What Meri's concepts are: pure types and validation, no IO
src/capabilities/ What Meri can do: one directory per capability
src/agents/ What Meri decides for itself: Mastra agents and their tools
src/platform/ How Meri talks to the outside world: ports and adapters
Two rules hold the layers apart:
src/domain/ performs no IO. It defines Trip, TripState, TripDraft, and
the certainty of each field (known, approximate, ambiguous, missing),
and it validates anything arriving from outside. It never calls a network or a
database.src/platform/ implements external integrations. Application services use
ports and normalized results; production factories and some route handlers
assemble the concrete adapters. Browser components also request Meri's own APIs.
Provider-specific HTTP/SDK handling belongs in adapters, not domain rules.src/capabilities/ is named after what the code does, not where it runs, and
holds one directory per capability, so a whole flow reads top to bottom in one
place. It contains no React components.
src/capabilities/journey/ Creating, loading, and updating a Journey
src/capabilities/conversation/ Interpreting a Workspace message and wording the reply
src/capabilities/destination/ Confirming a destination names a real place
src/capabilities/recommendation/ Turning preferences into validated, province-filtered suggestions
src/agents/ holds the parts that choose their own next step. A capability is a
fixed flow written in code; an agent gets a goal and tools and decides which tool
to call from what the last call returned. Its tools are thin wrappers over
src/platform/ ports, and nothing an agent produces is saved before code has
validated it. Today it holds a trial agent; the Planner behind Generate plan is
designed in src/agents/README.md.
src/platform/llm/ Structured-output port, Moonshot adapter
src/platform/location-provider/ Location and suggestion ports
src/platform/tianditu/ Tianditu place check and input tips
src/platform/search/ Search ports, one shared Bocha Web Search
request and the Discovery Search adapter
src/platform/persistence/ Repository ports at the top, with the Postgres
and in-memory adapters and the Drizzle schema
beneath them
src/platform/identity/ Guest identity
src/platform/observability/ Logger and error serialization
This is the beginning of the README. Read the rest at the original. Read the full README ↗