ViewTouch Point of Sale
GNU/Linux Restaurant Point of Sale software - Free and open source POS solution
翻译准备中
尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证正在加载完整 README。 以下为已保存的摘录。
RepeatlyOS is a city marketplace where shoppers find real local businesses —
and the operating system those businesses run on: orders, bookings,
payments, and customers, all in one place. Launched in Batroun and Shekka,
Lebanon.
This repo holds two things at different stages of maturity, and it's worth
knowing which is which before you dig in:查看完整 README ↗RepeatlyOS is a city marketplace where shoppers find real local businesses — and the operating system those businesses run on: orders, bookings, payments, and customers, all in one place. Launched in Batroun and Shekka, Lebanon.
This repo holds two things at different stages of maturity, and it's worth knowing which is which before you dig in:
/, /:citySlug, /app, /onboarding,
/platform-admin). This is what's described below./dashboard/*, kept around from before the Supabase build-out. It runs
entirely on fake in-memory data (src/context/DemoContext.tsx) and has no
connection to the real backend. Useful for showing off UI polish quickly
with zero setup, not representative of what a real business actually sees.For shoppers: browse a city's page (/batroun, /shekka), search across
every business in it — including a rule-based natural-language search
(/discover, try "nike basketball shoes in shekka") that falls back to
neighboring cities in the same region if nothing matches, or a real GPS-radius
"near me" search — add items from multiple businesses to one cart, and check
out as a guest (no account needed). Verified photo reviews, a verified-business
badge, live power-cut-aware "closed right now" status, and a city-wide loyalty
wallet (earn at any participating business, redeem at any other) round out the
shopping side.
For business owners: sign up, get approved, and run the shop from
/app/:businessId/* — products, inventory (a real append-only movement
ledger, not just a number you edit), orders, bookings with staff assignment
and overlap-safe scheduling, customers, tasks, payments, and analytics
(revenue heatmap, 30-day forecast, churn-risk flags, a health score, referral
leaderboard) — all computed from real data via Postgres functions, not
estimated client-side.
For the platform: a super-admin dashboard to approve businesses, open new cities, assign SaaS plans, manage the USD/LBP exchange rate shown throughout the marketplace, and revoke passkeys.
npm install
cp .env.example .env # fill in your Supabase project URL + anon key
npm run dev # → http://localhost:5173
Real backend, real schema — this is not a zero-config demo. You need an actual Supabase project. See Backend setup below.
npm run build # tsc -b && vite build
npm run lint
npm run test # vitest — unit tests for the parsing/math-heavy logic
.env
(.env.example has the exact variable names).supabase link --project-ref <your-ref> then
supabase db push — applies every file in supabase/migrations/ in
order. There are currently 41 migrations building up the full schema
incrementally; read a few if you want the "why", not just the "what" —
this codebase documents its own reasoning unusually heavily.supabase/seed.sql once (via the SQL editor, or
supabase db reset locally) for the business-type templates and the
first launch city.supabase/functions/ (verify-login,
admin-manage-passkeys, decrypt-invite-email,
decrypt-customer-address) — supabase functions deploy <name> each, or
via the Dashboard.insert into public.platform_admins (user_id) values ('<your auth.users.id>');
supabase test db # pgTAP — requires Docker Desktop
Covers core SQL logic (booking-overlap constraint, inventory auto-decrement,
loyalty balance) and an automated tenant-isolation check. See
supabase/tests/README.md.
No passwords, no codes, no emailed links — every login page works the same
way: type your email, click Verify, and if you're authorized, register
a passkey right there (or just use your existing one on repeat visits).
See docs/REPEATLYOS_SECURITY_MODEL.md → "Bootstrap flow reworked" for
exactly how a real session is established with nothing ever shown to or
typed by the user.
Business owner:
/signup (just an unauthenticated
signup_requests row — no account exists yet)./platform-admin — this only flips
the request's status; it doesn't create an account or send anything./app, enters that same email, clicks Verify, and
registers a passkey — landing on /onboarding.status = 'pending_approval' and they're made its owner immediately.pending_approval only hides the business from the public marketplace;
it does not block the owner's own use of their dashboard.City admin: a platform admin adds their email against a city from
/platform-admin (no account needs to exist yet) — they then verify and
register a passkey at /city-admin-login. Never self-registered.
Platform admin: the one role still requiring direct SQL access
(insert into platform_admins ..., see below) — intentional friction so
this can never be granted through the app itself. Once granted, sign-in
itself works the same way, at /super-admin.
Lost your passkey or switched devices? Same flow, any role: email + Verify re-establishes a session and lets you register a new one — fully self-service, no admin involvement needed.
React 19 · TypeScript (strict) · Vite · Tailwind CSS · React Router 7 · Supabase (Postgres + Auth + Edge Functions + Storage) · Recharts · Vitest
No custom API server — Postgres Row Level Security is the actual
authorization boundary; every table has RLS enabled with policies backed by
security definer helper functions (is_business_member,
has_business_permission, is_city_admin, is_platform_admin).
repeatlyos/
├── supabase/
│ ├── migrations/ # 41 files, applied in order — the real schema
│ ├── functions/ # 4 Edge Functions (service-role-gated operations)
│ └── tests/database/ # pgTAP tests
├── src/
│ ├── App.tsx # all routes — marketplace, /app, /dashboard, admin
│ ├── lib/ # smartSearch, geo, currency, i18n, checkout, offlineQueue
│ ├── pages/
│ │ ├── marketplace/ # public shopper-facing pages
│ │ ├── business/ # real merchant dashboard (Supabase-backed)
│ │ ├── admin/ # platform + city admin
│ │ ├── onboarding/ # business registration wizard
│ │ ├── auth/ # signup, per-role sign-in pages, passkeys
│ │ └── dashboard/ # legacy mock demo — see note at the top
│ └── types/domain.ts # hand-written mirror of the SQL schema
└── docs/ # architecture, security model, progress log —
# read these for the "why" behind non-obvious decisions
delivery_pool_members and
delivery_groups model shared delivery coordination internally, but
dispatching an actual rider needs a specific local courier chosen (a
business decision, not a code one).supabase/tests/), not exhaustive
coverage of all 33 tables.cities is a normal table, not a hardcoded list), not a code change.See docs/REPEATLYOS_PROGRESS.md for the full, dated history of what was
built, tested, and found along the way.