尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证AI shipment booking and pre-flight checker for Indian exporters (Gemini, Neon, Resend, Vercel)
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 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.