尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证正在加载完整 README。 以下为已保存的摘录。
ระบบ POS สำหรับร้านก๋วยเตี๋ยว/ลูกชิ้นขนาดเล็ก (~8 โต๊ะ) เน้นใช้งานง่ายผ่าน Tablet (หลัก) และ Mobile (รอง) สเปคฉบับเต็มอยู่ในโปรเจกต์ Claude ("Pos ร้านก๋วยเตี๋ยว" > spec-pos-requirements.md). Next.js (App Router) + TypeScript + Tailwind CSS + hand-rolled shadcn/ui-style components, Firebase (Firestore + Authentication). Every business value an Admin should be able to change (shop name, table count/names, menu, prices, categories, modifiers, payment methods, sales channels, logo, theme, receipt text) is read from Firestore, never hardcoded into a component — see types/ and repositories/.查看完整 README ↗
ระบบ POS สำหรับร้านก๋วยเตี๋ยว/ลูกชิ้นขนาดเล็ก (~8 โต๊ะ) เน้นใช้งานง่ายผ่าน Tablet (หลัก) และ Mobile (รอง)
สเปคฉบับเต็มอยู่ในโปรเจกต์ Claude ("Pos ร้านก๋วยเตี๋ยว" > spec-pos-requirements.md).
Next.js (App Router) + TypeScript + Tailwind CSS + hand-rolled shadcn/ui-style components, Firebase (Firestore + Authentication).
src/
app/ Next.js routes (login, /pos, /admin, API routes)
components/ui/ shadcn-style primitives (button, card, input, label, ...)
components/shared/ cross-cutting components (SignOutButton, ...)
lib/firebase/ Firebase client/admin SDK init, collection name constants
lib/auth/ session helpers (server), PIN hashing/throttling, AuthProvider (client)
repositories/ thin Firestore data-access layer — one per collection.
Components never call Firestore directly; they go through these.
services/ business logic on top of repositories (added as POS/checkout logic lands)
hooks/ React hooks wrapping repositories/services for components
types/ shared TS types mirroring the Firestore schema
proxy.ts Next.js 16 "Proxy" (formerly middleware) — optimistic route guard
scripts/
seed.ts one-time setup: default shop, 8 tables, sales channels, payment methods, admin login
firestore.rules role-based Security Rules (see file for the full breakdown)
Every business value an Admin should be able to change (shop name, table count/names, menu,
prices, categories, modifiers, payment methods, sales channels, logo, theme, receipt text) is
read from Firestore, never hardcoded into a component — see types/ and repositories/.
Create a Firebase project (console.firebase.google.com):
asia-southeast1).Configure env vars
cp .env.example .env.local
Fill in the Firebase Web app config, the Admin SDK service-account fields, a NEXT_PUBLIC_SHOP_ID
slug, a PIN_PEPPER secret, and a 6-digit SEED_ADMIN_PIN for the first login.
Generate the pepper with:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
PIN_PEPPER must never change after go-live — rotating it invalidates every staff PIN.
Install & seed
npm install
npm run seed
Deploy security rules (requires the Firebase CLI):
npx firebase-tools login
npx firebase-tools use --add # pick your project
npx firebase-tools deploy --only firestore:rules
Run the app
npm run dev
Log in at /login by tapping the seeded 6-digit PIN. Admins land on /admin, staff on /pos.
Staff and admin both sign in with a 6-digit PIN on a keypad — no email, no password (item 26: minimal typing, usable by staff who aren't comfortable with technology). How it works:
/api/auth/pin.HMAC-SHA256("<shopId>:<pin>", PIN_PEPPER) and looks that value up in
userSecrets. The raw PIN is never stored, and PIN_PEPPER lives only in the server
environment — so a leak of the Firestore data alone doesn't expose anyone's PIN.signInWithCustomToken and posts the ID token to /api/auth/session for the httpOnly session
cookie. From there, auth behaves exactly like any Firebase session — Security Rules still see a
real request.auth.uid.Because a PIN identifies its user on its own, PINs must be unique within a shop; the write path rejects duplicates.
Brute-force protection: 5 failed attempts within 15 minutes locks that client out for 15 minutes
(lib/auth/pin.ts). Without it a 6-digit PIN — only 10^6 combinations, on a publicly reachable
URL — would not survive long.
userSecrets and pinAttempts are denied to every client in firestore.rules, including
admins; only the Admin SDK touches them.
npm run test:pin # PIN hashing + lockout logic
Security rules against the emulator:
npx firebase-tools emulators:start --only firestore,auth
Milestone 1 (project foundation) — see the plan/PR this was built from. Covers: project setup,
Firebase wiring, Firestore types, seed data, login + role-gated /admin vs /pos, and Security
Rules. Menu/modifier/table/channel admin screens, the POS order screen, checkout, and the audit
log are the next milestones.