{"id":50510094,"url":"https://github.com/kitschpatrol/unplugin-tldraw","last_synced_at":"2026-06-02T19:30:55.448Z","repository":{"id":354246551,"uuid":"1222752136","full_name":"kitschpatrol/unplugin-tldraw","owner":"kitschpatrol","description":"Unplugin for module-style import of local tldraw .tldr files with automatic conversion to SVG or PNG.","archived":false,"fork":false,"pushed_at":"2026-04-27T20:18:14.000Z","size":340,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-27T20:18:16.178Z","etag":null,"topics":["bun","diagram","drawing","esbuild","farm","import","npm-package","nuxt","rolldown","rollup","rspack","sketch","tldr","tldraw","unplugin","vite","webpack","whiteboard"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kitschpatrol.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"license.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-27T17:12:00.000Z","updated_at":"2026-04-27T20:18:04.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/kitschpatrol/unplugin-tldraw","commit_stats":null,"previous_names":["kitschpatrol/unplugin-tldraw"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/kitschpatrol/unplugin-tldraw","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kitschpatrol%2Funplugin-tldraw","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kitschpatrol%2Funplugin-tldraw/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kitschpatrol%2Funplugin-tldraw/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kitschpatrol%2Funplugin-tldraw/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kitschpatrol","download_url":"https://codeload.github.com/kitschpatrol/unplugin-tldraw/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kitschpatrol%2Funplugin-tldraw/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33834010,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-02T02:00:07.132Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bun","diagram","drawing","esbuild","farm","import","npm-package","nuxt","rolldown","rollup","rspack","sketch","tldr","tldraw","unplugin","vite","webpack","whiteboard"],"created_at":"2026-06-02T19:30:53.273Z","updated_at":"2026-06-02T19:30:55.442Z","avatar_url":"https://github.com/kitschpatrol.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!-- title --\u003e\n\n# @kitschpatrol/unplugin-tldraw\n\n\u003c!-- /title --\u003e\n\n\u003c!-- badges --\u003e\n\n[![NPM Package @kitschpatrol/unplugin-tldraw](https://img.shields.io/npm/v/@kitschpatrol/unplugin-tldraw.svg)](https://npmjs.com/package/@kitschpatrol/unplugin-tldraw)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/license/mit/)\n[![CI](https://github.com/kitschpatrol/unplugin-tldraw/actions/workflows/ci.yml/badge.svg)](https://github.com/kitschpatrol/unplugin-tldraw/actions/workflows/ci.yml)\n\n\u003c!-- /badges --\u003e\n\n\u003c!-- short-description --\u003e\n\n**Unplugin for module-style import of local tldraw .tldr files with automatic conversion to SVG or PNG.**\n\n\u003c!-- /short-description --\u003e\n\n## Overview\n\n**A universal bundler plugin to automate the import and conversion of local [tldraw](https://tldraw.dev) `.tldr` files into SVG or PNG image assets.**\n\nBuilt on [unplugin](https://unplugin.unjs.io), it works with Vite, webpack, Rspack, Rollup, Rolldown, esbuild, Farm, Bun, and Nuxt.\n\nThis allows `.tldr` files to be imported just like regular `.webp`, `.jpeg` etc. files in your project:\n\n```ts\n// main.ts\nimport diagram from './assets/architecture.tldr'\n\nconst body = document.querySelector\u003cHTMLDivElement\u003e('body')\nif (body) {\n  body.innerHTML = `\u003cimg src=\"${diagram}\" /\u003e`\n}\n```\n\nThe above converts `./assets/architecture.tldr` into `./assets/architecture-{hash}.svg`, caches the output file, and then resolves the import to the generated image path.\n\nThe plugin provides a global configuration object to customize the conversion process, and also allows overrides on a per-import basis via query parameters on the import path, e.g.:\n\n```ts\nimport diagramPng from './assets/architecture.tldr?format=png\u0026tldr'\n```\n\n_For lower-level processing of `.tldr` files in Node projects or via the command line, please see [@kitschpatrol/tldraw-cli](https://github.com/kitschpatrol/tldraw-cli). This package replaces an earlier Vite-only package of the same concept: [@kitschpatrol/vite-plugin-tldraw](https://github.com/kitschpatrol/vite-plugin-tldraw)._\n\n## Installation\n\n### 1. Install the plugin package\n\n```sh\nnpm install @kitschpatrol/unplugin-tldraw\n```\n\n### 2. Add the plugin to your bundler config\n\n\u003cdetails\u003e\n\u003csummary\u003eVite\u003c/summary\u003e\n\n```ts\n// vite.config.ts\nimport tldraw from '@kitschpatrol/unplugin-tldraw/vite'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  plugins: [tldraw()],\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eRollup\u003c/summary\u003e\n\n```ts\n// rollup.config.js\nimport tldraw from '@kitschpatrol/unplugin-tldraw/rollup'\n\nexport default {\n  plugins: [tldraw()],\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eRolldown\u003c/summary\u003e\n\n```ts\n// rolldown.config.js\nimport tldraw from '@kitschpatrol/unplugin-tldraw/rolldown'\n\nexport default {\n  plugins: [tldraw()],\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003ewebpack\u003c/summary\u003e\n\n```js\n// webpack.config.js\nimport tldraw from '@kitschpatrol/unplugin-tldraw/webpack'\n\nexport default {\n  plugins: [tldraw()],\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eRspack\u003c/summary\u003e\n\n```js\n// rspack.config.js\nimport tldraw from '@kitschpatrol/unplugin-tldraw/rspack'\n\nexport default {\n  plugins: [tldraw()],\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eesbuild\u003c/summary\u003e\n\n```ts\nimport tldraw from '@kitschpatrol/unplugin-tldraw/esbuild'\nimport { build } from 'esbuild'\n\nbuild({ plugins: [tldraw()] })\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eFarm\u003c/summary\u003e\n\n```ts\n// farm.config.js\nimport tldraw from '@kitschpatrol/unplugin-tldraw/farm'\n\nexport default {\n  plugins: [tldraw()],\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eBun\u003c/summary\u003e\n\n```ts\n// build.ts\nimport tldraw from '@kitschpatrol/unplugin-tldraw/bun'\n\nBun.build({\n  entrypoints: ['./index.ts'],\n  plugins: [tldraw()],\n})\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eNuxt\u003c/summary\u003e\n\n```ts\n// nuxt.config.ts\nexport default defineNuxtConfig({\n  modules: ['@kitschpatrol/unplugin-tldraw/nuxt'],\n})\n```\n\n\u003c/details\u003e\n\n### 3. Configure TypeScript\n\n_Skip this step if you're using plain JavaScript._\n\nAdd the extension declarations to your [types](https://www.typescriptlang.org/tsconfig#types) in tsconfig.json:\n\n```json\n{\n  \"compilerOptions\": {\n    \"types\": [\"@kitschpatrol/unplugin-tldraw/client\"]\n  }\n}\n```\n\nAlternately, you can add a triple-slash package dependency directive to your global types file (e.g. `env.d.ts` or similar):\n\n```ts\n/// \u003creference types=\"@kitschpatrol/unplugin-tldraw/client\" /\u003e\n```\n\nThis step should take care of errors like:\n\n```sh\nCannot find module './assets/test-sketch.tldr' or its corresponding type declarations.ts(2307)\n```\n\n#### 4. Install VS Code preview extension (Optional)\n\nIf you're using VS Code, an [extension](https://github.com/kitschpatrol/vscode-tldraw-preview) is available to provide hover-previews for tldr file paths:\n\nInstall the extension from the [Marketplace](https://marketplace.visualstudio.com/items?itemName=kitschpatrol.tldr-preview), or run the following in VS Code's command palette:\n\n```sh\next install kitschpatrol.tldr-preview\n```\n\n## Usage\n\nSave your tldraw project to a `.tldr` file.\n\nAdd it to your project, most likely in an `assets` folder.\n\nThen simply import the `.tldr` file to get a working asset path:\n\n```ts\n// example.ts\nimport diagram from './assets/test-sketch.tldr'\n\n// Logs a path to the generated SVG\nconsole.log(diagram)\n```\n\nSee the sections below for additional conversion options.\n\n## Plugin options\n\n`@kitschpatrol/unplugin-tldraw` inherits most of the configuration flags available in [@kitschpatrol/tldraw-cli](https://github.com/kitschpatrol/tldraw-cli#command-line-usage).\n\n### `Options`\n\n| Key                        | Type                 | Description                                                                                                                                                        | Default                          |\n| -------------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------- |\n| `defaultImageOptions`      | `TldrawImageOptions` | Default options for the image conversion process. See section below.                                                                                               | _See section below_              |\n| `cacheEnabled`             | `boolean`            | Cache generated image files. Hashes based on the source `.tldr` content _and_ any image options or import query parameters ensure the cache regenerates as needed. | `true`                           |\n| `cacheDirectory`           | `string`             | Directory to store cached image files.                                                                                                                             | `\"./node_modules/.cache/tldraw\"` |\n| `maxConcurrentConversions` | `number`             | Maximum number of concurrent `.tldr` conversions. Each conversion spawns a headless browser, so lower values reduce system load.                                   | `2`                              |\n| `pruneCacheOnBuild`        | `boolean`            | Delete cached files that were not used during a build. Useful for keeping the cache directory tidy.                                                                | `false`                          |\n| `verbose`                  | `boolean`            | Log information about the conversion process to the console.                                                                                                       | `false`                          |\n\n### `TldrawImageOptions`\n\n| Key           | Type             | Description                                                                                                                                      | Default |\n| ------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ------- |\n| `format`      | `\"png\" \\| \"svg\"` | Output image format.                                                                                                                             | `\"svg\"` |\n| `transparent` | `boolean`        | Output image with a transparent background.                                                                                                      | `false` |\n| `dark`        | `boolean`        | Output a dark theme version of the image.                                                                                                        | `false` |\n| `stripStyle`  | `boolean`        | Remove `\u003cstyle\u003e` elements from SVG output, useful to lighten the load of embedded fonts or if you are providing your own stylesheet for the SVG. | `false` |\n| `padding`     | `number`         | Set a specific padding amount around the exported image.                                                                                         | `32`    |\n| `scale`       | `number`         | Set a sampling factor for raster image exports.                                                                                                  | `1`     |\n\n### Plugin options example\n\nConfigure the plugin to always generate PNGs with a transparent background, and to log conversion details:\n\n```ts\n// vite.config.ts\nimport tldraw from '@kitschpatrol/unplugin-tldraw/vite'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  plugins: [\n    tldraw({\n      defaultImageOptions: {\n        format: 'png',\n        transparent: true,\n      },\n      verbose: true,\n    }),\n  ],\n})\n```\n\nThe `@kitschpatrol/unplugin-tldraw` package also exports `Options` and `TldrawImageOptions` types for your convenience.\n\n## Import path options\n\nImport directives may include query parameters to set image conversion options on a per-import basis.\n\nQuery parameters take precedence over `defaultImageOptions` set at plugin instantiation in your bundler config.\n\nBoolean parameters accept `true` or `false` (e.g. `?dark=true`, `?dark=false`). A bare key like `?dark` (with no value) is shorthand for `true`. Any other value is ignored with a warning.\n\n_Note: Due to [constraints in TypeScript's module declaration wildcards](https://github.com/microsoft/TypeScript/issues/38638), the import path must be suffixed with `\u0026tldr` or `\u0026tldraw` when query parameters are used._\n\n### Additional query parameter options\n\nIn addition to all `TldrawImageOptions`, query parameters also accept additional options for selecting specific parts of a sketch:\n\n| Key     | Type                  | Description                                                                                                                                                                              | Default     |\n| ------- | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |\n| `frame` | `string \\| undefined` | When defined, outputs only a specific frame from the `.tldr` file. Provide either the frame name or its shape ID, e.g. `Frame 1`. Slugified frame names will also match, e.g. `frame-1`. | `undefined` |\n| `page`  | `string \\| undefined` | When defined, outputs only a specific page from the `.tldr` file. Provide either the page name or its page ID, e.g. `Page 1`. Slugified page names will also match, e.g. `page-1`.       | `undefined` |\n\n### Import path query parameter examples\n\n```ts\n// example.ts\nimport diagramFrame from './assets/test-sketch-three-frames.tldr?frame=frame-1\u0026tldr'\nimport diagramDark from './assets/test-sketch.tldr?dark=true\u0026tldr'\nimport diagramPng from './assets/test-sketch.tldr?format=png\u0026tldr'\nimport diagramTransparentPng from './assets/test-sketch.tldr?format=png\u0026transparent=true\u0026tldr'\n\n// Logs a PNG path\nconsole.log(diagramPng)\n\n// Logs a dark-mode SVG path\nconsole.log(diagramDark)\n\n// Logs a transparent-background PNG path\nconsole.log(diagramTransparentPng)\n\n// Logs an SVG path for \"Frame 1\" in the source `.tldr`\nconsole.log(diagramFrame)\n```\n\n## Implementation notes\n\nThis tool is not a part of the official tldraw project.\n\nBehind the scenes, the plugin calls [@kitschpatrol/tldraw-cli](https://github.com/kitschpatrol/tldraw-cli)'s Node API to generate image files from `.tldr` files, and then resolves the import to the generated file path.\n\nBecause [`tldraw-cli`](https://github.com/kitschpatrol/tldraw-cli) relies on the browser automation tool [Puppeteer](https://pptr.dev) for its output, conversion can be a bit slow (on the order of a second or two). To mitigate this, the plugin provides several layers of optimization:\n\n- **Content-addressed caching**: Generated images are named with a hash of the source content and conversion options. If the source hasn't changed, conversion is skipped entirely.\n- **Persistent cache**: A JSON lookup table (`.tldraw-plugin-cache.json`) persists across builds, so even cold starts benefit from prior conversions. Stale entries are automatically cleaned.\n- **Request deduplication**: If the same `.tldr` file is imported concurrently (e.g. from multiple modules), only one conversion runs and the result is shared.\n- **Concurrency limiting**: At most `maxConcurrentConversions` (default: 2) conversions run in parallel, preventing system overload from too many headless browser instances.\n\nThe tldraw project evolves quickly. This plugin is somewhat brittle because the tldraw website, the tldraw library, the `.tldr` file format, and the underlying CLI export tool must all be in harmonious alignment for exports to work.\n\nThis plugin succeeds [@kitschpatrol/vite-plugin-tldraw](https://github.com/kitschpatrol/vite-plugin-tldraw), extending support to all major bundlers via [unplugin](https://unplugin.unjs.io).\n\n## Migrating from `vite-plugin-tldraw`\n\nIf you're upgrading from [`@kitschpatrol/vite-plugin-tldraw`](https://github.com/kitschpatrol/vite-plugin-tldraw), the surface area is mostly the same. The notable changes are listed below.\n\n### Package and import path\n\nReplace the dependency:\n\n```sh\nnpm uninstall @kitschpatrol/vite-plugin-tldraw\nnpm install @kitschpatrol/unplugin-tldraw\n```\n\nUpdate the bundler config to import from the bundler-specific subpath. For Vite:\n\n_Before_:\n\n```ts\nimport tldraw from '@kitschpatrol/vite-plugin-tldraw'\n```\n\n_After_:\n\n```ts\nimport tldraw from '@kitschpatrol/unplugin-tldraw/vite'\n```\n\nFor other bundlers (webpack, Rollup, Rolldown, esbuild, Rspack, Farm, Bun), see the [Installation](#2-add-the-plugin-to-your-bundler-config) section above for the correct subpath.\n\n### TypeScript client types\n\nUpdate the types reference in `tsconfig.json` (or your `env.d.ts`):\n\n_Before_:\n\n```jsonc\n{\n  \"types\": [\"@kitschpatrol/vite-plugin-tldraw/client\"],\n}\n```\n\n_After_:\n\n```jsonc\n{\n  \"types\": [\"@kitschpatrol/unplugin-tldraw/client\"],\n}\n```\n\n### Removed: `returnMetadata`\n\nThe `returnMetadata` plugin option is gone. Imports always resolve to a `string` path now, never to a `{ src, width, height, format }` object. If you need image dimensions, read them from the resolved path with [`image-size`](https://www.npmjs.com/package/image-size) or a similar library at runtime.\n\n### New plugin options\n\nThree new keys are available on the [plugin options](#options) object:\n\n- `cacheDirectory` — customize where converted images are stored.\n- `maxConcurrentConversions` — cap the number of headless-browser exports running in parallel (default `2`).\n- `pruneCacheOnBuild` — delete cached files that weren't used during a build.\n\n### Cache location\n\nThe cache moved from `node_modules/.vite/tldr/` to `./node_modules/.cache/tldraw/` (configurable via `cacheDirectory`). The old directory is not reused and is safe to delete.\n\n### Unchanged\n\nImport-path query parameters (e.g. `?format=png\u0026tldr`), the `\u0026tldr` / `\u0026tldraw` suffix requirement, the `frame` and `page` selectors, every key on `TldrawImageOptions` (`format`, `dark`, `transparent`, `stripStyle`, `padding`, `scale`), and the underlying [`@kitschpatrol/tldraw-cli`](https://github.com/kitschpatrol/tldraw-cli) conversion engine all behave exactly as before.\n\n## Maintainers\n\n[kitschpatrol](https://github.com/kitschpatrol)\n\n\u003c!-- contributing --\u003e\n\n## Contributing\n\n[Issues](https://github.com/kitschpatrol/unplugin-tldraw/issues) are welcome and appreciated.\n\nPlease open an issue to discuss changes before submitting a pull request. Unsolicited PRs (especially AI-generated ones) are unlikely to be merged.\n\nThis repository uses [@kitschpatrol/shared-config](https://github.com/kitschpatrol/shared-config) (via its `ksc` CLI) for linting and formatting, plus [MDAT](https://github.com/kitschpatrol/mdat) for readme placeholder expansion.\n\n\u003c!-- /contributing --\u003e\n\n\u003c!-- license --\u003e\n\n## License\n\n[MIT](license.txt) © [Eric Mika](https://ericmika.com)\n\n\u003c!-- /license --\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkitschpatrol%2Funplugin-tldraw","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkitschpatrol%2Funplugin-tldraw","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkitschpatrol%2Funplugin-tldraw/lists"}