Javis OS
Javis OS is an Agentic AI that assists entrepreneurs in business tasks, helping them grow their work.
AI translation
Describe a shipment in plain English or upload your booking sheet. SaathiFly checks ten pre-flight rules, explains every fix and recommends a carrier from the rate card.
BusinessTypeScript · CSSGitHub @manavjain-cloudOnlineOwner 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
AI shipment booking and pre-flight checker for Indian exporters (Gemini, Neon, Resend, Vercel)
Taken from the repository README
Loading the full README.
Read the full README ↗Live demo: https://saathifly.vercel.app (no login; the earlier addresses prefly-app.vercel.app and shipsaathi-mj-3d6b.vercel.app still work). Try the chat on New Shipment, or upload the sample workbook with planted mistakes on Upload Excel.
SaathiFly helps Indian manufacturers and sellers book pallet shipments from the UK to Germany, France and the Netherlands without the small mistakes that get goods held at customs or turned away at a warehouse.
SaathiFly does not book carriers. There's no carrier integration: a confirmed booking is the seller's confirmed proposal. The ten checks catch common mistakes. They are not a full customs, dangerous-goods or export-compliance review.
Seller chat ─┐ ┌─> Issue report (Red / Amber / review + fixes)
├─> one Booking model ─> validation engine ─┤
Excel upload ┘ (src/lib/domain) (pure TypeScript) └─> Carrier eligibility + priority ranking
│
seller review / edit / confirm <────┘ ──> optional email (Resend)
persisted in Neon Postgres (bookings, items, results, events)
| Layer | Where | Notes |
|---|---|---|
| Data model | src/lib/domain/types.ts | Both entry paths produce the same Booking. null = not provided, never a guess. |
| Parsing | normalize.ts, dates.ts, excel.ts | Same parsers for Excel cells, chat values and form edits. |
| Rules | validation.ts | One pure function per rule (ruleR01 … ruleR10), plus data-quality checks. |
| Prohibited goods | hazmat.ts (+ server/hazard-ai.ts) | Deterministic keyword screen. Gemini can only escalate an item to human review. |
| Carriers | carriers.ts | Route + pallet-weight filter, priority ranking, ties, balanced score. |
| Chat logic | conversation.ts | Applies the model's proposed changes, works out missing fields and next questions. |
| Gemini | server/llm.ts, server/extract.ts | Structured JSON output. Keys stay on the server. |
| API | src/app/api/* | Server re-validates everything. Client results are never trusted. |
| UI | src/app/*, src/components/* | Next.js 16 App Router, Tailwind v4. |
The rate card and rulebook live in src/data/rate-card.json and src/data/rulebook.json. They are generated from the supplied workbook (npm run extract:reference), not typed by hand. If an uploaded workbook includes a Carrier options sheet that differs from the template, its rates are used for that upload and the UI says so.
All numeric checks are deterministic code. None of them use AI judgement.
| Rule | Severity | Formula / logic |
|---|---|---|
| R-01 | Red | HS code digits (ignoring ., space, -) must be numeric and ≥ 6. Blank fails. A 5-digit code gets a note that Excel may have dropped a leading zero. |
| R-02 | Red | Let S = Σ(quantity × unit price). Pass when ` |
| R-03 | Red | For each item: units per carton × cartons = quantity (exact). |
| R-04 | Red | booking cartons = Σ item cartons (exact). |
| R-05 | Red | gross weight ÷ pallets ≤ max kg/pallet of the chosen carrier. Chosen = the seller's selected carrier, otherwise the carrier their priority picks from the route. If it fails, the fix offers the cheapest eligible alternative or the pallet count that would fit. Missing or zero pallets fail. |
| R-06 | Red | Keyword screen for lithium batteries, aerosols and flammable liquids, with negations ("non-flammable", "batteries not included") removed first. Clear hits are Red. Ambiguous ones (e.g. "battery", "perfume", "laptop", "spray") and anything Gemini flags become Needs review. They block dispatch until the seller confirms the item is safe. A Red hit can't be acknowledged away. |
| R-07 | Amber | gross weight ≥ Σ(unit weight × quantity). |
| R-08 | Amber | Destination type Warehouse ⇒ delivery appointment must be Yes. |
| R-09 | Amber | Every item has a country of origin. |
| R-10 | Amber | Ready date ≥ today, using the calendar date in Europe/London (goods are collected in the UK). Today itself passes. |
Booking status
The server refuses to confirm anything that is Blocked or Needs review.
gross ÷ pallets ≤ max weight per pallet.pallets × price per pallet (GBP, from the rate card).score = 0.40·cost + 0.30·speed + 0.30·reliability. Cost gets the biggest weight because on this rate card the faster services are also the more reliable ones, so equal weights would count that premium twice. For UK → Germany with 3 pallets: A 0.40, B 0.65, C 0.60.Requirements: Node 20+ (tested on Node 24), npm.
npm install
cp .env.example .env.local
Fill in .env.local:
| Variable | Needed for | Notes |
|---|---|---|
DATABASE_URL | saving bookings, reports, history | Neon pooled connection string |
GEMINI_API_KEY or OPENROUTER_API_KEY | chat, AI hazard review, plain-English summary | A Google AI Studio key calls Gemini directly. An OpenRouter key calls google/gemini-* through OpenRouter. |
GEMINI_MODEL | optional | Defaults: gemini-2.5-flash (Google) / google/gemini-3.5-flash (OpenRouter) |
RESEND_API_KEY | Without a verified domain, Resend only delivers to the Resend account owner's address. | |
RESEND_FROM | Defaults to SaathiFly <[email protected]> |
Create the tables (safe to re-run):
psql "$DATABASE_URL" -f db/schema.sql
psql "$DATABASE_URL" -f db/seed-carriers.sql
Start the dev server:
npm run dev
Other scripts:
npm test
npm run typecheck
npm run extract:reference
npx tsx scripts/make-sample.ts rebuilds public/templates/SaathiFly_Sample_With_Mistakes.xlsx, a demo upload with deliberate mistakes for every rule (sample input only, not real bookings).
The app degrades gracefully. Without Gemini, the chat says so and the editable form still works. Without a database, uploads are validated but not saved. Without Resend, email shows a clear "not configured" error.
/api/health reports which integrations are configured, without revealing any values.The app needs no login. All database access goes through server routes with input validation (zod), size limits and per-IP rate limits. No secrets reach the browser.
npm test runs 115 unit tests covering:
Checked by hand in the browser: a full chat booking including a mid-conversation weight change and "add a pallet", saving, confirming (and the server refusing a booking with a Red error), email failure feedback, uploading the sample workbook, and phone-width layout (375px) on every page with no sideways scroll.