Easy-to-manage touch screens
Free, open-source touch screens. Guided USB setup, a drag-and-drop editor and local control. Made for Home Assistant.
翻訳待ち
Fixed-price ground transport across Namibia — airport transfers, intercity journeys and corporate mobility, with professional local drivers and no meter.
翻訳待ち
暮らしTypeScript · PLpgSQLGitHub @italkpropertyオンライン所有者未確認
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Namibian transporation network
翻訳待ち
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 |
NEXT_PUBLIC_GOOGLE_ADS_ID | Google Ads/Tag Assistant → site-wide Google tag ID (currently AW-18418844449) | Yes |
NEXT_PUBLIC_GOOGLE_ADS_CONVERSION_ID_BOOKING | Google Ads → Goals → Conversions → booking conversion → Tag setup | Yes |
NEXT_PUBLIC_GOOGLE_ADS_CONVERSION_LABEL_BOOKING | Same Google Ads conversion action → Tag setup | Yes |
NEXT_PUBLIC_GOOGLE_ADS_CONVERSION_ID_PAID | Google Ads → Goals → Conversions → paid booking conversion → Tag setup | Yes |
NEXT_PUBLIC_GOOGLE_ADS_CONVERSION_LABEL_PAID | Same Google Ads conversion action → Tag setup | Yes |
The Google Ads site tag ID and conversion-action IDs are deliberately separate. Do not copy the site tag ID into a conversion-action variable unless Google Ads actually gives you that value for the selected conversion action. A missing conversion label causes the application to send nothing rather than silently counting against the wrong action.
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 |
| ` |
This is the beginning of the README. Read the rest at the original. Read the full README ↗