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.
We use Trunk to manage formatting and linting.
If you’re not using the devcontainer, first install Trunk locally.
Once installed:
# Format all changed files
trunk fmt
# Lint all changed files
trunk checkTip
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
Deno dependencies are currently managed manually. Open the deno-2 devcontainer and run:
cd examples/deno
deno update --interactive --latestPython dependencies are currently managed extra manually. From the python-3 devcontainer:
# 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-cacheVSCode switch devcontainer:
[COMMAND]+[P] > Dev Containers: Switch Container