Consider using nvm to manage node versions, after installing in the project directory run:
nvm use
From the top-level root folder of this npm workspace, you can run the following npm commands:
Install dependencies:
Will install all the dependencies we need to build and run the project:
npm install
Build all workspaces:
Use this to produce the same output as a release. The build directory will be populated with
various artifacts.
npm run buildTip
You can run the build command from within any sub-project too, the artifacts will always be
lifted out to the root-level build folder.
Run unit tests for all workspaces:
npm run test-unitRun integration tests for all workspaces:
npm run test-intRun extended integration tests for all workspaces:
npm run test-int-xClean tree and check for changes:
npm run test-clean-treeGenerate documentation using TypeDoc:
npm run docsGenerate and watch documentation using TypeDoc:
npm run docs-watchCompile TypeScript files:
npm run tscWatch and compile TypeScript files:
npm run tsc-watchLint the codebase using ESLint:
npm run lintLint and automatically fix issues:
npm run lint-fixServe integration test pages on port 3220:
npm run serveServe special pages on port 3221:
npm run serve-special-pagesReleases are created via GitHub Actions: Release workflow
C-S-S is consumed by native apps (Android, iOS, macOS, Windows) that each use a different dependency mechanism (npm, Swift Package Manager, git submodules). These consumers need built artifacts (build/, Sources/ContentScopeScripts/dist/) — not source code they'd have to compile themselves.
On main and feature branches, build/ and Sources/ContentScopeScripts/dist/*.js are gitignored. This keeps diffs clean: PRs show only source changes, not thousands of lines of generated JavaScript.
Built artifacts live on dedicated branches:
| Branch | Purpose | How it's created |
|---|---|---|
releases |
Production releases. Tags (e.g. 12.38.0) point here. |
Manual workflow_dispatch on build.yml |
pr-releases/<branch> |
Per-PR build artifacts for cross-repo testing. | Automatic via build-pr.yml on every PR push |
The releases branch is the long-lived equivalent of "what main would look like if we checked in build output". The pr-releases/ branches are ephemeral — created when a PR is opened/updated, deleted when it's closed.
Why not check build output into main directly?
- Rebasing becomes painful: every commit in a rebase would require rebuilding and re-staging
build/andSources/. - PRs become unreadable: generated diffs dwarf the actual source changes.
- Merge conflicts in generated files are meaningless noise.
The separate-branch approach was adopted via Tech Design: Build automation for content-scope-scripts.
- Go to Actions → Release
- Click "Run workflow"
- Select version bump type
- Click "Run workflow"
The workflow creates a tag and GitHub release automatically. Build artifacts on the releases branch are consumed by native app repos.
When you push to any branch (except main, releases, or pr-releases/*), the build-pr.yml workflow automatically:
- Builds all workspaces (
npm run build) - Pushes the source + build artifacts to
pr-releases/<your-branch-name> - If an open PR exists for the branch, updates the PR description and posts a comment with:
- Static preview entry points (docs, static pages, integration pages)
- Integration commands for each platform
The build branch is created on the first push and updated on every subsequent push. It's deleted automatically when the source branch is deleted.
Using a PR build branch in a native client:
# Android / Extension (npm)
npm i github:duckduckgo/content-scope-scripts#pr-releases/my-feature-branch
# Apple (Swift Package Manager) — in Package.swift
.package(url: "https://github.com/duckduckgo/content-scope-scripts.git",
branch: "pr-releases/my-feature-branch")
# Windows (git submodule)
git -C submodules/content-scope-scripts fetch origin pr-releases/my-feature-branch
git -C submodules/content-scope-scripts checkout origin/pr-releases/my-feature-branchUse <build-commit-hash> from the PR build comment for cache-safe preview links.
Static preview entry points for that build commit:
https://rawcdn.githack.com/duckduckgo/content-scope-scripts/<build-commit-hash>/docs/index.html
https://rawcdn.githack.com/duckduckgo/content-scope-scripts/<build-commit-hash>/injected/integration-test/test-pages/index.html
https://rawcdn.githack.com/duckduckgo/content-scope-scripts/<build-commit-hash>/build/integration/pages/index.html
When making breaking changes:
- Ensure you land a major release version bump.
- Test and complete the native application side first before merging the C-S-S repo change.
- Only merge the C-S-S change after native app support is complete.
Why This Matters
This prevents any engineer from having a breaking change and broken workflow. The native application must be tested and complete before the C-S-S repo change is merged.