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
Every shift gets a receipt.
Translation pending
BusinessTypeScript · JavaScriptGitHub @CpvasanthOnlineOwner 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
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗Live: https://fairshift-five.vercel.app · Prompt Wars 2026 · UN SDG 8 (Decent work)
Construction sites and college campuses run their workforce on paper registers. The register belongs to the boss, so pay is opaque, complaints get traced, and hazards are ignored until someone is hurt. FairShift makes the worker's phone a second register: their own copy of hours, pay math and the status of every report, in Tamil.
UN SDG 8, Decent work and economic growth (targets 8.5 equal pay, 8.8 labour rights and safe work). Persona: a daily-wage or contract worker (mason, helper, security guard, housekeeping) who speaks Tamil, uses a low-end Android phone and has no say over the paper register. Second persona: the site admin who needs to see hazards and overwork early.
lib/rules.ts): wage
basis, overtime thresholds, hazard categories, severity floors, feedback themes. The same report or the same 12-hour
shift gives a different, correct result on a construction site and on a college campus.lib/assistant.ts turns each person's own context into ranked next
steps, each with the rule behind it (see How FairShift decides below).| Screen | What it does | Code |
|---|---|---|
Landing page / | Live Shift Receipt hero, key figures, problem → features story, worker tiles, rule-pack comparison | app/page.tsx |
Worker app /w/[id] | Key figures and the worker's own rest flags; weekly pay receipt with overtime bars and Tamil read-aloud; Voice Hazard recorder; "Speak up (sealed)" | app/w/[id]/page.tsx, components/HazardReporter.tsx, components/SpeakButton.tsx |
Admin dashboard /admin?site= | Key figures, hazard-resolution gauge, crew hours chart, worker × day heatmap, filterable live hazards (cards on phones), attention list, Sealed Voice, crew pay table with CSV export | app/admin/page.tsx, components/LiveWidgets.tsx, components/Kpi.tsx |
| Shift assistant | Worker: "What to do next" in English + Tamil, read aloud. Admin: ranked "Do this first" | lib/assistant.ts, app/w/[id]/page.tsx, components/LiveWidgets.tsx |
| Live data | One poller for the whole dashboard (4s, 204 when unchanged, paused when hidden) | components/live.tsx |
| Shared UI | One look on all three screens: top bar, cards, key figures, status pills | components/TopBar.tsx, components/Card.tsx, components/Kpi.tsx, components/StatusBadge.tsx |
| API | Hazards POST/GET/PATCH and Sealed Voice in one route (shares one in-memory store) | app/api/hazards/route.ts, lib/store.ts |
| Rules (tested) | Pay, fatigue, severity floor, Sealed Voice grouping, site totals and CSV, rule packs, rate limit | lib/pay.ts, lib/fatigue.ts, lib/severity.ts, lib/sealed.ts, lib/crew.ts, lib/rules.ts, lib/ratelimit.ts |
| AI | Gemini, schema-constrained JSON, temperature 0, falls back across models on quota errors | lib/ai.ts |
| Who | Context | Decision (most urgent first) | Why it is shown |
|---|---|---|---|
| Worker | 7+ days in a row | Act now: ask for a day off | 7+ days without rest is HIGH |
| Worker | Over 60h (or 48h) in 7 days | Act now (or Check): ask for shorter shifts | Over 48h/week is overtime; over 60h is HIGH |
| Worker | Under 10h between shifts | Check: start later tomorrow | At least 10h rest between shifts |
| Worker | Any overtime | Check: pay slip shows the overtime amount | Over 8h/day or 48h/week is paid at 2× |
| Worker | None of the above | All good | Within the site's rule pack |
| Admin | Open HIGH hazard | 1. Fix it (oldest first) | Safety first |
| Admin | Report Gemini could not read | 2. Read the original report | Never lose a report |
| Admin | Worker with a HIGH fatigue flag | 3. Take the flag's action | Overwork before feedback |
| Admin | Open MEDIUM hazard, unlocked Sealed Voice theme, WARN flag, LOW hazard | 4–7, in that order | Lower risk |
The same report or shift gives a different, correct decision under each site's rule pack. Tested in
tests/assistant.test.ts.
lib/seed.ts).| Worker pain | FairShift feature | Code | SDG 8 target |
|---|---|---|---|
| Pay and overtime are opaque | Shift Receipt: day-by-day hours, regular × rate, overtime × 2 × rate, total owed, read aloud in Tamil | lib/pay.ts, app/w/[id]/page.tsx | 8.5 equal pay, 8.8 labour rights |
| Workers and admins don't know what to act on first | Shift assistant: ranked next steps from each person's own records, each with its rule | lib/assistant.ts | 8.8, 8.5 |
| Hazards ignored, reporters identified | Voice Hazard: speak or type in Tamil → Gemini → HIGH card on the admin board → Acknowledged → Fixed → status read aloud on the worker's phone. No reporter identity stored | app/api/hazards/route.ts, lib/ai.ts, lib/severity.ts, components/HazardReporter.tsx | 8.8 safe working environments |
| Overwork goes unseen | Attention list: explainable fatigue flags with an action ("13 days without rest: schedule a day off") | lib/fatigue.ts, app/admin/page.tsx | 8.8, 8.5 |
AI listens, rules decide. Gemini only converts speech/text into structured JSON (schema-constrained, temperature 0, validated with zod). Money and alerts are plain functions with unit tests. Gemini never touches a rupee, and it can raise a hazard's severity but never lower it below the rule pack's floor.
| Construction site | College campus | |
|---|---|---|
| Wage basis | daily (Rs 700/day) | monthly (Rs 15,000) |
| Overtime | 2× beyond 8h/day or 48h/week | 2× beyond 8h/day or 48h/week |
| Hazard categories | fall from height, scaffolding, electrical, no PPE, heat stress | electrical, lab chemical, fire exit blocked, structural damage, slippery floor |
| Severity floor (HIGH) | fall from height, electrical | electrical, fire exit blocked |
A hospital or factory is one more entry in lib/rules.ts. Defaults are illustrative; verify the applicable state
rule before using real figures. Under this pack a 12-hour guard shift is worth two 8-hour days of pay.
Worker phone (/w/[id]) Admin (/admin?site=...)
record / type / poll status poll every 4s (204 when unchanged)
\ /
Next.js 16 on Vercel: /api/hazards (POST, GET, PATCH)
lib/* pure functions (pay, fatigue, severity, rules)
lib/ai.ts -> Gemini API (Flash-Lite, falls back across models on quota errors), server-only key
npm install
cp .env.example .env.local # set GEMINI_API_KEY (server-only, never NEXT_PUBLIC_)
npm run dev
npm test # Vitest (46 tests): pay, fatigue, severity, sealed, assistant, crew, format, rate limit
npm run lint
Deploy: push to main; Vercel builds it. GEMINI_API_KEY is set as a Vercel sensitive environment variable.
Demo workers (fictional): Murugan and Selvi (construction), Ravi and Lakshmi (college).
.env* is gitignored.429 + Retry-After), which also protects the Gemini
quota. The limiter key lives in memory for the window only and is never logged or stored with a report.frame-ancestors 'none', nosniff, Referrer-Policy: no-referrer, Permissions-Policy: microphone=(self).aria-pressed and a visible
timer (keyboard-usable), severity is icon + word + color, overtime bars use a stripe pattern, lang="ta" on Tamil
text, role="status" / aria-live for updates. Read-aloud only uses a Tamil voice; it hides rather than reading
Tamil with an English voice./, /admin and /w/murugan, mobile and desktop. Layouts verified
at 1440px and 390px with no horizontal scrolling; on phones the hazard table becomes cards so actions stay on screen.lib/ai.ts falls through several models on 429s. Google may use submitted content to improve its products; a production deployment should use a
paid tier or Vertex AI.