Synaplan
Open-source AI platform for companies: self-hosted AI agents, GDPR-compliant chatbot widget, RAG knowledge base, WhatsApp and Outlook AI, MCP, multi-model routing. Docker, Kubernetes or hosted in Germ
KTrack (Kuroshio Track): a local-first Kee Safety operations demo.
Translation pending
BusinessTypeScript · CSSGitHub @Kuroshio-AIOnlineOwner 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
Kee Safety demonstration of spreadsheet ingestion, inspections, approvals, in-app alerts, and certificate verification.
Translation pending
Taken from the repository README
Loading the full README.
Read the full README ↗KTrack (Kuroshio Track) is a local-first Kee Safety operations console for fictional register data. The default route is /dashboard; records, inspections, alerts and certificates are stored in one versioned localStorage document. EmailJS and Meta WhatsApp Cloud API are available only for explicitly requested single-alert actions; there is no database or background messaging integration.
Use Node 24.x.
npm ci
cp .env.example .env.local
npm run dev
The token secret must be at least 32 characters. NEXT_PUBLIC_APP_URL is used to build QR verification URLs; when omitted in development, the request origin is used. Never expose DEMO_CERT_TOKEN_SECRET or the Meta variables to the browser. EmailJS uses the three NEXT_PUBLIC_EMAILJS_* values; outbound WhatsApp requires META_WHATSAPP_ACCESS_TOKEN, META_WHATSAPP_PHONE_NUMBER_ID, and META_WHATSAPP_TO in the server environment. META_WHATSAPP_TEMPLATE_NAME, META_WHATSAPP_TEMPLATE_LANGUAGE and META_GRAPH_API_VERSION have safe defaults. Leave the channel values unset to keep WhatsApp disabled.
Run the focused checks with:
npm run typecheck
npm test
npm run build
/verify?token=... page. Tokens are signed, immutable payloads with a 24-hour TTL.[email protected] and CC [email protected]; KTrack sends only when you click and has no automatic or bulk send action.Production demo: kuroshio-ktrack.vercel.app (the old keetrack.vercel.app address still works) · source: github.com/Kuroshio-AI/ktrack-demo. This repo is the sales demo; the production build lives in the private Kuroshio-AI/ktrack repo.
.xlsx files contain a worksheet named Register, a worksheet named Savings, or both. CSV files use the same fixed UTF-8 headers in the template: asset_ref, record_type, asset_type, site, owner, serial_no, assigned_engineer, inspection_due_date, inspection_interval_months, licence_expiry_date, certificate_no, certificate_issued_date, certificate_expiry_date, retirement_due_date, status. asset_ref, record_type, asset_type, site and owner are required. Date values are stored as calendar strings (YYYY-MM-DD), certificate fields are all-or-nothing, and certificate expiry cannot precede issue. Formula cells, malformed layouts, duplicate trimmed case-insensitive asset refs, files over 2MB and imports exceeding 500 total register records are rejected or reported per row. Duplicate rows never overwrite existing records.
Sustainability savings use the layout the Sustainability page exports: certificate_no, quarter, date, type, description, quantity, unit, kg_co2e_per_unit, kg_co2e_saved, cost_saving_usd, site, evidence, issued_date. quarter, kg_co2e_saved and issued_date are worked out again on import. In a CSV the savings block follows the register after a blank row, starting at its own header row; the Demo Controls templates and both filled samples carry both. A known certificate number, or the same type, date, quantity and description, is skipped rather than overwritten, and every new saving gets the next ENV-<year>-<seq> number.
The browser saves a complete next-state JSON document before updating the visible state. Unsupported or corrupted stored data enters recovery mode and blocks ordinary writes until Start fresh is explicitly confirmed in Demo Controls. Reset clears only KTrack’s operational local data.
Inspection evidence is optional fictional demo data. Only image MIME types are accepted, with a 200KB per-image and 1MB total local cap. No inspection or approval history is invented by register import.
Creating a QR calls POST /api/certificates/demo-token with a small allowlisted certificate snapshot. The API signs it with an HMAC secret and returns a verification URL. /verify?token=... displays the captured status, dates and asOf timestamp; it is not a live certificate lookup. Old tokens remain valid until their own expiry even if a certificate is later revoked or superseded. QR generation can be retried without changing the approved certificate.
Future integrations such as a database, automated outbound delivery, customer identity and real certification evidence are intentionally outside this demo.
EmailJS uses the browser REST endpoint only after a user clicks Send email on an individual alert. The template has fixed To [email protected] and CC [email protected]; KTrack sends only the alert event, asset reference/type, site, owner, severity, due date, demo date, status and occurrence timestamp. Notes, inspection evidence and contact lists are never included. The shared EmailJS account and mailbox quota are a demo dependency, so configure the three public values in .env.local, do not commit account values, and expect no scheduled or background delivery. A provider acceptance is recorded in localStorage; network failures remain unconfirmed and require a deliberate manual retry.
The provider template is versioned at docs/emailjs-template.html. Keep its settings as follows: subject [KTrack Demo] {{event}} — {{asset_ref}}, fixed To and Reply-To [email protected], fixed CC [email protected], From Name KTrack Demo, the default EmailJS sender, blank BCC, and no auto-reply. Keep the template body limited to the allowlisted fields above.
The WhatsApp action is a manual, one-alert operation. The browser posts a same-origin JSON allowlist to /api/alerts/whatsapp with alertId, event, assetRef, site, severity and dueDate. The browser derives those values from the selected alert and its matching local record, sends no owner, notes, evidence, contact list or arbitrary message body, and never chooses the recipient, phone number ID, template or Meta access token. Missing asset, site or due date values are sent as Not applicable.
The server requires META_WHATSAPP_ACCESS_TOKEN, META_WHATSAPP_PHONE_NUMBER_ID and META_WHATSAPP_TO. Sending is deliberately unauthenticated: anyone using the public demo can send an alert, but only to the fixed recipients, with the guards below. META_WHATSAPP_TO holds one number or several separated by commas, and each alert goes to all of them. If only some numbers accept, the result stays unconfirmed so a retry can't message the others twice. META_WHATSAPP_TEMPLATE_NAME defaults to keetrack_asset_alert, META_WHATSAPP_TEMPLATE_LANGUAGE defaults to en_US, and META_GRAPH_API_VERSION defaults to v26.0. Keep all of these values in the server environment, never in browser code or the repository.
To replace an expired access token without a redeploy, connect Upstash for Redis from the Vercel Marketplace so the project has KV_REST_API_URL and KV_REST_API_TOKEN. Demo Controls then shows a Meta access token box. Anyone can submit it, but a token is saved only after Meta confirms it can use META_WHATSAPP_PHONE_NUMBER_ID, so only someone who already controls that number can change it. The saved token lives in Redis, overrides META_WHATSAPP_ACCESS_TOKEN, and is never returned to the browser.
The approved template must have these five body text parameters in this exact order:
KTrack maintenance alert for your registered equipment.
Event: {{1}}
Asset: {{2}}
Site: {{3}}
Severity: {{4}}
Due date: {{5}}
Please review this item in your KTrack register.
The template name, language, parameter order and approved category are ultimately controlled by Meta. A successful response with a valid WhatsApp message ID means Meta accepted the API request; it does not confirm delivery. Network, timeout and malformed-provider responses remain unconfirmed and are cached so the browser does not automatically retry an ambiguous request. 4xx responses are redacted as provider rejection. Accepted and ambiguous results use a bounded warm-instance replay cache for 10 minutes, with a three-second per-instance cooldown and a maximum of 500 alert keys. These module-local guards are not full customer authentication or a durable global quota; cold starts and multiple instances can reset or bypass them. There are no scheduled, background or bulk sends.
For production, complete the local Meta app and business onboarding/migration before deployment and use a separate production sender. Keep the user's existing WhatsApp Business phone app number outside this migration. The deployed Meta app must be published, have the WhatsApp Business Account connected, and subscribe to the messages field for webhook callbacks. Configure the fixed recipient and approved keetrack_asset_alert template in the production server environment.
The optional /api/webhooks/whatsapp route supports Meta's verification challenge and signed event callbacks. Set META_APP_SECRET and META_WHATSAPP_VERIFY_TOKEN in the server environment, then configure that callback URL in the published Meta app. GET verification compares the token in constant time and returns the challenge as plain text. POST requests are accepted only with a valid X-Hub-Signature-256 HMAC over the raw request bytes and a basic WhatsApp event envelope; unsigned callbacks are rejected.
This demo authenticates and acknowledges valid callbacks only. It has no backend database: callback events are not persisted, do not trigger inbound replies or automatic messages, and are not used to mark local alerts delivered. Delivery remains unconfirmed in KTrack even when a webhook callback is received. Alert sending has no authentication or durable global rate limiting, so this flow suits the controlled demo only.