WallpaperMachine
당신이 사랑하는 배경화면, 맥에서 새롭게 만나보세요
저장소 정보는 아직 수집하지 않았습니다.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
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
여기까지가 README 앞부분입니다. 나머지는 원문에서 읽을 수 있습니다. README 전문 보기 ↗