Fork-ready monorepo template for published TypeScript libraries. tsdown ESM builds, Vitest, oxlint/oxfmt, fallow, Changesets, Fumadocs, and a Vite demo, prewired.
Prerequisites: Node ≥24, pnpm 11 (pinned via packageManager), and portless running as the local HTTPS proxy (the docs dev URL depends on it).
pnpm install
pnpm dev # docs at https://acme-package.docs.localhost · demo at http://localhost:5173
pnpm test # vitest across packages
pnpm build # builds all workspaces (packages + docs)| Package | Role |
|---|---|
@acme/core |
Example framework-agnostic library (tiny typed store) |
@acme/react |
Example React adapter (useStore via useSyncExternalStore) |
@repo/typescript-config |
Shared tsconfig presets (internal) |
@repo/config-vitest |
Shared Vitest presets + coverage thresholds (internal) |
| App | Role |
|---|---|
apps/docs |
Fumadocs site (https://acme-package.docs.localhost via portless) |
apps/demo-vite |
Vite playground consuming both packages via workspace:* |
The rename surface is small. Full walkthrough: docs → "Using this template".
@acmescope → your npm scope (packages/*/package.json+ imports inapps/, including the docs.mdxcontent)- Repo identity: root
name,repository.urlin BOTH publishable packages (npm provenance validates it against the publishing repo, so a renamed fork's first release fails if skipped), the site identity inapps/docs/lib/site.ts, the repository link inapps/docs/content/docs/index.mdx(a test keeps it equal tosite.ts), the titles inapps/demo-vite/index.htmlandapps/demo-vite/public/404.html, and this README plusAGENTS.md - Portless names in the docs and demo dev scripts (
apps/docs/package.jsonandapps/demo-vite/package.json→"dev") - LICENSE holder
Changesets: pnpm changeset, merge the auto-opened "Version Packages" PR, and release.yml publishes to npm with provenance. It authenticates through npm trusted publishing (GitHub OIDC), so the repository stores no npm token. The release job is skipped until you register this repository and release.yml as the trusted publisher of each package on npmjs.com and set the RELEASE_ENABLED repository variable to true.
| Command | What |
|---|---|
pnpm dev |
run all dev servers (turbo) |
pnpm build / pnpm test / pnpm test:coverage |
build / test across workspaces |
pnpm lint / pnpm format / pnpm format:check / pnpm typecheck |
oxlint / oxfmt / tsc |
pnpm fallow:dead / fallow:dupes / fallow:health / fallow:audit |
dead code / duplicates / health score / audit vs main |
pnpm changeset / version-packages / release |
Changesets flow |
pnpm 11.13.1 (pinned) · Node ≥24 · Turborepo · tsdown (ESM-only) · Vitest 5 · oxlint + oxfmt · fallow · husky + lint-staged · Changesets · Next 16 + Fumadocs · Vite 8