Fujimod
Try your camera firmware in the browser and build Fujimod SD boot files.
Fixed-price ground transport across Namibia — airport transfers, intercity journeys and corporate mobility, with professional local drivers and no meter.
LifestyleTypeScript · CSSGitHub @italkpropertyOnlineOwner 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
Namibian transporation network
Translation pending
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
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.Read the full 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.