ระบบ POS สำหรับร้านก๋วยเตี๋ยว/ลูกชิ้น
Translation pending
CommerceTypeScript · CSSGitHub @kickdata33OnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Loading the full README. The saved excerpt is shown below.
ระบบ 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/.Read the full 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.