Thanks for helping improve the Arcjet Examples! This guide explains how to set up your environment, run examples, follow our lint/format rules, add a new example, publish it to its own repository, and keep dependencies up to date.
- Development environment
- Starting the examples
- Static analysis (formatting & linting)
- Adding a new example (Arcjet JS SDK)
- Publishing to a new repository
- Publishing an example (semi‑automated)
- Updating dependencies
- Helpful commands
We recommend using the provided Dev Container. It gives you a consistent toolchain and avoids “works on my machine” issues.
Tip
You can still work locally without the devcontainer; just be sure to install the tools referenced below (e.g., Docker, Trunk).
From outside the devcontainer, start all examples in watch mode:
# You'll likely need to populate the relevant .env files first
docker compose up [example-name] # e.g. astro, deno, expressjs, etc.When using OrbStack, each example will be reachable at:
[example-name].arcjet-examples.orb.local
# e.g. astro.arcjet-examples.orb.local
Tip
Using a different Docker provider? Ports will be auto‑assigned and examples will be served at http://localhost:<port> rather than *.arcjet-examples.orb.local.
Run docker compose ps to find the assigned ports.
Run Biome and Prettier directly from the example directory:
# Lint (Biome)
npx biome lint .
# Format (Prettier)
npx prettier --write .Tip
If you hit Biome import‑sorting issues, stage the affected files and run:
npm run sort-staged-importsNote
These steps are for examples built with the Arcjet JS SDK.
-
Create the project
- Place your example in the
examples/directory.
- Place your example in the
-
Set up the shared stylesheet
-
Copy the shared
*.cssfiles (temporarily copy fromexamples/astro/src/styles). -
Install required dependencies:
npm install @fontsource-variable/figtree @fontsource/ibm-plex-mono
-
Import
styles.cssusing your framework’s standard method.
-
-
Match the HTML structure
- Follow the general HTML structure used by existing examples to stay consistent.
-
Containerization
- Add a
Dockerfileand acompose.yamlin your example folder. - Link your example service in the root
compose.yaml.
- Add a
-
(Temporary) Workspace entry
- Until #31 is resolved, manually add your example to the
workspacesarray inscripts/prepare-to-publish.ts.
- Until #31 is resolved, manually add your example to the
Once your example is merged into main, you can publish it to its own repository.
-
Create a public GitHub repository
-
Naming:
arcjet/example-[example-name] -
Do not initialize a README,
.gitignore, or license. -
Description:
An example [framework] application protected by Arcjet -
Mark as a Template repository
-
Disable repository features you won’t need:
- Wikis
- Issues
- Sponsorships
- Discussions
- Projects
-
Disable GitHub Actions
-
-
Add the repository field to your example’s
package.json{ "repository": "github:arcjet/example-[example-name]" }
Your example repository is now ready to receive code. Next, follow Publishing an example.
Note
This process is currently semi‑automated. We may fully automate it with a GitHub Action & GitHub App in the future.
-
Ensure you have
mainchecked out and a clean working directory. -
Build all Docker images to validate they’re healthy (run outside the devcontainer):
docker compose build
-
Prepare examples for publishing:
npm run prepare-to-publish
This script will:
- Shallow clone each example’s destination repo into
dist/[example-name] - Overwrite
dist/[example-name]with the current example - Commit any changes to the example repository
- Prompt you to push the changes upstream
- Shallow clone each example’s destination repo into
-
When prompted, sanity‑check the changes and push.
# Check changed files git diff --name-only HEAD^Remember it's a proper (shallow) git repository! You'll only be able to see the last commit but the power of git is still there if you need it!
We use npm-check-updates with a 30‑day cooldown.
-
Update Arcjet packages to the latest version:
npx --no -- npm-check-updates --interactive --packageFile 'examples/*/package.json' --filter 'arcjet, @arcjet/*, nosecone, @nosecone/*' --target latest
-
Recursively update all dependencies to the greatest minor within cooldown:
npx --no -- npm-check-updates --interactive --packageFile 'examples/*/package.json' --cooldown 30 --target minor -
Recursively update all dependencies to the latest within cooldown:
npx --no -- npm-check-updates --interactive --packageFile 'examples/*/package.json' --cooldown 30 --target @latest
When a parent package cannot be updated past a Socket or npm audit
finding, pin the transitive with overrides in that example's
package.json. See OVERRIDES.md for the current pins and
why they exist.
Deno dependencies are currently managed manually. Run:
cd examples/deno
deno update --interactive --latestPython dependencies are currently managed extra manually. Run:
# Run from an example folder, e.g. examples/fastapi
# Show top-level outdated dependencies
uv tree --depth 1 --outdated | grep latest
# Show installed version of a specific package
uv tree --package <package-name>
# Update specific transitive package
uv lock --upgrade-package <package-name>
Destroy all docker containers + volumes (can be relevant for dependency updates):
docker compose down -vRebuild all examples:
Typically if this passes without error, everything is working relatively well.
docker compose build --no-cache