Synaplan
开源 AI 软件平台,面向企业:自托管 AI 代理,符合 GDPR 的聊天机器人小部件,RAG 知识库,WhatsApp 与 Outlook AI,MCP,多模型路由。支持 Docker、Kubernetes 或在 Germ 托管。
AI 翻译
尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证RFQ
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗Arabic-first RFQ and quote comparison for Saudi businesses. Send a request for quotation, collect supplier quotes by web form or emailed PDF, compare them line by line excluding VAT, and auto-approve the best one within rules the buyer sets. Every step is recorded on a decision trail.
Screenshots: add
docs/screenshots/landing.png,compare.png,dashboard.pngandsupplier-form-ar.png. The live demo needs no sign-up: open the site and press Explore the live demo.
A Saudi contractor or office manager who buys every week runs the same loop by hand:
Nobody records why that supplier won, the spreadsheet is never the same twice, and the cheapest quote isn't always the right one.
Clarix turns the loop into one flow, in Arabic or English, right to left where it should be:
flowchart LR
subgraph Browser
B[Buyer app<br/>Next.js RSC + server actions]
S[Supplier form<br/>/quote/token]
V[Public site<br/>/ and /pricing]
end
subgraph Vercel
MW[Middleware<br/>2.5 s auth cap]
SA[Server actions]
WH["/api/webhooks/resend-inbound<br/>svix-verified"]
JR["/api/jobs/process<br/>CRON_SECRET"]
end
subgraph Supabase
DB[(Postgres + RLS<br/>jobs queue, audit_events)]
ST[(Storage: quote-pdfs)]
AU[Auth]
end
G[Gemini Flash<br/>zod-validated JSON]
R[Resend<br/>email in/out]
B --> MW --> SA --> DB
S --> SA
V --> SA
R -- inbound PDF --> WH -- enqueue --> DB
SA -- enqueue + waitUntil --> JR
JR -- claim_jobs skip locked --> DB
JR --> G
JR --> R
SA --> G
SA --> ST
MW --> AU
GH[GitHub Actions every 15 min<br/>+ Vercel daily cron] --> JR
auth.uid() through RLS. The demo
account is read-only at the database.waitUntil, and swept every 15 minutes. claim_jobs uses
for update skip locked, so runs never collide.More detail: docs/ARCHITECTURE.md, docs/SECURITY.md,
docs/DECISIONS.md (75 numbered decisions), and DESIGN.md.
| Choice | Why |
|---|---|
| Next.js 14 App Router | Server components read through RLS with the user's cookie, and server actions keep every write on the server. One deployable runs the buyer app, the public supplier form, webhooks and the job runner. |
| Supabase (Postgres, RLS, Auth, Storage) | Tenancy enforced by the database, not by where clauses someone forgets. Postgres also hosts the job queue and rate limits, so there is no extra infrastructure. |
Gemini Flash via @google/genai | Reads scanned PDFs natively, handles Arabic, supports structured output, and has a free tier for a pre-revenue product. The model is GEMINI_MODEL, which matters: see the challenges below. |
| Resend | Outbound invitations and POs plus inbound email in one service. The inbound webhook makes "reply with your PDF" work. |
| next-intl, cookie-based | Full Arabic/English without locale URLs, so every existing link (emails, supplier tokens, webhooks) keeps working. The language follows the buyer across devices through profiles.locale. |
| Tailwind and shadcn/ui (Radix) | Accessible primitives. Logical properties (ms, ps, start, end) make RTL a direction flip, not a second stylesheet. |
| Vitest and PGlite | 701 tests. Migrations and RLS are tested against real Postgres in WASM, with no Docker and no hosted database. Gemini and Resend are always mocked. |
| Vercel and GitHub Actions | Hobby-tier hosting. CI runs typecheck, lint, tests, the offline evals and the build on every PR, and a free schedule sweeps the job queue. |
1. Background work that silently never happened. The supplier form, manual entry and PDF
confirmation called maybeAutoGenerateRecommendation() without await. On a laptop that works.
On a serverless platform the function freezes as soon as the response is sent, so the
recommendation, the auto-approval and the PO email were dropped at random, with no error
anywhere.
waitUntil. A cron sweep finishes anything a frozen instance
left behind.2. The middleware that took the whole site down. Middleware called
supabase.auth.getUser() on every matched request with no timeout. When Supabase Auth was slow,
every page hung until Vercel killed it with MIDDLEWARE_INVOCATION_TIMEOUT (504), including the
public supplier form and the webhook. The fix:
fetch, plus a Promise.race./login with an explanation.3. Race conditions in auto-approval. Two suppliers submitting the last quotes at the same moment could both create a recommendation, and both runs could send a PO. The award insert now gates every side effect, and the database enforces the uniqueness.
4. A model that quietly disappeared. The extraction evals (below) failed every case one
morning. gemini-2.5-flash had started returning 404 "no longer available to new users". The
default moved to gemini-3.5-flash (the newest models were overloaded that day), and
GEMINI_MODEL now changes it without a deploy of code. Because evals run against the real API on
demand, this was caught before any buyer was affected.
5. Arabic that wasn't really Arabic.
next/font places a size-matched Arial fallback right after Geist in the font
stack. Arial has Arabic glyphs, so every Arabic word rendered in Arial instead of IBM Plex Sans
Arabic. Removing the generated fallback fixed it.6. Security without a security team. Every server action checks the session on the server. On top of that:
Details: docs/SECURITY.md.
22 deliberately messy synthetic quotes in Arabic, English and mixed (VAT-inclusive prices, Arabic-Indic digits, line totals only, emails, tables, other currencies). Each runs through the production prompt, schema and repair path.
| Field | Rule-based baseline | Gemini (gemini-3.5-flash) |
|---|---|---|
| Unit price (excl. VAT) | 46.3% | 100% (32/32) |
| Currency | 100% | 100% |
| Delivery days | 90.9% | 94.1% |
| Warranty period | 100% | 100% |
Method and full results: docs/EVALS.md.
npx tsx evals/extraction/run.ts # offline baseline
RUN_LIVE_EVALS=true npx tsx --env-file=.env.local evals/extraction/run.ts --write # real Gemini
Requirements: Node 22, a Supabase project (hosted or supabase start), and optionally Gemini and
Resend keys.
npm install
cp .env.example .env.local # fill in the values; names are documented in the file
supabase/migrations/0001 to 0020 in order (supabase db push, or paste
them into the SQL editor). They are additive.npm run dev
Open http://localhost:3000. Signed out, you see the landing page; sign up to reach the app.ALLOW_SEED=true npm run seed:demo # local Supabase
ALLOW_SEED=true DEMO_SEED_PROJECT_REF=<ref> npm run seed:demo # a hosted project, on purpose
npm run typecheck && npm run lint && npm test && npm run build
Without a Gemini key, the AI features fail gracefully and quotes can be entered by hand. Without Resend, nothing is emailed. Tests never call either.
docs/PROGRESS.md: every phase, its PR, and how it was verified.docs/plans/: the plan for each phase.docs/METRICS.md: how savings and scorecards are calculated.PRODUCT.md and DESIGN.md: product truth and the design system.