Krowz
Real discounts at local restaurants, cafés and dessert spots. Show the QR at the counter, staff scan it, done.
翻译准备中
尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗A mobile-first directory of specialty coffee shops and roasters in Bali, then the rest of Indonesia. Phase 1 is a curated directory entered by an admin, plus a light community layer: anonymous thumbs up/down and shop submissions that an admin reviews.
"Coffee App" is a working name. Every brand string lives in src/lib/brand.ts.
You need Node 24 and Docker Desktop (running).
npm install
cp .env.example .env.local
cp supabase/functions/.env.example supabase/functions/.env
npm run db:start # local Supabase, with migrations and sample data
npm run admin:add -- [email protected] # invite yourself as an admin
npm run dev # http://localhost:3000
Sign in at http://localhost:3000/admin. Locally, sign-in emails go to Mailpit at http://127.0.0.1:54324, where you'll find the 6-digit code. Supabase Studio is at http://127.0.0.1:54323.
| Command | What it does |
|---|---|
npm run dev | Dev server |
npm run build | Production build (needs the database running: some pages prerender) |
npm run typecheck | Generates route types, then runs TypeScript |
npm run lint | ESLint |
npm test | Unit tests (Vitest) |
npm run db:test | Database tests (pgTAP): RLS, change history, votes, search |
npx playwright test | End-to-end tests against the dev server and local Supabase |
npm run db:reset | Rebuild the local database from migrations and seed. Clears test data |
npm run db:types | Regenerate database.types.ts after a schema change |
npm run admin:add -- email | Invite an admin |
npx supabase migration new <name>), applied with npx supabase db push./admin/options. The seed fills them locally only. Two values have meaning in code: the roast slugs light, medium and dark draw the roast scale, and the bean origin slug both matches either single origin in the filters. A slug comes from the label when an option is added and never changes, so rename labels freely.public.admins, invited with npm run admin:add. Sign-up is off. Admin writes go through Server Actions acting as the signed-in admin, so RLS applies to them too.shops, one revision per save, so no code path can edit a shop without leaving a record.The app is deployed to Vercel at https://coffee-app-five-gray.vercel.app/, with its own hosted Supabase project.
Local, staging and production each have their own Supabase project. To set up a hosted one:
npx supabase link --project-ref <ref> then npx supabase db push.{{ .Token }} (see supabase/templates/sign-in-code.html), and set up SMTP for real email delivery.npx supabase functions deploy vote --no-verify-jwt and the same for submit-shop. Set their secrets: npx supabase secrets set IP_HASH_SALT=<random> TURNSTILE_SECRET_KEY=<from Cloudflare>.pg_cron (the nightly vote refresh is scheduled by the migrations) and point-in-time recovery once the data matters.NEXT_PUBLIC_SITE_URL, NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY and NEXT_PUBLIC_TURNSTILE_SITE_KEY. The app never needs the secret key.npm run admin:add.CI (.github/workflows/ci.yml) runs every check above on each push once the repository is on GitHub.