Easy-to-manage touch screens
무료 오픈소스 터치스크린으로 USB 설정 가이드, 드래그‑드롭 편집기, 로컬 제어를 제공하며 Home Assistant용으로 제작되었습니다
Namibia Transport는 고정요금으로 나미비아 전역 공항·도시·기업 이동을 제공하며 현지 전문 운전사가 meter 없이 운행합니다
Fixed-price ground transport across Namibia — airport transfers, intercity journeys and corporate mobility, with professional local drivers and no meter.
라이프스타일TypeScript · CSSGitHub @italkproperty온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기Namibian transporation network
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Booking and dispatch for private airport transfers in Namibia. Travellers book a
fixed-price transfer online; independent licensed partner drivers fulfil the trip.
Read CLAUDE.md first — it holds the project constraints, the
architecture rules, and the current phase's definition of done.
Set these in .env.local locally, and in Vercel → Project → Settings →
Environment Variables for Preview and Production.README 전문 보기 ↗Booking and dispatch for private airport transfers in Namibia. Travellers book a fixed-price transfer online; independent licensed partner drivers fulfil the trip.
Read CLAUDE.md first — it holds the project constraints, the
architecture rules, and the current phase's definition of done.
Next.js 15 (App Router) · React 19 · TypeScript strict · Tailwind CSS v4 · shadcn/ui · Supabase (Postgres/Auth) · Drizzle ORM · Vercel
npm install
cp .env.example .env.local # then fill in the values below
npm run db:migrate # apply migrations to your Supabase database
npm run db:seed # seed the launch route + vehicle class
npm run dev
Set these in .env.local locally, and in Vercel → Project → Settings →
Environment Variables for Preview and Production.
| Variable | Where to find it | Exposed to browser |
|---|---|---|
DATABASE_URL | Supabase → Connect → Transaction pooler (port 6543, username postgres.<ref>). Not the direct connection — see below | No |
NEXT_PUBLIC_SUPABASE_URL | Supabase → Project Settings → API → Project URL | Yes |
NEXT_PUBLIC_SUPABASE_ANON_KEY | Supabase → Project Settings → API → anon public | Yes |
SUPABASE_SERVICE_ROLE_KEY | Supabase → Project Settings → API → service_role | No — bypasses RLS |
ADMIN_PASSWORD | Any strong secret you choose — gates /admin/bookings | No |
NEXT_PUBLIC_SITE_URL | Your custom domain, e.g. https://example.com. On Vercel, falls back to the project domain when unset | Yes |
NEXT_PUBLIC_SUPPORT_WHATSAPP | E.164 support WhatsApp — unlocks WhatsApp CTAs sitewide | Yes |
NEXT_PUBLIC_SUPPORT_PHONE | Optional support phone | Yes |
NEXT_PUBLIC_SUPPORT_EMAIL | Optional support email | Yes |
NEXT_PUBLIC_COMPANY_LOCATION | e.g. Windhoek, Namibia | Yes |
NEXT_PUBLIC_COMPANY_REGISTRATION | Company registration number, shown on quotes/footer | Yes |
QUOTE_VAT_RATE | e.g. 0.15 once VAT-registered; empty = quotes without VAT | No |
NEXT_PUBLIC_MAPBOX_TOKEN | Mapbox → Tokens → public token (pk.…). Restrict it by URL to your domains | Yes |
MAPBOX_SECRET_TOKEN | Optional server-only token for Directions (npm run routes:measure) | No |
PAYMENT_PROVIDER | paytoday to take real money; anything else uses the stub | No |
PAYTODAY_SHOP_KEY | PayToday Support / Merchant Portal | No — secret |
PAYTODAY_SHOP_HANDLE | PayToday Support / Merchant Portal | No — secret |
PAYTODAY_PRIVATE_KEY | PayToday Support / Merchant Portal | No — secret |
PAYTODAY_ENVIRONMENT | production — PayToday has no sandbox | No |
PAYTODAY_FALLBACK_EMAIL | Receipt address for bookings made without an e-mail | No |
PAYTODAY_SDK_PATH | Optional path to a vendored copy of the PayToday SDK | No |
PAYTODAY_SDK_SHA256 | Optional digest pin for that SDK | No |
DATABASE_URL is read at server start, so it must be present in every
environment that builds or runs the app.
Use Supabase's transaction pooler, not the direct connection. The direct
host (db.<ref>.supabase.co:5432) resolves to IPv6 only, and Vercel's
serverless functions have no IPv6 egress — every query fails with ENOTFOUND
while pages keep rendering from the catalogue fallback, so the symptom looks
like a database problem rather than a connection-string one. The pooler
(aws-0-<region>.pooler.supabase.com:6543, username postgres.<project-ref>)
is IPv4 and works. The direct connection is fine from a local machine.
| Command | Does |
|---|---|
npm run dev | Dev server on http://localhost:3000 |
npm run build / start | Production build / serve |
npm run lint | ESLint |
npm run typecheck | tsc --noEmit |
npm run db:generate | Generate a migration from db/schema.ts (no database needed) |
npm run db:migrate | Apply pending migrations |
npm run db:push | Push schema directly — dev only, skips migration files |
npm run db:seed | Idempotent seed of routes + vehicle classes |
npm run db:studio | Drizzle Studio |
npm run test:payments | Payment reconciliation tests — needs a throwaway DATABASE_URL |
npm run test:maps | Mapbox URL-construction tests — no network, no database |
npm run test:geometry | Geometry-backfill tests, including the unreachable-Mapbox path |
npm run test:polyline | Polyline decoding — precision and coordinate order |
npm run routes:measure | Ask Mapbox for each route's real distance and duration. Road geometry backfills itself on first render, so this is only needed to correct the quoted figures |
app/(marketing)/ public + SEO pages, incl. programmatic route pages
app/(booking)/ booking flow and confirmation
app/(dashboard)/ internal admin + dispatch at /admin/bookings
app/driver/ partner-driver app (later phase)
app/api/ route handlers and webhooks
components/ui/ shadcn/ui components
db/ Drizzle schema, migrations, seed
lib/payments/ PaymentProvider interface — stub + PayToday (Nedbank)
lib/messaging/ Messenger interface — stubbed, WhatsApp + Resend later
lib/maps/ route reads — database, falling back to lib/catalog.ts
lib/pricing.ts fare maths, shared by the client preview and the server
External services sit behind the adapter interfaces in lib/. Swap an
implementation there and nothing in the booking flow changes.
Stripe and Paddle do not serve Namibian entities and must not be added. The live gateway is PayToday (Nedbank Namibia): international cards, NAD settlement.
Two adapters implement the same PaymentProvider interface:
PAYMENT_PROVIDER | Adapter | Behaviour |
|---|---|---|
unset / stub | StubPaymentProvider | Records a pending intent, no redirect, no money moves. |
paytoday | PayTodayPaymentProvider | Creates a real intent and redirects to PayToday's hosted page. |
The stub is the default on purpose: a missing key should never quietly turn a live site into one that takes bookings it cannot charge.
createBooking() writes the booking as pending_payment, then asks the
provider for an intent. The amount is re-derived server-side from the route
and vehicle class — the form sends no price at all.payment_url./api/payments/paytoday/return?ref=NT-XXXXXX.status PayToday appends to the URL and calls
queryPaymentIntent() server-side for the authoritative result. Anyone can
type ?status=success; only the gateway's own answer is written down.Intents lapse after 30 minutes. An unpaid booking offers "Pay now", which resumes a live intent or issues a fresh one.
PAYTODAY_SHOP_KEY, PAYTODAY_SHOP_HANDLE and PAYTODAY_PRIVATE_KEY are
server-only — no NEXT_PUBLIC_ prefix, never in a browser bundle. PayToday's
guide contradicts itself here (§3.3 forbids keys in client code; the React
sample puts the private key in REACT_APP_*). We follow the disclaimer and run
the SDK server-side, so the browser only ever sees the hosted payment URL.
Keys come from PayToday Support: [email protected].
PayToday publishes no REST specification — only a browser <script> SDK. It is
therefore fetched and evaluated in a Node VM (lib/payments/paytoday/sdk.ts) and
driven from server code. Because that means executing a third-party script in
the payment path, two controls exist and at least one should be set before
taking real money:
PAYTODAY_SDK_PATH — run a vendored copy from disk instead of the network.PAYTODAY_SDK_SHA256 — pin the digest; a mismatch refuses to run.PayToday has no test environment. Every transaction is live and charged in real currency, refunded within 3–5 business days (immediately for Nedbank accounts). Budget a small real payment for the first end-to-end test, and never wire real intents into an automated test run.