npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@richardmcquiston01/unofficial-lb-writer

v0.2.3

Published

Unofficial framework-agnostic TypeScript library for writing LightBurn-compatible (.lbrn2) project files.

Readme

@richardmcquiston01/unofficial-lb-writer

Table of Contents

| Overview | Getting Started | API Reference | Development | Buy Me a Coffee | License | Copyright |

Overview

This is an unofficial TypeScript package that writes LightBurn project files (.lbrn2). LightBurn is software for laser cutters and engravers. This project is not tied to or endorsed by LightBurn Software.

The package is a low-level writer. It knows nothing about your app's document model. You map your own data onto its builder. It has no runtime dependencies and works with any framework. It also fills in {{token}} placeholders in an existing .lbrn2 file.

Back to Top

Getting Started

Prerequisites

  • Node.js 20 or newer, or Bun 1.1 or newer
  • A TypeScript or JavaScript project that targets ES2022 or newer

Installation

bun add @richardmcquiston01/unofficial-lb-writer

You can also use npm install @richardmcquiston01/unofficial-lb-writer.

Usage

Create a project, add a cut setting, add a shape, and write the XML.

import { createLbrn2Project, IDENTITY } from '@richardmcquiston01/unofficial-lb-writer';

const project = createLbrn2Project();

const cutIndex: number = project.addCutSetting({
  name: 'Cut',
  type: 'Cut',
  maxPower: 80,
  speed: 10,
});

project.addRect(cutIndex, IDENTITY, 20, 10, 0);

const lbrn2Xml: string = project.toXml();

Save the result with a .lbrn2 extension and open it in LightBurn.

Each cut setting returns an index. Shapes use that index to pick their layer. The package keeps cut settings in the order you add them. It does not remove duplicates. Each shape is placed with a matrix, which is LightBurn's own <XForm> format.

To fill in an existing template, use the three template functions:

import {
  assertLbrn2Format,
  extractLbrn2Tokens,
  renderLbrn2File,
} from '@richardmcquiston01/unofficial-lb-writer';

const xml: string = await fetch('/templates/name-tag.lbrn2').then((r) => r.text());

assertLbrn2Format(xml); // throws if the file is not a .lbrn2 file

const tokens: string[] = extractLbrn2Tokens(xml); // e.g. ['FirstName', 'LastName']

const output: string = renderLbrn2File(
  xml,
  [{ token: 'FirstName', defaultValue: 'Guest' }, { token: 'LastName' }],
  { FirstName: 'Jane', LastName: 'Smith' }
);

Reading and substituting into an existing .lbrn2 file

import {
  assertLbrn2Format,
  extractLbrn2Tokens,
  renderLbrn2File,
} from '@richardmcquiston01/unofficial-lb-writer';

const xml = await fetch('/templates/name-tag.lbrn2').then((r) => r.text());

assertLbrn2Format(xml); // throws if invalid

const tokens = extractLbrn2Tokens(xml); // e.g. ['FirstName', 'LastName']

const output = renderLbrn2File(
  xml,
  [{ token: 'FirstName', defaultValue: 'Guest' }, { token: 'LastName' }],
  { FirstName: 'Jane', LastName: 'Smith' }
);

.lbrn2 files are plain XML text (not a ZIP archive), so these functions work directly on strings. renderLbrn2File does plain text substitution on the raw XML -- LightBurn re-renders its own fonts from stored text, so unlike xTool Studio's .xcs/.xs there's no glyph outline data to regenerate when text changes.

Values are inserted literally in a single pass: $ sequences are not expanded, and a value that contains another variable's {{token}} is not substituted again. Values are not XML-escaped, so run them through escapeXml first if they may contain &, <, >, or ".

Examples

See EXAMPLES.md for more examples. They cover moving and turning shapes, using many layers, adding images, and filling in templates.

Back to Top

API Reference

See API.md for every function, with tables for the project builder, the matrix helpers, and the template functions.

Back to Top

Development

Install the packages, then run the checks:

bun install
bun run typecheck
bun run test
bun run build

Back to Top

Buy Me a Coffee

If this app, code, or repository has helped you or someone you know, please consider donating. I appreciate any help to offset the costs of development and/or AI Credits.

Donate via Stripe, or scan:

Donate via Stripe

Back to Top

License

Apache 2

Back to Top

Copyright

(c)2026 Richard McQuiston. All rights reserved.

Back to Top