Node.js spreadsheet formula engine for services
Use @bilig/headless when a Node.js service needs spreadsheet formulas as part
of its own runtime. The useful case is not “make a prettier spreadsheet.” It is
“accept inputs, update workbook state, recalculate formulas, persist the
document, and return values that were actually read back from the engine.”
That shows up in ordinary backend work:
- pricing rules that business users still think about as spreadsheet formulas
- invoice, quote, commission, or usage-billing checks inside an API route
- forecasts and variance reports in queue workers
- coding-agent tools that must prove a workbook edit happened
- tests that need a formula-backed fixture instead of a hand-coded math clone
If you only need to write an XLSX file for Excel to open later, use an XLSX
library. If you need maximum Excel-function coverage today, evaluate
HyperFormula first. If you need a small TypeScript WorkPaper object that a Node
process can mutate, verify, and save as JSON, @bilig/headless is the slice to
try.
What the engine owns
@bilig/headless gives the service a WorkPaper object. A WorkPaper is a
programmatic workbook with sheets, cell addresses, formulas, computed values,
structural edits, and persistence helpers.
The important boundary is readback. Do not trust that a service “wrote the formula” just because a string was assigned. Read the calculated cell value through the WorkPaper API, serialize the document, restore it, and read the same value again. That is the path the package is built around.
Quick smoke test
Run this from an empty directory:
mkdir bilig-formula-engine-eval
cd bilig-formula-engine-eval
npm init -y
npm pkg set type=module
npm install @bilig/headless
npm install -D tsx typescript @types/node
cat > formula-engine-smoke.ts <<'EOF'
import { WorkPaper } from '@bilig/headless'
type NumericCell = {
value: number
}
function readNumber(cell: unknown, label: string): number {
if (typeof cell === 'object' && cell !== null && typeof (cell as NumericCell).value === 'number') {
return (cell as NumericCell).value
}
throw new Error(`Expected ${label} to be numeric, got ${JSON.stringify(cell)}`)
}
const workbook = WorkPaper.buildFromSheets({
Plan: [
['Metric', 'Value'],
['Customers', 80],
['Price', 49],
['Discount', 0.08],
],
Summary: [
['Metric', 'Value'],
['Net revenue', '=Plan!B2*Plan!B3*(1-Plan!B4)'],
],
})
const sheet = workbook.getSheetId('Summary')
if (sheet === undefined) {
throw new Error('Summary sheet was not created')
}
const netRevenue = readNumber(workbook.getCellValue({ sheet, row: 1, col: 1 }), 'net revenue')
if (netRevenue !== 3606.4) {
throw new Error(`Unexpected formula readback: ${netRevenue}`)
}
console.log({ netRevenue, verified: true })
EOF
npx tsx formula-engine-smoke.ts
Expected output:
{ "netRevenue": 3606.4, "verified": true }
That tiny check proves three things at once: multi-sheet workbook creation, formula evaluation, and computed readback from Node.
When it fits
Start here when the service needs a workbook model, not just isolated formula functions.
| Need | Why @bilig/headless helps |
|---|---|
| Put spreadsheet formulas behind an API | The service can build a WorkPaper, edit input cells, and return computed cells. |
| Let an agent edit a workbook safely | The agent can report exact changed cells and post-write readback instead of only narrating intent. |
| Persist formula-backed state | Export the WorkPaper document, store JSON, restore it later, and verify formulas still calculate. |
| Keep examples runnable | The repo includes invoice, budget variance, subscription MRR, quote approval, and capacity examples. |
When to choose something else
Use a different tool when the job is outside this package’s current shape:
- Use ExcelJS or SheetJS-style tooling when the main product is an XLSX file with styles, tables, images, or import/export fidelity.
- Use HyperFormula when the primary need is broad, mature Excel-compatible formula coverage inside a headless calculation engine.
- Use a visual spreadsheet grid when people need to edit cells directly in the browser.
- Do not choose
biligexpecting a finished Excel clone. The compatibility boundaries are public because the project is still early.
Evaluation path
If the smoke test matches your use case, run the maintained example next:
git clone https://github.com/proompteng/bilig.git
cd bilig
pnpm --dir examples/headless-workpaper install --ignore-workspace
pnpm --dir examples/headless-workpaper run start
pnpm --dir examples/headless-workpaper run agent:verify
Then inspect the focused examples:
- invoice totals
- budget variance alerts
- subscription MRR forecast
- quote approval threshold
- fulfillment capacity plan
- serverless WorkPaper API route
Related docs
- Five Node.js workbook automation examples
- WorkPaper Node service recipe
- Excel file as a calculation engine in Node.js
- Persist formula-backed WorkPaper documents in Node
- Headless spreadsheet engine comparison for Node services and agents
- JavaScript spreadsheet library for Node services
- SheetJS and ExcelJS alternative for formula-backed workbook APIs
- HyperFormula alternative for headless WorkPaper workflows
- Where bilig is not Excel-compatible yet
- Starter issues for first-time contributors
Repository and release notes: https://github.com/proompteng/bilig.
If it almost matches but a gap blocks adoption, open an implementation gap discussion: https://github.com/proompteng/bilig/discussions/new?category=general.