尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证正在加载完整 README。 以下为已保存的摘录。
A household meal planner for two people in Turkish homes: decide "what's for dinner" together by swiping, plan the week as menus (çorba + ana yemek + yanında + salata), get a shared shopping list generated from the plan, and get prep reminders at the right moment ("Akşama İzmir köfte var, kıymayı buzluktan çıkarmayı unutma."). No calories, streaks or guilt.查看完整 README ↗
A household meal planner for two people in Turkish homes: decide "what's for dinner" together by swiping, plan the week as menus (çorba + ana yemek + yanında + salata), get a shared shopping list generated from the plan, and get prep reminders at the right moment ("Akşama İzmir köfte var, kıymayı buzluktan çıkarmayı unutma."). No calories, streaks or guilt.
Round 2 added: recipe import from a link (Instagram Reels, YouTube Shorts, TikTok, recipe sites — with a paste fallback), leftovers as a choice (per recipe, per household lunch habit, per evening) and a real cooking mode (one step per screen, several timers at once, screen stays on).
Round 3 turned the repo into a monorepo with an iOS + Android app (Expo) on the same local-first data, and made both apps Turkish + English.
Live: https://aksama-ne-var.vercel.app · Morning demo script: DEMO.md
| Path | What |
|---|---|
apps/web | Next.js app (pages, components, server routes /api/import, /api/translate) |
apps/mobile | Expo app (Expo Router, runs in Expo Go) — see docs/MOBILE.md |
packages/core | Framework-free TypeScript shared by both: models, repositories, migrations, key-value adapter, domain rules, import parser, seed recipes, store (zustand/vanilla), i18n catalogs, design tokens |
Vercel needs Root Directory apps/web: see docs/MONOREPO.md.
npm install
npm run dev # web, http://localhost:3000
npm run mobile # Expo dev server; scan the QR code with Expo Go
Node 24 LTS (.nvmrc). No backend: everything is stored in the browser. No environment variables
are required. Optional server-side keys improve recipe import (details in docs/IMPORT.md,
template in apps/web/.env.example):
| Variable | Optional? | Effect |
|---|---|---|
AI_PROVIDER | optional | anthropic (Claude only, for production), gemini (Gemini only, dev/testing), none (rules only); unset = every configured key, Gemini → Claude |
GEMINI_API_KEY | optional | Gemini (free tier, gemini-3.1-flash-lite) turns a caption into a clean recipe draft; tried first. Free-tier inputs may be used by Google and its limits are unpublished: for development and testing |
GEMINI_MODEL | optional | overrides the Gemini model |
ANTHROPIC_API_KEY | optional | Claude (Haiku) as the fallback when Gemini is unset, over quota or fails |
YOUTUBE_API_KEY | optional | reads full YouTube descriptions; without it only the title arrives and the paste box opens |
Without any LLM key a rule-based Turkish parser pre-fills the form. All keys stay on the server
(/api/import, /api/translate); the phone app calls those routes and carries no key.
Costs: oEmbed (TikTok, YouTube, Instagram), the YouTube Data API's daily quota, Gemini's free tier, the rule parser and on-device screenshot reading are free. Claude Haiku 5.5 is $0.10 / $0.50 per million input/output tokens: one import is about 2.3k + 600 tokens ≈ $0.0005 (≈ $0.50 per 1 000 imports, worst case ≈ $0.0015 for a maximum-length caption). Details in docs/IMPORT.md.
Root scripts run across the workspaces (npm run <script> -w @anv/web etc. for one):
| Script | What it does |
|---|---|
npm run dev / build | Next.js (web) |
npm run lint / typecheck | ESLint and TypeScript in every workspace |
npm test | Vitest in core (domain, data layer, store, seed, import parser) and web (routes, components); Jest (jest-expo) in mobile |
npm run test:e2e | Playwright at 390×844 and 1440×900: two-member journey, board drag-and-drop, import, leftovers, cooking mode with timers, axe on every screen (builds and starts the app on port 3100) |
npm run screenshots | Every screen at 390/1440 × light/dark into apps/web/screenshots/ (SHOTS=bugun,liste to limit) |
Expo Go (npm run mobile) runs everything except the parts below. They need a development
build (eas build --profile development, or npx expo run:ios / run:android on a machine with
Xcode / Android Studio) or the local APK (npm run apk). Details: docs/MOBILE.md.
| Feature | Expo Go | Native build |
|---|---|---|
Timer tone in notifications (timer_alarm.wav) | default sound (expo-notifications logs "Custom sound … not found") | the app's tone |
| Android "Telefonun saatinde kur" (Clock app timer) | works | works |
| iOS 26+ "Telefonun saati" (AlarmKit) | — | only with EXPO_PUBLIC_ENABLE_ALARMKIT=1 (below) |
| Share a reel into the app (Instagram / TikTok / YouTube) | — | Android always; iOS Share Extension only with ANV_IOS_SHARE_EXTENSION=1 |
| "Ekran görüntüsünden oku" (Instagram caption from screenshots, on-device OCR) | — (paste only) | yes |
The local module apps/mobile/modules/anv-alarmkit is not linked unless the build is made with
EXPO_PUBLIC_ENABLE_ALARMKIT=1, so a default build never compiles its Swift. It has not been
compiled yet (it was written on Linux). For the first test build:
EXPO_PUBLIC_ENABLE_ALARMKIT=1 npx expo run:ios --device on a Mac, or
on EAS set "env": { "EXPO_PUBLIC_ENABLE_ALARMKIT": "1" } in the development profile of eas.json
(the variable must be present at prebuild time and in the JS bundle).AnvAlarmKitModule.swift, build without the flag (everything else works)
and send the Xcode error.The built-in recipes come from a curated catalog in packages/core/data/recipes/: dish-list.json (1,000 dishes in an exact cuisine × category matrix, the app's original 100 marked existing) and one JSON file per cuisine/category (≤ 100 recipes each). Schema: packages/core/src/recipes/schema.ts. The app works with however many recipes exist; the rest are written by an LLM through a script you run:
# 1. Key: GEMINI_API_KEY in apps/web/.env.local (the script reads it), or export it.
npm run recipes:generate -- --limit 10 # try 10 dishes first, read them, then:
npm run recipes:generate # every dish without a recipe (Gemini, 5 per request)
npm run recipes:generate -- --fill # descriptions for the 100 converted built-ins
npm run recipes:validate -- --partial # check what exists (no args: the full 1,000 must be there)
npm run recipes:export # Supabase seed: packages/core/data/recipes/export/seed.sql + CSVs
packages/core/data/recipes/failed.json. A rerun tries those again (--skip-failed to leave them). An unknown ingredient means the ingredient catalog needs it: add it to packages/core/src/data/seed/pantry.ts with its aisle, then rerun.--only slug1,slug2, --cuisine italian, --category dessert, --limit N.GEN_PROVIDER=gemini (default; GEN_MODEL to pick another Gemini model, GEN_DELAY_MS between requests, default 6000) or GEN_PROVIDER=anthropic (needs ANTHROPIC_API_KEY). Anthropic sends every remaining dish as one Message Batch to claude-haiku-5-5, polls every minute (most batches finish within an hour), writes the results, and retries failures in a smaller batch. The batch id is saved, so if you stop while it's processing, rerunning picks the same batch up again.containsAlcohol); known pantry keys only (each has an aisle); leftover defaults by category.Or press Örnek evle dene · Ali ve Zeynep on the login page (also in Ayarlar) for the design's
sample week. Demo accounts: [email protected] / [email protected], password demo1234.
apps/web/src/app/globals.css (light/dark/system, no flash), Young Serif + Figtree via next/font.packages/core/src/data): zod models shaped like Postgres tables, repository interfaces
(repos.ts), one implementation KeyValueAdapter over any synchronous KeyValueStore
(localStorage on the web, an AsyncStorage-backed mirror on phones; one JSON array per table, schema
version + migrations, corrupt-data quarantine, quota errors), a per-tab session, and a
SyncBus (web: BroadcastChannel + storage events, apps/web/src/data/browserBus.ts) for live updates and presence.packages/core/src/domain): pure, unit-tested rules — list aggregation with unit conversion and
pack rounding, "evde var" subtraction, prep scheduling, deck building and matching, rotation
memory, leftovers, plan transitions (ate out, plan changed, swaps), summaries, Turkish copy.packages/core/src/store/app.ts): a vanilla Zustand store over the repositories; each app binds it to React (apps/web/src/store/app.ts, apps/mobile/src/store.ts); components never touch storage.packages/core/src/data/seed): 100 Turkish home recipes over a canonical ingredient catalog.packages/core/src/domain/import, apps/web/src/server/import, /api/import): source adapters over public
endpoints only, schema.org reader, rule parser, optional Claude structuring with validation./pisir/<date|recipe>, apps/web/src/components/cooking): shared resumable session,
timers stored as end timestamps, Screen Wake Lock.supabase/schema.sql (draft, with RLS) and docs/SUPABASE_MIGRATION.md.packages/core/src/domain/pantryReminders.ts is delivery-free, so a push sender can reuse it).NEXT_PUBLIC_AUTH_PROVIDERS_UI / EXPO_PUBLIC_AUTH_PROVIDERS_UI (on unless 0); the local
profile ("Giriş yapmadan devam et") is the only way in.