{"_id":"@grandbusta/spyde","_rev":"4-78d6d3780ed7216d64a35ad26a4ee7dc","name":"@grandbusta/spyde","dist-tags":{"latest":"0.2.1"},"versions":{"0.1.0":{"name":"@grandbusta/spyde","version":"0.1.0","keywords":["pdf","pdfkit","layout","declarative","invoice","report","node","typescript"],"license":"MIT","_id":"@grandbusta/spyde@0.1.0","maintainers":[{"name":"grandbusta","email":"bustajay30@gmail.com"}],"homepage":"https://github.com/Grandbusta/spyde#readme","bugs":{"url":"https://github.com/Grandbusta/spyde/issues"},"dist":{"shasum":"cccd50fc702d8893d4b37cc0e0d2fa6627b6ffc5","tarball":"https://registry.npmjs.org/@grandbusta/spyde/-/spyde-0.1.0.tgz","fileCount":51,"integrity":"sha512-ZGhNpff+M/GNiX7chBrIRMVKnqEh6OA3aT1e2z6qRYXAmwEA+smeBkHGi54bPOrv49nK3SRok6HrakiCX9B/Aw==","signatures":[{"sig":"MEUCIQCZhqf6yg3Of/s27f7cz+UN2u/joxMtPa0zuJfw+ZBb7gIgX2skERzyOBGsnqDAchK4CezPH3//ik462TgEMshhIw4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":69981},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"3180b14fc5f422a212846f8cd6ff71da489f0e18","scripts":{"test":"tsc -p tsconfig.test.json && node --test .test-out/test/","build":"tsc -p tsconfig.json","clean":"rm -rf dist .test-out","example":"tsc -p tsconfig.test.json && node .test-out/examples/invoice.js","typecheck":"tsc -p tsconfig.json --noEmit","prepublishOnly":"npm run clean && npm run build && npm test"},"_npmUser":{"name":"grandbusta","email":"bustajay30@gmail.com"},"repository":{"url":"git+https://github.com/Grandbusta/spyde.git","type":"git"},"_npmVersion":"10.8.2","description":"Declarative, composable PDF layout for Node on top of PDFKit. No browser.","directories":{},"_nodeVersion":"20.19.4","dependencies":{"pdfkit":"^0.20.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^7.0.2","@types/node":"^20.19.43","@types/pdfkit":"^0.17.6"},"_npmOperationalInternal":{"tmp":"tmp/spyde_0.1.0_1789383833051_0.5828559963401843","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@grandbusta/spyde","version":"0.1.1","keywords":["pdf","pdfkit","layout","declarative","invoice","report","node","typescript"],"license":"MIT","_id":"@grandbusta/spyde@0.1.1","maintainers":[{"name":"grandbusta","email":"bustajay30@gmail.com"}],"homepage":"https://github.com/Grandbusta/spyde#readme","bugs":{"url":"https://github.com/Grandbusta/spyde/issues"},"dist":{"shasum":"b952a5e96e3ddcf9cd232e84297da48839e00183","tarball":"https://registry.npmjs.org/@grandbusta/spyde/-/spyde-0.1.1.tgz","fileCount":51,"integrity":"sha512-6++aW5MkIWREAQXWqp0u+a7lgaOLe0ADoY+jOz1xvw/Y1ASAuC7bSs1Qs/fQx1dM20HHiXTCoWBVUoVxR5cKpg==","signatures":[{"sig":"MEUCIA8+89OmdZ5K5kTRQ6w4cDnQGqeBHzUGxiUiLnXrDOUvAiEAqPxYIDtC/16AYqFcp1E+ELQfgxKjoRLS6pR6SI2hkvc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":69967},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"7493cd2f275bd41a2a9f49b43f732cd9fc260a65","scripts":{"test":"tsc -p tsconfig.test.json && node --test .test-out/test/","build":"tsc -p tsconfig.json","clean":"rm -rf dist .test-out","example":"tsc -p tsconfig.test.json && node .test-out/examples/invoice.js","typecheck":"tsc -p tsconfig.json --noEmit","prepublishOnly":"npm run clean && npm run build && npm test"},"_npmUser":{"name":"grandbusta","email":"bustajay30@gmail.com"},"repository":{"url":"git+https://github.com/Grandbusta/spyde.git","type":"git"},"_npmVersion":"10.8.2","description":"Declarative, composable PDF layout for Node on top of PDFKit. No browser.","directories":{},"_nodeVersion":"20.19.4","dependencies":{"pdfkit":"^0.20.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^7.0.2","@types/node":"^20.19.43","@types/pdfkit":"^0.17.6"},"_npmOperationalInternal":{"tmp":"tmp/spyde_0.1.1_1789384399493_0.46134617252360677","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@grandbusta/spyde","version":"0.2.0","keywords":["pdf","pdfkit","layout","declarative","invoice","report","node","typescript"],"license":"MIT","_id":"@grandbusta/spyde@0.2.0","maintainers":[{"name":"grandbusta","email":"bustajay30@gmail.com"}],"homepage":"https://github.com/Grandbusta/spyde#readme","bugs":{"url":"https://github.com/Grandbusta/spyde/issues"},"dist":{"shasum":"e959671daf7d1dc4d576f561b61691831a11ebc4","tarball":"https://registry.npmjs.org/@grandbusta/spyde/-/spyde-0.2.0.tgz","fileCount":78,"integrity":"sha512-nKtWTez4qz4xrb/RkNpf3yBGimFhtj/Dv4OmBrkoDfRAvo37kQEk5Ds7qMt9QIpWgicgsir3iifd1gLEvpYnVg==","signatures":[{"sig":"MEUCIQCcxQYz0s36IUEo0ggH5uh0FODFKoQdincQhTdYkCYlkAIgbuu2igE24pAj/FwA6r2sdIff1ItiwPgnVWNQoX5KCHM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIFRi9EErNHqn/7HJZv5jnt384zyPo/d/N6phvTGwk5d1AiBTAPGdxY3T/INq9hjsf/g/N7NKAwcbNTW2zcdwBIoETg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":164861},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"4bd8b33c9e24481ff470974f5e44fd8263c79261","scripts":{"test":"tsc -p tsconfig.test.json && node --test .test-out/test/","build":"tsc -p tsconfig.json","clean":"rm -rf dist .test-out","example":"tsc -p tsconfig.test.json && node .test-out/examples/invoice.js && node .test-out/examples/statement.js","preview":"tsc -p tsconfig.test.json && node .test-out/examples/preview/server.js","docs:dev":"npm --prefix docs run dev","typecheck":"tsc -p tsconfig.json --noEmit","docs:build":"npm --prefix docs run build","docs:preview":"npm --prefix docs run preview","prepublishOnly":"npm run clean && npm run build && npm test"},"_npmUser":{"name":"grandbusta","email":"bustajay30@gmail.com"},"repository":{"url":"git+https://github.com/Grandbusta/spyde.git","type":"git"},"_npmVersion":"10.8.2","description":"Declarative, composable PDF layout for Node on top of PDFKit. No browser.","directories":{},"_nodeVersion":"20.19.4","dependencies":{"pdfkit":"^0.20.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^7.0.2","@types/node":"^20.19.43","@types/pdfkit":"^0.17.6"},"_npmOperationalInternal":{"tmp":"tmp/spyde_0.2.0_1789784002524_0.756065294769902","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"_id":"@grandbusta/spyde@0.2.1","bugs":{"url":"https://github.com/Grandbusta/spyde/issues"},"dist":{"shasum":"4790e2ed500b19ab017b68f955713756d7755528","tarball":"https://registry.npmjs.org/@grandbusta/spyde/-/spyde-0.2.1.tgz","fileCount":81,"integrity":"sha512-li6S9mfH0QIMPMprcUtzVEWReo9mS+6yYfed5swLQ+pKEFA+2XKJyx86XgQ/Ft/JH5K+ov444bZHqi7NVmEp5g==","signatures":[{"sig":"MEUCIB83vVaBBS2rQ4y9zf771oY/oKpT4IpsmrOKOC6RjJ+qAiEA4qAf1vvn2vUi6US1HTAoU6u3hZb/3XZmQkkDYEBYST0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCICxXm3qU1se1TtsKlfmt9yX/nme2diEvfCFgg4HoIqnzAiAvkOX819hN6BPazUrWNEAUw2kkKqX7VFvlgTcU4EkcwA=="}],"unpackedSize":180179},"main":"./dist/index.js","name":"@grandbusta/spyde","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"8ea92b3bf187ef50513847cc88f29c8b80338d91","license":"MIT","scripts":{"test":"tsc -p tsconfig.test.json && node --test .test-out/test/","build":"tsc -p tsconfig.json","clean":"rm -rf dist .test-out","example":"tsc -p tsconfig.test.json && node .test-out/examples/invoice.js && node .test-out/examples/statement.js","preview":"tsc -p tsconfig.test.json && node .test-out/examples/preview/server.js","docs:dev":"npm --prefix docs run dev","typecheck":"tsc -p tsconfig.json --noEmit","docs:build":"npm --prefix docs run build","docs:preview":"npm --prefix docs run preview","prepublishOnly":"npm run clean && npm run build && npm test"},"version":"0.2.1","_npmUser":{"name":"grandbusta","email":"bustajay30@gmail.com"},"homepage":"https://github.com/Grandbusta/spyde#readme","keywords":["pdf","pdfkit","layout","declarative","invoice","report","node","typescript"],"repository":{"url":"git+https://github.com/Grandbusta/spyde.git","type":"git"},"_npmVersion":"10.8.2","description":"Declarative, composable PDF layout for Node on top of PDFKit. No browser.","directories":{},"maintainers":[{"name":"grandbusta","email":"bustajay30@gmail.com"}],"_nodeVersion":"20.19.4","dependencies":{"pdfkit":"^0.20.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^7.0.2","@types/node":"^20.19.43","@types/pdfkit":"^0.17.6"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/spyde_0.2.1_1789909362578_0.7215950657068508"}}},"time":{"created":"2026-09-14T11:03:52.854Z","modified":"2026-09-20T13:02:42.797Z","0.1.0":"2026-09-14T11:03:53.188Z","0.1.1":"2026-09-14T11:13:19.634Z","0.2.0":"2026-09-19T02:13:22.613Z","0.2.1":"2026-09-20T13:02:42.661Z"},"bugs":{"url":"https://github.com/Grandbusta/spyde/issues"},"license":"MIT","homepage":"https://github.com/Grandbusta/spyde#readme","keywords":["pdf","pdfkit","layout","declarative","invoice","report","node","typescript"],"repository":{"url":"git+https://github.com/Grandbusta/spyde.git","type":"git"},"description":"Declarative, composable PDF layout for Node on top of PDFKit. No browser.","maintainers":[{"name":"grandbusta","email":"bustajay30@gmail.com"}],"readme":"# Spyde\n\nDeclarative PDF layout for Node. No browser.\n\nDescribe a document as a tree of functions. Spyde works out where everything\ngoes, breaks it across pages, and draws it with PDFKit. You never type an x\nor a y.\n\n**Documentation:** https://grandbusta.github.io/spyde/\n\n## Install\n\n```sh\nnpm install @grandbusta/spyde\n# or\nyarn add @grandbusta/spyde\n```\n\nNode 20 or newer. PDFKit is the only runtime dependency. TypeScript types are included.\n\n## Example\n\n```ts\nimport { render, column, row, text, fill, table } from \"@grandbusta/spyde\";\n\nconst money = (n: number) => `€${n.toFixed(2)}`;\nconst entries = [\n  { item: \"LG Speakers\",  qty: 1, total: 227.99 },\n  { item: \"Apple iPhone\", qty: 2, total: 1999.99 },\n];\n\nconst doc = column([\n  row([\n    fill(text(\"ACME Ltd\", { size: 20, font: \"Helvetica-Bold\" })),\n    fill(text(\"Invoice #1042\", { align: \"right\" })),\n  ]),\n  table(entries, {\n    columns: [\n      { label: \"Item\",  key: \"item\",  share: 2 },\n      { label: \"Qty\",   key: \"qty\",   align: \"right\" },\n      { label: \"Total\", key: \"total\", align: \"right\", format: money },\n    ],\n    rowPadding: { x: 12, y: 8 },\n    header: { background: \"#f2f2f2\" },\n  }),\n  row([text(\"Total due\"), text(money(2227.98))], { justify: \"between\", margin: { top: 16 } }),\n], { gap: 8 });\n\nconst pdf = await render(doc);   // Uint8Array, ready to write or send\n```\n\nEvery function takes its content first and its settings second, so a call\nreads the way it works.\n\n## Why\n\nMaking a PDF in Node today means drawing it by hand with PDFKit, computing\nevery coordinate, or writing HTML and printing it through a headless\nbrowser, which ships Chromium to make a receipt. Spyde is the middle: a\nsmall layout engine on PDFKit, with PDFKit's speed and footprint and a\ndeclarative API.\n\nColumns and tables break across pages. Table headers repeat. The same\nlayout can also be rendered as an HTML fragment for a live preview that\nmatches the PDF line for line.\n\nThe [documentation](https://grandbusta.github.io/spyde/) covers the API,\ntables, pages, text and images, the live preview, and how it works.\n\n## Development\n\n```sh\nnpm install\nnpm run build      # tsc -> dist/\nnpm test           # node --test against compiled sources\nnpm run example    # writes examples/*.pdf\nnpm run preview    # live preview server on http://localhost:8787\nnpm run docs:dev   # documentation site with hot reload\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md"}