CLAUDE.md
This file provides guidance when working with code in this repository.
Overview
angular-cli-ghpages is an Angular CLI builder/schematic that deploys Angular applications to GitHub Pages, Cloudflare Pages, or any Git repository. It wraps the gh-pages npm package and integrates with Angular CLI's deployment infrastructure via ng deploy.
Development Commands
All development commands must be run from the src directory:
IMPORTANT: The src/.npmrc file contains ignore-scripts=false to override global npm settings. DO NOT DELETE OR MODIFY this file - it's required for build scripts to run.
Build
Build process: prebuild (clean + regenerate schema.d.ts) - build (tsc) - postbuild (copy metadata to dist/).
schema.json is source of truth for deployment options. Editing it requires rebuild.
Test
Local Development with npm link
For testing changes locally with an Angular project:
-
Build and link from
src/dist:cd src
npm run build
cd dist
npm link -
In your Angular test project:
npm link angular-cli-ghpages
ng add angular-cli-ghpages
ng deploy --dry-run # Test without deploying
Debugging
To debug the deploy builder in VSCode, use this launch.json configuration in your Angular project:
"type": "node",
"request": "launch",
"name": "Debug ng deploy",
"skipFiles": ["
"program": "${workspaceFolder}/node_modules/@angular/cli/bin/ng",
"cwd": "${workspaceFolder}",
"sourceMaps": true,
"args": ["deploy", "--no-build"]
}
Alternatively, debug from command line:
For debugging the standalone engine directly, use the "Launch Standalone Program" task in VSCode (configured in .vscode/launch.json).
Publishing
Publishing uses npm Trusted Publishers with OIDC - no tokens stored in CI!
- Go to Actions - Publish to npm
- Click Run workflow - select branch
- Leave "Dry-run" checked to test, or uncheck for real publish
- Wait for approval (5 min timer + required reviewer)
Publishes with provenance attestation for supply chain security.
For pre-release versions, after publishing:
Architecture
Entry Points
-
Angular CLI Integration (
src/deploy/):builder.ts- Angular builder entry point, called byng deployactions.ts- Orchestrates build and deployment processschema.json- Defines CLI options/arguments
-
Schematic (
src/ng-add.ts):- Implements
ng add angular-cli-ghpages - Adds deploy target to
angular.json
- Implements
-
Standalone CLI (
src/angular-cli-ghpages):- Bash script for non-Angular CLI usage
- Uses
commanderfor CLI parsing
-
Core Engine (
src/engine/):engine.ts- Core deployment logic (wraps gh-pages)defaults.ts- Default configuration values
Deployment Flow
ng deploy
|
builder.ts (createBuilder)
|
actions.ts (deploy function)
+-- Build Angular app (if not --no-build)
| Uses BuilderContext.scheduleTarget()
+-- engine.run()
+-- Prepare options (tokens, CI env vars)
+-- Create .nojekyll file (bypasses Jekyll on GitHub)
+-- Create 404.html (copy of index.html for SPAs)
+-- Create CNAME file (if custom domain)
+-- Publish via gh-pages package
Build Target Resolution
Precedence:
prerenderTarget- For SSG/prerendering builds (if specified, overrides all others)buildTarget- Standard build target (if specified)- Default -
${project}:build:production
Implementation details:
- Static build target:
buildTarget || default(seesrc/deploy/builder.ts) - Final target:
prerenderTarget || staticBuildTarget(seesrc/deploy/builder.ts)
Output directory resolution:
- Checks
angular.jsonforoutputPath - If string: appends
/browser(modern Angular convention) - If object: uses
${base}/${browser}properties - Can be overridden with
--diroption
Token Injection
The engine automatically injects authentication tokens into HTTPS repository URLs:
- Discovers remote URL from current git repo (if
--reponot specified) - Checks environment variables in order:
GH_TOKEN,PERSONAL_TOKEN,GITHUB_TOKEN - Transforms:
https://github.com/...-https://x-access-token:TOKEN@github.com/...
Note: Tokens only work with HTTPS, not SSH URLs (git@github.com).
CI Environment Detection
The engine appends CI metadata to commit messages when running on:
- Travis CI (
TRAVISenv var) - CircleCI (
CIRCLECIenv var) - GitHub Actions (
GITHUB_ACTIONSenv var)
Option Name Mapping
CRITICAL: Angular CLI passes --no-X flags as noX: true, NOT as X: false. The engine must manually invert these:
--no-dotfiles- Angular passes{ noDotfiles: true }- Engine converts to{ dotfiles: false }--no-notfound- Angular passes{ noNotfound: true }- Engine converts to{ notfound: false }--no-nojekyll- Angular passes{ noNojekyll: true }- Engine converts to{ nojekyll: false }
Important Conventions
-
No Server-Side Rendering: GitHub Pages only supports static files. SSR/Universal build targets are not supported.
-
404.html Handling:
- GitHub Pages: Requires
404.htmlworkaround (only way to get SPA routing, but returns HTTP 404 status) - Cloudflare Pages: MUST NOT have
404.html- its presence disables native SPA mode - Future: Consider changing default or auto-detecting deployment target
- GitHub Pages: Requires
-
Jekyll Bypass: Creates
.nojekyllto prevent GitHub Pages from processing files through Jekyll (which would break files starting with_or.txtin assets). -
Breaking Changes in v2: Changed from guessing build conventions in Angular 17+. Projects may need explicit
--build-targetspecification.
Deprecated Options (Maintainers Only)
Current deprecated options:
noSilent- Ignored with warning
Rejected options (v2.1+):
browserTarget- Actively rejected with clear error message ("Use buildTarget instead"). Not silently ignored - users get explicit feedback.
Testing
- Uses Jest (
npm test), tests in*.spec.tsfiles - Requires git clone with
originremote (seetest-prerequisites.spec.ts) - All tests preserve/restore
process.envusingoriginalEnvpattern - No test counts in documentation - they become stale quickly and are bragging
Testing Rules
- Use
.toBe()for scalar equality (strings, numbers, booleans) - Use
.toContain()for array membership or substring checks in long messages - Variable reuse for passthrough (same var = no transformation)
- Separate variables for transformations (input != expected)
Avoid:
.toContain('partial')when you could use.toBe(fullExpectedValue)- Reusing literals instead of variables to show intent
TypeScript: No any Type
Use proper types, unknown, or Partial instead. For mocks: Partial cast to CompleteType.
Related Projects
For sync considerations with AngularFire, monitor:
- https://github.com/angular/angularfire/blob/master/src/schematics/deploy/builder.ts
- https://github.com/angular/angularfire/blob/master/src/schematics/deploy/actions.ts
GitHub CLI Usage
When performing GitHub operations (creating issues, PRs, etc.), use the gh CLI tool instead of web requests to avoid rate limiting and authentication issues.