Skip to content

Repository files navigation

template-typescript-lib

trunk

Project template for TypeScript libraries built with Effect, optimized for tree-shaking and agentic engineering.

Features

Quick Start

gh repo create mylib --template jasonkuhrt/template-typescript-lib --clone --public && \
cd mylib && \
bun install && \
bun run bootstrap

Then setup a repo secret called NPM_TOKEN for CI publishing.

If you use git-hooks, run this one-time local setup after bootstrap:

git-hooks install

This template tracks its pre-commit behavior in .git-hooks/pre-commit.d/, so installation is explicit and local while hook intent stays in the repo.

Effect

This template uses Effect as a peer dependency. Consumers of your library must install Effect themselves.

Building an app instead of a library? Move effect from peerDependencies to dependencies in package.json.

The project includes an .mcp.json configuring the Effect MCP server by tim-smart for Claude Code, giving AI agents access to Effect documentation.

Tree Shaking

This template is configured for aggressive tree-shaking. Bundlers (webpack, esbuild, rollup, vite) can eliminate unused code when consumers import from your library.

Configuration

Field Value Purpose
type "module" ESM output (required for tree-shaking)
sideEffects false Tells bundlers all modules are pure
exports Explicit entry points Black-boxes package internals

TypeScript Settings

Option Purpose
verbatimModuleSyntax Preserves ES module syntax for bundlers
isolatedModules Ensures code is compatible with single-file transpilers

Validation

Two tools validate your package works correctly for consumers:

  • publint - Checks packaging for compatibility across environments
  • attw - Checks TypeScript types resolve correctly across module resolution modes

Run both with bun run check.

Code Patterns

Prefer named exports

Named exports tree-shake more reliably than default exports. Default exports can cause issues with CommonJS interop.

// Preferred
export const foo = () => {}
export const bar = () => {}

// Avoid
export default { foo, bar }

Pure annotations

For module-level function calls (HOCs, factories), the /*#__PURE__*/ annotation tells bundlers the call is side-effect free. See Terser and UglifyJS docs.

sideEffects

Bundlers cannot always statically determine if code has side effects. The sideEffects field hints to bundlers that your modules are "pure" and safe to prune if unused.

Important: If you add modules with side effects (e.g., CSS imports, polyfills, or code that runs on import), update sideEffects to an array:

{
  "sideEffects": ["./src/polyfill.js", "**/*.css"]
}

Barrel Files

Barrel files (index.ts files that re-export from other modules) can inhibit tree-shaking in some bundlers. This template uses a single entry point which is acceptable for small libraries.

For larger libraries, consider:

  • Multiple entry points via exports field
  • Avoiding deep re-export chains
  • Testing your bundle size with bundlephobia or pkg-size

References

Details

TypeScript

  • Strict settings via @tsconfig/strictest
  • Node 24 target via @tsconfig/node24
  • Build cache in node_modules/.cache
  • Output includes declaration, declarationMap, sourceMap for optimal consumer DX
  • Source published for go-to-definition support
  • .ts import specifiers with rewriteRelativeImportExtensions at build time
  • Subpath imports (#lib/*) for clean internal paths

Linting

  • oxlint: Rust-based, type-aware with --deny-warnings
  • oxlint-tsgolint: Enables type-aware rules via tsgo
  • actionlint: GitHub Actions workflow validation
  • --fix-dangerously enabled for auto-fix (safe with strict types + high coverage)
  • Staged-file pre-commit checks are tracked in .git-hooks/pre-commit.d/10-lint-staged.sh and run lint-staged, which applies oxfmt and oxlint only to staged files when git-hooks is installed

Testing

bun test with coverage gating at 95% lines / 95% functions.

Formatting

oxfmt - Rust-based formatter from the oxc project.

npm Scripts

Script Description
check Run all checks sequentially
check:format Verify formatting
check:lint Run oxlint (type-aware)
check:types Type check with tsgo
check:cov Run tests + enforce coverage thresholds
check:package Validate package with publint
check:exports Validate exports with attw
check:ci Lint GitHub Actions workflows
fix Auto-fix format + lint
fix:format Fix formatting
fix:lint Auto-fix lint issues (--fix-dangerously)
build Build with tsgo
test Run tests

CI

PR workflow:

  • actionlint, format, lint, types, publint, exports checks
  • Tests on ubuntu/macos/windows
  • Coverage gating

Trunk workflow:

  • Automated canary release via Dripip

Claude Code

This template includes AI tooling for Claude Code:

  • Effect MCP (.mcp.json): Provides Effect documentation access to Claude Code agents
  • Hookify rule (.claude/hookify.use-tsgo.md): Blocks tsc usage, directs agents to use tsgo instead

Zed Settings

Configure tsgo globally in ~/.config/zed/settings.json:

{
  "languages": {
    "TypeScript": {
      "language_servers": ["tsgo", "!vtsls", "oxc"]
    }
  }
}

Repobeats

About

πŸŽ›οΈ Project template for TypeScript libraries

Topics

Resources

Stars

Watchers

Forks

Used by

Contributors

Languages