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.