ANTIGRAVITY LABJP
Articles/App Development
App Development/2026-03-31Intermediate

Antigravity × npm Package Development Guide — Automate TypeScript Library Creation, Testing, and Publishing with AI Agents

Learn how to efficiently develop, test, and publish TypeScript npm packages using Antigravity's AI agents. From project scaffolding to CI/CD-powered auto-publishing.

antigravity436npm5typescript27package-developmentnodejs3open-source3

Setup and context — Why Build npm Packages with an AI IDE?

The npm registry hosts over 2 million packages, and many developers dream of publishing their own utilities or open-source libraries. Yet the overhead of setting up TypeScript builds, configuring test frameworks, managing semantic versioning, and handling the publish workflow can slow you down before you even write your first function.

Antigravity's AI agents can automate much of this boilerplate. From scaffolding a dual-format project to generating comprehensive test suites and managing the entire publish pipeline, you can stay focused on what matters most: the library's core logic.

Project Scaffolding — Let the AI Handle the Setup

The first step is to ask Antigravity's agent to generate the project structure. In the terminal or chat panel, provide a prompt like this:

Create a TypeScript npm package project:
- Package name: @myorg/utils
- ESM + CJS dual output
- Bundle with tsup
- Test with vitest
- Lint and format with biome

The agent will generate a directory structure like the following:

@myorg/utils/
├── src/
   └── index.ts          # Entry point
├── tests/
   └── index.test.ts     # Test file
├── tsconfig.json          # TypeScript config
├── tsup.config.ts         # Bundle config (ESM + CJS)
├── vitest.config.ts       # Test config
├── biome.json             # Lint & format config
├── package.json           # npm metadata
├── README.md              # Documentation
├── LICENSE                # License file
└── .gitignore

The key here is requesting tsup for dual ESM and CJS output from the start. This ensures your library works with both modern import statements and legacy require() calls.

Designing package.json — Getting the exports Field Right

The most critical part of any npm package is the package.json configuration. When you ask the AI agent, it will generate an optimal setup like this:

{
  "name": "@myorg/utils",
  "version": "0.1.0",
  "type": "module",
  "main": "./dist/index.cjs",
  "module": "./dist/index.js",
  "types": "./dist/index.d.ts",
  "exports": {
    ".": {
      "import": {
        "types": "./dist/index.d.ts",
        "default": "./dist/index.js"
      },
      "require": {
        "types": "./dist/index.d.cts",
        "default": "./dist/index.cjs"
      }
    }
  },
  "files": ["dist", "README.md", "LICENSE"],
  "scripts": {
    "build": "tsup",
    "test": "vitest run",
    "test:watch": "vitest",
    "lint": "biome check .",
    "prepublishOnly": "npm run build && npm run test"
  }
}

The exports field with conditional exports ensures that Node.js resolves the correct file based on the module system being used. Placing types first within each condition is a best practice for TypeScript resolution.

Antigravity's agent handles these nuances automatically, saving you the time of researching the correct configuration patterns.

Build Configuration with tsup — Dual ESM and CJS Output

tsup is a zero-config bundler purpose-built for TypeScript libraries, and its configuration is refreshingly simple.

// tsup.config.ts
import { defineConfig } from "tsup";
 
export default defineConfig({
  entry: ["src/index.ts"],
  format: ["esm", "cjs"],    // Dual output
  dts: true,                  // Auto-generate type definitions
  splitting: false,
  sourcemap: true,
  clean: true,                // Clean dist/ before build
  outDir: "dist",
  target: "es2022",
  minify: false,              // Libraries typically skip minification
});

Run the build with a simple command:

# Run the build
npx tsup
 
# Verify the output
# dist/index.js     — ESM format
# dist/index.cjs    — CommonJS format
# dist/index.d.ts   — Type definitions
# dist/index.d.cts  — CJS type definitions

Just tell the Antigravity agent to "build and verify the output," and it will handle both the execution and file validation for you.

AI-Powered Test Generation

Reliable tests are essential for any published library. Antigravity's agent can read your implementation code and generate comprehensive tests, including edge cases.

Consider the following utility functions:

// src/index.ts
export function slugify(text: string): string {
  return text
    .toLowerCase()
    .trim()
    .replace(/[^\w\s-]/g, "")
    .replace(/[\s_]+/g, "-")
    .replace(/-+/g, "-")
    .replace(/^-|-$/g, "");
}
 
export function truncate(str: string, maxLength: number, suffix = "..."): string {
  if (str.length <= maxLength) return str;
  return str.slice(0, maxLength - suffix.length) + suffix;
}
 
export function groupBy<T>(arr: T[], key: keyof T): Record<string, T[]> {
  return arr.reduce((acc, item) => {
    const group = String(item[key]);
    (acc[group] ??= []).push(item);
    return acc;
  }, {} as Record<string, T[]>);
}

Ask the agent to "generate tests for src/index.ts," and it will produce something like this:

// tests/index.test.ts
import { describe, it, expect } from "vitest";
import { slugify, truncate, groupBy } from "../src/index";
 
describe("slugify", () => {
  it("converts a basic string to a slug", () => {
    expect(slugify("Hello World")).toBe("hello-world");
  });
 
  it("removes special characters", () => {
    expect(slugify("Hello, World! @2026")).toBe("hello-world-2026");
  });
 
  it("strips leading and trailing hyphens", () => {
    expect(slugify("  --hello--  ")).toBe("hello");
  });
 
  it("handles empty strings", () => {
    expect(slugify("")).toBe("");
  });
 
  it("collapses consecutive spaces into a single hyphen", () => {
    expect(slugify("a   b   c")).toBe("a-b-c");
  });
});
 
describe("truncate", () => {
  it("returns strings shorter than the limit unchanged", () => {
    expect(truncate("short", 10)).toBe("short");
  });
 
  it("truncates strings exceeding the limit", () => {
    expect(truncate("this is a long sentence", 10)).toBe("this is...");
  });
 
  it("applies a custom suffix", () => {
    expect(truncate("abcdefghij", 8, "…")).toBe("abcdefg…");
  });
});
 
describe("groupBy", () => {
  it("groups items by the specified key", () => {
    const data = [
      { category: "a", value: 1 },
      { category: "b", value: 2 },
      { category: "a", value: 3 },
    ];
    const result = groupBy(data, "category");
    expect(result.a).toHaveLength(2);
    expect(result.b).toHaveLength(1);
  });
 
  it("returns an empty object for empty arrays", () => {
    expect(groupBy([], "key" as never)).toEqual({});
  });
});

Let the agent run vitest run and confirm all tests pass. If you're interested in a TDD-driven approach, check out Antigravity × TDD Test Automation Guide for an in-depth walkthrough.

Version Management and CHANGELOG Automation

Proper semantic versioning (semver) is critical when publishing packages. Antigravity's agent can analyze your changes and automate the entire version bump and CHANGELOG update process.

Analyze the recent commit history and suggest a semver version bump.
Update CHANGELOG.md in Keep a Changelog format.

The agent will categorize commits and make recommendations:

  • fix: Patch version bump (0.1.0 → 0.1.1)
  • feat: Minor version bump (0.1.0 → 0.2.0)
  • BREAKING CHANGE: Major version bump (0.1.0 → 1.0.0)

The generated CHANGELOG follows a clean, standardized format:

## [0.2.0] - 2026-03-31
 
### Added
- `groupBy` utility function
- ESM + CJS dual output support
 
### Fixed
- Consecutive hyphens not being collapsed in `slugify`

Publishing to npm — Pre-Publish Checks and Execution

Before publishing, ask the Antigravity agent to run a final checklist:

Run pre-publish checks:
- Verify the files field in package.json
- Confirm dist/ contains build artifacts
- Ensure README.md exists with usage instructions
- Verify LICENSE file exists
- Run npm pack --dry-run to inspect included files

The agent will execute npm pack --dry-run and display the package contents:

# Pre-publish inspection
npm pack --dry-run
 
# Example output:
# npm notice Tarball Contents
# npm notice 1.2kB  dist/index.js
# npm notice 1.0kB  dist/index.cjs
# npm notice 892B   dist/index.d.ts
# npm notice 892B   dist/index.d.cts
# npm notice 2.1kB  README.md
# npm notice 1.1kB  LICENSE
# npm notice 580B   package.json
# npm notice Tarball Details
# npm notice name:          @myorg/utils
# npm notice version:       0.2.0
# npm notice package size:  3.2 kB

Once everything checks out, publish with:

# Log in to npm (first time only)
npm login
 
# Publish (use --access public for scoped packages)
npm publish --access public

The prepublishOnly script in package.json ensures that a build and test run happen automatically before every publish, preventing broken packages from reaching the registry.

CI/CD Integration — Auto-Publishing with GitHub Actions

For a more robust workflow, you can set up GitHub Actions to automatically publish your package when you create a release. Ask the Antigravity agent to generate the workflow:

# .github/workflows/publish.yml
name: Publish Package
 
on:
  release:
    types: [published]
 
jobs:
  publish:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      id-token: write
    steps:
      - uses: actions/checkout@v4
 
      - uses: actions/setup-node@v4
        with:
          node-version: "22"
          registry-url: "https://registry.npmjs.org"
 
      - run: npm ci
      - run: npm run lint
      - run: npm run test
      - run: npm run build
 
      - run: npm publish --provenance --access public
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

The --provenance flag enables npm's supply chain security feature (provenance attestations), which increases trust in your package by linking it to a verifiable build process.

For more advanced CI/CD pipeline patterns, see Antigravity × GitHub Actions Advanced CI/CD Pipeline Guide for a comprehensive deep dive.

Summary

Antigravity's AI agents can streamline every phase of TypeScript npm package development. From project scaffolding and optimal package.json configuration to automated test generation, version management, and CI/CD-powered publishing, the agent handles the tedious parts so you can focus on building great library APIs.

Give it a try — publish your favorite utilities as npm packages and contribute to the open-source ecosystem.

Share

Thank You for Reading

Antigravity Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

App Dev2026-07-02
Stop Treating Dependency Updates as a Monthly Chore — Weekly Agent Runs with Semver Risk Triage and Verification Gates
Move from batch-updating 47 stale packages at once to a weekly agent-driven routine: semver-based risk tiers, a playbook YAML, hallucination-proof changelog reports, and a lockfile diff gate.
App Dev2026-05-03
Building Idempotency Keys and Dedupe Stores in TypeScript with Antigravity
A production guide to designing idempotency keys and dedupe stores in TypeScript with Antigravity — covering Stripe webhook retries, Temporal replays, and the Cloudflare KV / Redis / Postgres trade-offs you actually need to choose between.
App Dev2026-05-01
Drawing the Server/Client Boundary with Antigravity — A Workflow That Stops Next.js 16 RSC From Tripping You Up
Drawing the line between Server and Client Components is still the trickiest part of Next.js 16. Here's the practical workflow I use with Antigravity to stop misplaced `use client` directives and serialization errors before they happen.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →