尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗Double-entry accounting, GST compliance, e-invoicing and banking for Indian business. Next.js 15 on the front, MySQL and a real posting engine behind it — every figure on every report is computed from the journal on request, so no two screens can disagree.
Status: MVP. Every module is built and tested (the unit suite runs with
npm run test:unit), but it has not yet run a real business's books. The government portals (GST, IRP, e-way bill) go through a built-in stand-in until a GSP and NIC credentials are connected. Email goes out once an SMTP account is set in the environment, online payment once the business connects its own Razorpay account; SMS and WhatsApp messages are sent by hand.
npm install
cp .env.example .env.local # DB_HOST, DB_USER, DB_PASSWORD, DB_NAME
npm run db:migrate # hand-numbered SQL migrations, checksum-enforced
npm run db:seed # builds the demo organisation
npm run dev # http://localhost:5000
Then either create an account at /register — which gives you an empty, private set of books — or open the demo book from the sign-in page, which is a fully worked example you can click through without signing up.
Under the screens sits a real double-entry ledger in MySQL. Every invoice, bill and payment posts a balanced journal entry inside the same transaction that writes the document, and the Trial Balance, Profit & Loss and Balance Sheet are derived from those entries on every request. Nothing is cached, and nothing is faked with hard-coded numbers.
lib/server/ledger/posting.ts rejects any entry whose debits and credits differ — by construction, not by checking afterwards. It is the only writer of journal lines in the codebase.lib/server/audit.ts.lib/tax/gst.ts resolves CGST+SGST versus IGST from the supplier's registration and the place of supply, handles exports, SEZ, reverse charge and composition dealers, and validates GSTIN mod-36 checksums.DECIMAL(19,4) in the database, string and BigInt arithmetic in between. No floating point touches a rupee value.After an auditor's review, the controls around the books are built in and shown, area by area with the evidence, under Settings → Controls (lib/server/services/controls.ts):
/exceptions, services/exceptions.ts) — the scheduler finds what is wrong (invoices without an IRN, customers 15/30/60/90 days past due, bills falling due, MSME bills nearing day 45, concentration and credit-limit risks, unreconciled bank lines, bad GSTINs, expiring documents, system errors), gives each an owner and a date, escalates it to the admins when the date passes, and closes it with a resolution — or by itself when the problem goes away.gst/auto-irn.ts); a refusal becomes an exception.services/stock-ledger.ts) — each sale posts its cost to Cost of Goods Sold, stock purchases go to Inventory, month end brings Inventory into line with the valuation. Profit is identical to the periodic (Tally) method, which stays the default./analytics/risk): journal anomalies, customer risk scores, collections by each customer's own lateness; dashboard cached until the books change.Benchmarked against Zoho Books, the pieces it had and Rekonza did not are built in:
SMTP_HOST …, see .env.example): invoices with a view-and-pay link, statements, and payment reminders on their own.lib/server/services/portal.ts): opened from a link or by signing in at /portal/login with a six-digit code emailed to them (only a hash kept; ten minutes, five tries). A customer has a home page of what they owe, then quotes (accept, or decline with a reason), invoices (pay online), sales orders, retainers, credit notes, payments, statement and projects; a vendor has purchase orders to accept or decline, bills, vendor credits, payments and statement. Both comment on any of their documents (the business replies from the contact's page), swap files with the business, and keep their own email, phone and addresses up to date. A vendor's new bank account is a request the business approves after checking it by phone, never applied from the portal. Portal Activities reports everything they did.Software Checklist (left menu, and a card on the dashboard; services/checklist.ts) answers each area of the accounting software checklist — company management, security and audit trail, masters, vouchers, inventory, banking, receivables, payables, fixed assets, payroll, GST, budgeting, reporting, integration — with where it is in the app and what the company's own records show: how many assets are on the register, when depreciation last ran, how many bank lines are reconciled. Among the pieces built for it: the fund flow statement, cheque printing on the CTS-2010 leaf, the stock ledger and stock ageing, a collections workbench with promises to pay, balance confirmations for customers and vendors, account groups, bank statements read from Excel in the bank's own layout, and Power BI / Excel feeds (/api/bi/…, read with an API key).
Open the demo book as Admin from the sign-in page.
| Area | What's in it |
|---|---|
| Dashboard | Cash, receivables, payables, profit, compliance alerts |
| Sales | Customers · Items · Estimates · Sales orders · Delivery challans · Invoices · Retainers · Payments · Credit notes · Recurring profiles |
| Purchases | Vendors · Expenses · Purchase orders · Bills (ITC / reverse charge / TDS) · Payment runs · Vendor credits · MSME tracker |
| Banking | Accounts · Reconciliation workspace · Statement import · Rules · Transfers · Cheques & PDCs |
| Accountant | Manual journals · Chart of accounts · Opening balances · Budgets · Recurring journals · Period close · Transaction locks · Audit trail |
| GST & taxes | E-invoices · E-way bills · GSTR-1 · GSTR-3B with the Section 49A set-off order · GSTR-2B reconciliation · TDS & TCS |
| Inventory | Stock on hand · Adjustments · Warehouses |
| Reports | 32 reports, every one derived from the journal, all exportable |
| Settings | Organisation · Numbering · HSN master · Custom fields · Automation · Integrations |
| Portal | Customer-facing view at /portal, currently a signed-in preview |
app/
page.tsx the landing page (static, no session read)
login/ register/ sign in, sign up, and the demo door
(app)/… the application, grouped by module
api/… route handlers; every write goes through a service
portal/ customer-facing surface
components/
brand/logo.tsx the single source of the name, tagline and artwork
ui/ shadcn primitives on Base UI
shared/ layout/ charts/
lib/
server/
ledger/posting the only writer of journal entries
ledger/chart-of-accounts
services/ invoices, bills, payments, banking, GST — the write layer
reports/ TB · P&L · BS · GL · ageing, computed on request
gst/ returns, e-invoicing, ITC reconciliation
seed/ the demo organisation
auth/ argon2id passwords, server-side sessions
tax/gst.ts supply-type resolver + GSTIN checksum
tax/tds.ts section master + threshold logic
api/client.ts the typed browser-side API surface
db/migrations/ hand-numbered SQL, checksum-enforced
The demo organisation is a real row in the database carrying is_demo = 1. That flag is what the app keys off:
npm run db:seed -- --fresh deletes and rebuilds only organisations with it set, so a customer's ledger is never in range of the seed script.Nothing that comes through the sign-up form can set it. A new organisation gets the standard chart of accounts, a Cash in Hand account, numbering that starts at one, and nothing else.
Ask about the books in plain words: "How much does Apex owe us?", "What returns are due this month?", "Which items are running low?", "How are we doing against the budget?". Every figure is read from the same report the screens use: ledger balances, profit and loss, balance sheet, cash, receivables and payables, invoices and bills, sales and expenses, GST, ratios, cash flow, stock, customer and supplier statements, payments, TDS, the compliance calendar, bank reconciliation, projects, payroll, fixed assets, budgets, open quotes and orders, and collections. A report card (key figures, a chart and a table) sits under each answer. The assistant only reads, and a role is offered only the lookups for what it can see: a salesperson's assistant has no payroll or profit lookup to be talked into.
OPENAI_API_KEY set, OpenAI answers (gpt-5-mini unless OPENAI_MODEL says otherwise). It reasons over the figures, compares them and advises.AI_STANDIN=1 allows the stand-in.lib/server/ai/cache.ts): the lookups of one step run side by side; a lookup already made while the books stood still is reused; the same first question asked again before anything in the books changed is answered at once and charged nothing; and OpenAI is given a prompt-cache key so the unchanging part of every request is billed at its cached price. Speed & savings on the AI page shows how it has gone over thirty days.Live IRN registration, and filing returns with the GST system, need a contract with a GST Suvidha Provider; the returns connection is built and switches on with the GSP's details (GST_API_*). Automatic bank feeds need an Account Aggregator licence that accounting software does not hold, or each bank's own API agreement; statements are imported (CSV or Excel) meanwhile. SMS and WhatsApp sending need a provider. Email and online payment are built and switch on with the business's own SMTP account (SMTP_HOST …) and Razorpay keys (Settings → Integrations). The app says what is and is not connected where you would go looking for it, rather than showing a green "Connected" badge over nothing.
The TDS return's FVU text file: the return is laid out as rows for the government's Return Preparation Utility, whose file layout Protean publishes and changes.
From Zoho Books: digital signatures with a DSC token (Zoho does it through a desktop utility that talks to the USB token; a web page cannot reach the token by itself), payment gateways other than Razorpay (each needs the business's own account with it), and the developer extras of its top plans (custom buttons, validation rules, custom modules). Sales returns are handled as Zoho Books handles them, by a credit note with the items, which brings the goods back into stock.
A Vercel deployment with no database configured plays a recording of the demo book instead: every screen and report opens with real figures, and anything that would save says that saving is switched off. middleware.ts answers /api from the files in public/demo-snapshot; nothing else changes. DEMO_SNAPSHOT=1 turns it on anywhere, DEMO_SNAPSHOT=0 turns it off.
To record it again after a change, with the app running against a seeded database: BASE=http://localhost:5001 npx tsx scripts/demo-snapshot.ts. It opens the demo book through its own door, visits every screen, and blocks every write, so the books are left as they were.
The AI assistant answers on the online demo too, from lib/server/ai/demo-recording.json: what every lookup returned for the demo book, for each customer, supplier, item, account and the periods a question is likely to name. With OPENAI_API_KEY set on the deployment, OpenAI answers from those figures, limited per visitor and to DEMO_AI_DAILY_LIMIT questions a day (default 300); without a key, the stand-in answers. Nothing is charged, and a conversation is kept only in the server's memory. Record it again together with the screens: npx tsx --conditions=react-server --env-file=.env.local scripts/demo-ai-snapshot.ts. It only reads.
Vercel runs the app; it does not run the database. You need:
DATABASE_URL (mysql://user:password@host:port/name, as Vercel's integrations set it) is used ahead of the DB_* settings, with TLS. Put it in .env.production.local and run the migrations and the demo book against it from your machine: node --env-file=.env.production.local scripts/migrate.mjs, then npx tsx --conditions=react-server --env-file=.env.production.local scripts/seed.ts.BLOB_READ_WRITE_TOKEN itself.DATABASE_URL (a Vercel database integration adds it), or the DB_* set with DB_SSL=true (and DB_SSL_CA if the provider asks), APP_ENV=production, FIELD_ENCRYPTION_KEY, CRON_SECRET, NEXT_PUBLIC_SITE_URL, and the mail, GSP and e-invoice settings when the business has them. See .env.example.npx tsx --conditions=react-server --env-file=.env.production.local scripts/golive.ts (or Settings → System health once it is running) tests the database and its TLS, every migration, the encryption key, the cron secret, the site address, file storage and the demo door, and lists which connections are live or on a stand-in. It exits non-zero while anything required is missing.vercel.json runs the functions in Mumbai (bom1) and calls /api/cron/sweep once a day for the background work (scheduled entries, retries, webhooks, reports, stock alerts, reminders). On a Pro plan, make it every ten minutes: "*/10 * * * *". Backups are the database host's: turn on its daily backups and point-in-time recovery; npm run db:backup is for a server you run yourself.
npm run golive # is this server set up to keep real books (lib/server/golive.ts)
npm run test:unit # posting engine, money arithmetic, services
npm run test:api # route handlers against a live server
npm run smoke # every route renders with no console errors
npm run flows # end-to-end journeys through the UI
node scripts/onboarding.mjs # landing page, sign-up, and the demo door
lib/print-doc.ts, lib/server/services/document-print.ts): quotes, sales orders, delivery challans (in triplicate, Rule 55), credit notes (naming the invoice, Rule 53), retainer invoices, payment receipts (a receipt voucher with the tax when GST was paid on an advance, Rule 50), purchase orders, vendor credits, payment advices and bills, in the business's invoice template. Each list has a "⋯" menu: print or PDF, email now, send from your own mail app or WhatsApp, copy a link that opens it without signing in; quotes, sales orders and purchase orders clone. Select rows on any list to print them together, one to a page. The portal opens each of a contact's documents the same way. A quote emailed becomes sent, a purchase order emailed is issued.lib/server/reports/statements.ts): on the cash basis a sale counts when it is paid, in the share paid and on the day paid, a bill when it is paid, and anything paid at once on its own date; a credit note set against an invoice counts for nothing, one refunded counts when refunded; the statements still tie.lib/server/services/contact-merge.ts): everything of the one merged away — documents, payments, ledger lines, contact persons, addresses, custom fields, comments, files — moves to the one kept, which also takes any email, phone, PAN or address it lacked; the other is archived pointing at it and its portal links stop. Two different GSTINs never merge, nor a party without a GSTIN that has invoices into one with a GSTIN (it would change past returns).FX_FEED_URL for another source); a rate typed for the day is kept; "Fetch now" does it at once.lib/server/services/landed-cost.ts): freight, duty or clearing on one bill spread over the goods of another (or the same) bill — by quantity, by value or by hand — into their stock value from the charge bill's date, so the cost per unit and everything sold from it include it. A perpetual book also moves it into Inventory; taking it off, or voiding either bill, undoes it.lib/server/gst/gstr3b-form.ts): tables 3.1, 3.1.1, 3.2 by place of supply, 4 (A)(1)–(5), (B), (C), (D), 5, 5.1 and 6.1, in the portal's words, monthly or quarterly. Every figure opens the invoices, bills and journals behind it; blocked credit is shown in 4(A) and reversed in 4(B)(1) per Circular 170/2022; IGST credit is spread where it saves cash (Rule 88A, set-off.ts); interest and late fee follow the due date; the return downloads as the GSTN's JSON or as Excel; the ARN is kept once filed.lib/server/integrations/gst/returns-service.ts), as Zoho's GSTN integration: each GSTIN connected with its portal username and the OTP the portal sends; Push to GSTN for GSTR-1, IFF and GSTR-3B with the portal's status and error report; File with EVC, the ARN kept and the compliance calendar marked; Fetch GSTR-2B into the reconciliation; Fetch details from a GSTIN on customer and vendor forms. It speaks GSTN's taxpayer API with its encryption, through your GSP (GST_API_* in .env.example); without one, a stand-in that behaves like the GSTN sandbox (OTP 575757) answers and files nothing.