Skip to content

Repository files navigation

js-ai-driven-development-pipeline-template

A comprehensive template for AI-driven JavaScript/TypeScript development with full CI/CD pipeline support.

This repository publishes the real test package @link-foundation/example-package-name so the template release pipeline is validated end to end with npm trusted publishing.

Features

  • Multi-runtime support: Works with Bun, Node.js, and Deno
  • Universal testing: Uses test-anywhere for cross-runtime tests
  • Automated releases: Changesets-based versioning with GitHub Actions
  • Optional Docker Hub publishing: Docker images can be published after the matching npm version is visible
  • Universal app example: React UI for the package API with GitHub Pages, Electron, and Capacitor build paths
  • Code quality: ESLint + Prettier with pre-commit hooks via Husky
  • Package manager agnostic: Works with bun, npm, yarn, pnpm, and deno
  • Broken link checks: Automated link validation with lychee and Web Archive fallback suggestions

Quick Start

Using This Template

  1. Click "Use this template" on GitHub to create a new repository
  2. Clone your new repository
  3. Update package.json with your package name and description
  4. Install dependencies: bun install
  5. Start developing!

Development

# Install dependencies
bun install

# Run tests
bun test --timeout 30000

# Or with other runtimes:
npm test
deno test --allow-read

# Lint code
bun run lint

# Format code
bun run format

# Check all (lint + format + file size)
bun run check

# Build the universal React example app
npm install --prefix examples/universal-app
npm run example:web:build
npm run example:desktop:package

# Try the CLI locally
node bin/example-package-name.js add 2 3

Project Structure

.
├── .changeset/           # Changeset configuration
├── .github/workflows/    # GitHub Actions CI/CD
├── .husky/               # Git hooks (pre-commit)
├── examples/             # Usage examples
│   └── universal-app/    # React + GitHub Pages + Electron + Capacitor app
├── scripts/              # Build and release scripts
├── src/                  # Source code
│   ├── index.js          # Main entry point
│   └── index.d.ts        # TypeScript definitions
├── tests/                # Test files
├── .eslintrc.js          # ESLint configuration
├── .prettierrc           # Prettier configuration
├── bunfig.toml           # Bun configuration
├── deno.json             # Deno configuration
└── package.json          # Node.js package manifest

Design Choices

Multi-Runtime Support

This template is designed to work seamlessly with all major JavaScript runtimes:

  • Bun: Primary runtime with highest performance, uses native test support (bun test)
  • Node.js: Alternative runtime, uses built-in test runner (node --test)
  • Deno: Secure runtime with built-in TypeScript support (deno test)

The test-anywhere framework provides a unified testing API that works identically across all runtimes.

Package Manager Agnostic

While package.json is the source of truth for dependencies, the template supports:

  • bun: Primary choice, uses bun.lockb
  • npm: Uses package-lock.json
  • yarn: Uses yarn.lock
  • pnpm: Uses pnpm-lock.yaml
  • deno: Uses deno.json for configuration

Note: package-lock.json is not committed by default to allow any package manager.

Universal App Example

The template includes examples/universal-app, a Vite React app that imports add and multiply from src/index.js and renders a visual calculator UI. The same static build is used by:

  • GitHub Pages (npm run example:web:build)
  • Electron desktop packaging (npm run example:desktop:package)
  • Capacitor Android/iOS sync (npm run example:mobile:sync)

The example app has its own package.json and lockfile so template users can opt into the frontend stack without adding React, Electron, or Capacitor to the library package itself.

See examples/universal-app/README.md for local web, desktop, Android, and iOS testing instructions.

Code Quality

  • ESLint: Configured with recommended rules + Prettier integration
  • Prettier: Consistent code formatting
  • Husky + lint-staged: Pre-commit hooks ensure code quality
  • File size limit: Files must stay under 1500 lines for maintainability (enforced via ESLint and CI)

Release Workflow

The release workflow uses Changesets for version management:

  1. Creating a changeset: Run bun run changeset to document changes
  2. PR validation: CI checks for valid changeset in each PR
  3. Automated versioning: Merging to main triggers version bump
  4. npm publishing: Automated via OIDC trusted publishing (no tokens needed)
  5. Optional Docker Hub publishing: When configured, waits for the exact npm version and tags the Docker image with that version
  6. GitHub releases: Auto-created with formatted release notes

First release of a brand-new package: OIDC trusted publishing cannot create a package that does not exist yet (the first publish fails with E404, because a trusted publisher can only be configured for an existing package). To bootstrap, add a repository secret named NPM_TOKEN (a granular/automation token with publish access). The release workflow passes it as NODE_AUTH_TOKEN automatically. Once the package exists and OIDC trusted publishing is configured on npmjs.com, the token becomes optional and can be removed.

Manual Releases

Two manual release modes are available via GitHub Actions:

  • Instant release: Immediately bump version and publish
  • Changeset PR: Create a PR with changeset for review

CI/CD Pipeline

The GitHub Actions workflow (.github/workflows/release.yml) implements a fast-fail pipeline:

Fast checks (~7-30s each, run first for fastest feedback):

  1. Test compilation: Syntax-checks all .mjs files with node --check
  2. Lint, format & secrets scan: ESLint, Prettier, jscpd, and secretlint for credential leak detection
  3. File line limits: Enforces the 1500-line limit on JavaScript (.js, .mjs, .cjs) and Markdown (.md) files plus release.yml
  4. Changeset check: Validates PR has exactly one changeset (added by that PR)
  5. Version check: Blocks manual version changes in package.json
  6. Documentation validation: Checks required doc files (doc line limits are enforced by the file line limits check)

Slow checks (only run after all fast checks pass):

  1. Test matrix: 3 runtimes × 3 OS = 9 test combinations
  2. Broken link checks: Validates all links in Markdown/HTML files (separate workflow)

Release (on merge to main):

  1. Changeset merge: Combines multiple pending changesets at release time
  2. Release: Automated versioning and npm publishing
  3. Optional Docker publish: Publishes Docker Hub latest and npm-version tags after the npm package is visible

Reasonable Timeouts

Every CI job declares an explicit timeout-minutes so hung steps fail in minutes instead of reaching the GitHub Actions default of six hours. Fast checks use 5-10 minute caps, release jobs use 30 minutes, and the link checker uses 10 minutes for external network variance.

Individual tests are also capped inside supported runners: npm test runs node --test --test-timeout=30000, and the CI Bun runner uses bun test --timeout 30000. Deno does not provide a single global per-test timeout flag, so Deno tests are protected by the 10-minute matrix job cap.

See BEST-PRACTICES.md for detailed explanations of each practice.

Robust Changeset Handling

The CI/CD pipeline is designed to handle concurrent PRs gracefully:

  • PR Validation: Only validates changesets added by the current PR, not pre-existing ones from other merged PRs. This prevents false failures when multiple PRs merge before a release cycle completes.

  • Release-time Merging: If multiple changesets exist when releasing, they are automatically merged into a single changeset with:

    • The highest version bump type (major > minor > patch)
    • All descriptions preserved in chronological order

This design decouples PR validation from the need to pull changes from the default branch, reducing conflicts and ensuring that even if CI/CD fails, all unpublished changesets will still get published when the error is resolved.

Deploying the example app

The example-app.yml workflow deploys the universal example app to GitHub Pages on every push to main. Before the first run on main in a new repository created from this template, open Settings → Pages and set Source = GitHub Actions. This is a one-time manual step and cannot be configured from a workflow because the Pages source defaults to Deploy from a branch. Without it, the pages-deploy job fails on actions/deploy-pages with Get Pages site failed / Failed to create deployment. After flipping the source, the workflow provisions the Pages site on its first run.

Auto-regenerated preview screenshots

The same example-app.yml workflow contains a preview-regen job that boots the built example app in a headless Chromium via browser-commander + Playwright and writes fresh screenshots to docs/screenshots/example-app/example-app-{locale}-{theme}.png on every push to main (and on workflow_dispatch). Any drift is committed back to main with [skip ci] so README/site images never go stale between releases. The job runs in the official Playwright container with the browser already installed, avoiding CI stalls from live Chromium downloads.

The same script is available locally:

npm install --prefix examples/universal-app
npm run example:web:preview-images
# Verbose probe of <html data-theme>, <html lang>, and PNG signatures:
PREVIEW_VERBOSE=1 npm run example:web:preview-images

The matrix defaults to {en, ru} × {light, dark}. The shipped example app has no localization or theme toggle yet, so every cell currently renders the same UI — when a fork adds either, the matrix produces real per-cell variants without script edits.

Broken Link Checker

The link checker workflow (.github/workflows/links.yml) validates all links in Markdown and HTML files:

  1. Detection: Uses lychee to scan all *.md and *.html files
  2. Web Archive fallback: For any broken links found, automatically checks the Wayback Machine for archived versions
  3. Actionable suggestions: Reports one of three outcomes for each broken link:
    • Archived: Suggests the Web Archive URL as a replacement
    • Not archived: Clearly reports the link is unrecoverable
  4. Scheduled checks: Runs weekly to catch links that break over time (even if no files changed)
  5. Issue creation: On scheduled runs, creates a GitHub Issue with the full broken links report

Add regex patterns to .lycheeignore to exclude URLs from checks (e.g., local dev URLs, example.com, known rate-limited sites).

Configuration

Updating Package Name

After creating a repository from this template, update the package name in:

  1. package.json: replace "@link-foundation/example-package-name" with your package name
  2. .changeset/config.json: Package references

Release scripts derive the package name from package.json at runtime, so no script-level package-name constants need to be edited during template adoption.

Optional Docker Hub Publishing

Docker publishing is disabled by default. To enable it for a project that ships a Docker image, add a Dockerfile and configure these GitHub Actions settings:

Setting Type Description
DOCKERHUB_IMAGE Variable Docker Hub image name, for example namespace/image. This enables Docker publishing.
DOCKERHUB_USERNAME Variable Docker Hub username used by docker/login-action.
DOCKERHUB_TOKEN Secret Docker Hub access token used for registry authentication.
DOCKER_CONTEXT Variable, optional Docker build context. Defaults to ..
DOCKERFILE Variable, optional Dockerfile path. Defaults to ./Dockerfile.

When enabled, the release workflow waits until the exact published npm version is visible in the npm registry, then publishes Docker Hub tags for latest and that same version. The Docker build also receives NPM_PACKAGE_VERSION as a build argument so Dockerfiles can install the matching published package.

ESLint Rules

Customize ESLint in eslint.config.js. Current configuration:

  • ES Modules support
  • Prettier integration
  • No console restrictions (common in CLI tools)
  • Strict equality enforcement
  • Async/await best practices
  • Strict unused variables rule: No exceptions - all unused variables, arguments, and caught errors must be removed (no _ prefix exceptions)

Prettier Options

Configured in .prettierrc:

  • Single quotes
  • Semicolons
  • 2-space indentation
  • 80-character line width
  • ES5 trailing commas
  • LF line endings

Scripts Reference

Script Description
bun test --timeout 30000 Run tests with Bun and a 30s per-test cap
npm test Run tests with Node.js and a 30s per-test cap
bun run lint Check code with ESLint
bun run lint:fix Fix ESLint issues automatically
bun run format Format code with Prettier
bun run format:check Check formatting without changing files
bun run check Run all checks (lint + format)
npm run example:web:dev Start the universal app Vite dev server
npm run example:web:build Build the universal app static web bundle
npm run example:web:preview-images Regenerate preview screenshots via browser-commander
npm run example:desktop:package Package the Electron desktop app locally
npm run example:mobile:sync Build and sync the app bundle into Capacitor projects
bun run changeset Create a new changeset

Contributing

See CONTRIBUTING.md for detailed contribution guidelines.

Quick steps:

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/my-feature
  3. Make your changes
  4. Create a changeset: bun run changeset
  5. Commit your changes (pre-commit hooks will run automatically)
  6. Push and create a Pull Request

Best Practices

This template implements CI/CD best practices for AI-driven development. See BEST-PRACTICES.md for details on:

  • File size limits for AI readability
  • Automated formatting and linting
  • Multi-runtime and cross-platform testing
  • Changeset-based versioning
  • Concurrency control for CI/CD pipelines

License

Unlicense - Public Domain

About

A template for AI driven development pipeline for JavaScript/TypeScript

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages