ViewTouch Point of Sale
GNU/Linux 레스토랑 POS 소프트웨어, 무료 오픈소스 솔루션
RepeatlyOS는 레바논 현지 사업자를 위한 도시 마켓플레이스로 주문·예약·결제·고객 관리까지 한 곳에서 제공한다
RepeatlyOS is a city marketplace for local Lebanese businesses and the operating system they run on — orders, bookings, payments, and customers, all in one place.
커머스TypeScript · PLpgSQLGitHub @Georges51379온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기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.