CLI tool
shadcn-labs/pdfcn avatar
shadcn-labs/pdfcn

shadcn-labs/pdfcn: copy-and-paste PDF components with no releases, two domains and one missing workspace

Beautiful pdf components, built on Takumi and Forme. 100% Free, Zero config, one command setup.

2,852 stars141 forksTypeScriptMIT

At a glance

What is it?
pdfcn hands React developers PDF components built on Takumi and Forme, distributed as source you own rather than a dependency. Its own plumbing is where the interesting detail sits: every root task is filtered to a single app, the linter configs and the check script name different tools, and the workspace globs point at a directory the root does not have.
Who is it for?
This fits teams that already ship shadcn/ui components and want PDF output as source files in the same repository, with the choice between two rendering bases left open.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 11 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 4, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The description promises one command setup and the page prints no command

The repository description ends with three claims: 100% Free, Zero config, one command setup. The page itself carries none of them as something you can type. There is no shell block anywhere in it, no package name to install and no CLI invocation. What it does carry is a pointer to https://pdfcn.vercel.app/docs/installation, and a features line saying the components use the same registry format and CLI workflow as shadcn/ui. That sentence names the mechanism without writing the command, which is a deliberate choice for a registry based project and an unhelpful one for anyone deciding from this page alone. The zero config claim has the same shape: it appears as a feature bullet promising sensible defaults, and the free claim appears as prose rather than as a pricing page. Every artifact the page promises, tables, forms, charts, invoices, reports, is reachable only through the documentation site.

The workspace globs name packages/* and the root listing has no packages directory

The root package.json declares a private, ES module package with workspaces of apps/* and packages/*. The top level of the repository holds an apps/ directory and no packages/ directory at all. The workspace root also carries pnpm-workspace.yaml and pnpm-lock.yaml, so the pnpm side of the same declaration is present, but the directory the second glob names is not visible from the root. That is worth knowing before you plan around it, because a component library distributed through a registry is the kind of thing you would expect to find in a packages/ folder with a build step and a manifest, and here the visible work lives under apps/ alongside whatever the documentation site is. The package itself is marked private, which is the usual way to say this manifest is not meant to be published, and that sits correctly with a copy-and-paste distribution model where the consumer's own package.json is the one that ships.

Every root task except typecheck is filtered down to the web app

Six scripts sit at the root, and five of them carry the same turbo filter. dev, build and start all run the task through turbo with --filter=web, and registry:build does the same. typecheck is the exception: turbo run typecheck with no filter, so it fans out across the whole workspace instead of one app. The practical effect is that the root command surface is built around a single application called web, which is consistent with a documentation site being the thing you actually start, while the type check is the one operation the project wants to run everywhere. The registry:build script is the interesting one, since building a registry is how a shadcn style component set publishes its manifest of files, and that build is also confined to the web app. There is no test script at the root, and the top level listing carries no tests directory either.

check and fix call ultracite while the root carries oxlint and oxfmt configs

Two config files sit at the root of a TypeScript project: oxlint.config.ts and oxfmt.config.ts, matching devDependencies on oxlint at ^1.61.0 and oxfmt at ^0.46.0. Neither tool is named in any root script. The two quality scripts both call a third tool instead, check running ultracite check and fix running ultracite fix, against a devDependency pinned as ultracite 7.6.1 with no caret at all while every other devDependency uses one. So the lint and format configuration lives in two files that the root scripts never read by name, the commands a contributor runs are the ultracite ones, and ultracite is the only dependency in the file held at an exact version. The other root entries are consistent with the rest of the setup: lefthook.yml at the root with a prepare script running lefthook install, and turbo.json beside it for the task graph.

Two rendering bases, and the renderer the project credits is not one of them

The feature list opens on rendering bases rather than components: PDFs can be generated with Takumi or Forme, and both are linked to their own documentation, takumi.kane.tw/docs/pdf and docs.formepdf.com. The credits section then names pdfx by Akash as the source of the react-pdf version. Read together, those two lines say the project descends from a react-pdf based implementation and now offers two other bases instead. That choice is the substantive engineering decision here, because it decides which document model your components compile against, and it is left open per component rather than per project. The rest of the distribution story is consistent across the page: sensible props and shared themes, and the phrase you own the code, which is the copy and paste model stated plainly rather than implied.

The homepage and the documentation the README links are on two different domains

The homepage for the project is pdfcn.dev. Every documentation link inside the page points somewhere else: pdfcn.vercel.app/docs for Get Started, pdfcn.vercel.app/docs/installation, pdfcn.vercel.app/docs/components and pdfcn.vercel.app/docs/blocks, and the sponsor link at pdfcn.vercel.app/sponsor. So the domain a visitor is sent to learn how to install the project is not the domain the project is sold on, which is a detail worth holding onto when you decide whether the deployment behind those paths is the same thing you are evaluating. Two smaller pieces of page plumbing sit alongside it. A Stats heading is followed immediately by Star History with no text between them, and the Star History chart URLs carry a long opaque sealed_token parameter inside the srcset. The gold sponsor slot links out to pro.reactbits.dev carrying three utm parameters that name this project as the referrer.

No tagged releases, a pinned package manager and agent scaffolding at the root

The repository has no GitHub releases at all, so nothing to pin, nothing to diff against and no changelog tied to a version. Everything version shaped lives in the root package.json instead: engines requiring Node 20.9.0 or newer and pnpm 10.0.0 or newer, a packageManager field pinning pnpm 10.28.2, and a TypeScript dependency on ^6.0.3. The last push to main was on 2026-09-24 and the repository is not archived. The root also carries .agents/, .cursor/ and .vscode/ directories, plus a skills-lock.json with no skills directory beside it, which puts editor and agent configuration in the same tracked tree as the build. That is a deliberate choice for a project inviting contributions, and CONTRIBUTING.md is there to explain the local setup, with a code of conduct and a SECURITY.md that asks for vulnerabilities to go through GitHub Security Advisories rather than public issues.

Editorial conclusion

This fits teams that already ship shadcn/ui components and want PDF output as source files in the same repository, with the choice between two rendering bases left open. What you accept by taking it on is a project with no tagged releases at all, so there is no version to pin or to fall back to, and a root workspace whose globs name a packages directory that is not present, meaning the component sources sit wherever apps/ puts them rather than where the workspace globs suggest. Before adopting it, read the installation page for the actual command, since the front page states a one command setup and prints none, and decide whether Takumi or Forme is the base you want before you copy anything into your own tree.

Frequently asked questions

What is shadcn-labs/pdfcn?

Free and open source, MIT licensed React components for generating PDF documents, built on Takumi and Forme and distributed as source you copy into your own project rather than as a dependency you install.

Which PDF rendering engines does shadcn-labs/pdfcn support?

Two rendering bases are named, Takumi and Forme, and a feature bullet offers the choice between them. The credits section attributes the react-pdf version to a project called pdfx, so react-pdf is the ancestor rather than one of the current bases.

How do you install shadcn-labs/pdfcn?

The page states the components use the same registry format and CLI workflow as shadcn/ui and links an installation page on its documentation site, but it prints no command of its own, so the registry command has to be read there.

Does shadcn-labs/pdfcn have versioned releases?

The repository has no GitHub releases. Versions are pinned through the root package.json instead, which requires Node 20.9.0 or newer, pnpm 10.0.0 or newer, and names pnpm 10.28.2 as the package manager.

How does shadcn-labs/pdfcn want security problems reported?

Security vulnerabilities should not be opened as public issues. SECURITY.md directs reporters to send them privately through GitHub Security Advisories.

Official sources

  1. Issues
  2. License: MIT
  3. Project website
  4. README
  5. shadcn-labs/pdfcn on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/shadcn-labs-pdfcn.svg)](https://hysenlabs.com/projects/shadcn-labs-pdfcn)