Thanks for your interest in contributing to Frontman! This guide will help you get set up and productive quickly.
- Node.js v24+
- Yarn 4 (via Corepack:
corepack enable) - Elixir 1.19+ (only needed for the server in
apps/frontman_server/) - mkcert (for local SSL certificates)
# Clone the repo
git clone https://github.com/frontman-ai/frontman.git
cd frontman
# Install dependencies
make install
# Build all packages
make build
# Start the dev environment
make dev- Branch from
main— Create a feature branch for your change. - Use
makecommands — The task runner is Makefiles, not yarn/npm scripts. Runmake helpin any directory to see available targets. - Run tests — Run
make testin the relevantlibs/directory before submitting a PR. - Add a changeset — If your change is user-facing, run
yarn changesetfrom the repo root and follow the prompts. A CI check will block PRs that are missing a changeset.
frontman/
├── apps/
│ ├── dogfooding/ # Internal testing app
│ ├── frontman_server/ # Elixir/Phoenix backend
│ └── marketing/ # Marketing website
├── libs/
│ ├── bindings/ # ReScript bindings for Node/browser APIs
│ ├── client/ # React UI component library
│ ├── frontman-astro/ # Astro framework integration
│ ├── frontman-client/ # Browser-side MCP client
│ ├── frontman-core/ # Core server-side tools
│ ├── frontman-nextjs/ # Next.js integration
│ ├── frontman-protocol/ # Protocol definitions
│ ├── react-statestore/ # React state management library
│ └── frontman-vite/ # Vite plugin
├── docs/ # Protocol documentation
└── infra/ # Infrastructure configs
| Layer | Technology |
|---|---|
| Language | ReScript |
| Backend | Elixir / Phoenix |
| UI | React |
| Runtime | Node.js |
- Functional style with
Resulttypes for error handling. - Crash early and obviously. Use
Option.getOrThrow/Result.getOrThrowwhen a value should always exist. Never silently swallow exceptions. - File naming follows the
Client__ComponentName.resflat-folder convention. - JSON parsing: always use Sury schemas (
@schemaannotation) instead of manualDict.getchains. - State management: all API calls and side effects go through the
StateReducer(seelibs/client/).
- Tests use Vitest with
rescript-vitest. - Test files are named
*.test.res.mjs. - Assertion style:
t->expect(value)->Expect.toEqual(expected).
- Story files are co-located with components:
Client__MyComponent.story.res. - Run
cd libs/client && make storybookto start Storybook.
- Fill out the PR template (description, related issues, testing checklist).
- Ensure CI passes — linting, type checking, and tests are run automatically.
- Include a changeset if the change is user-facing (
yarn changeset). - A maintainer will review your PR. We aim to provide initial feedback within a few business days.
Frontman uses changesets for versioning and changelogs.
When making user-facing changes, run yarn changeset from the repo root. This creates a markdown fragment in .changeset/ describing the change and which packages are affected.
make releaseThis triggers a GitHub Actions workflow that:
- Runs
yarn changeset versionto bump package versions and update changelogs - Creates a
release/vX.Y.Zbranch and opens a PR
Review the changelog in the PR, then merge when ready.
When the release PR merges to main, a git tag and GitHub Release are created automatically.
npm publishing is done manually after the release PR merges:
git checkout main && git pull
# Publish @frontman-ai/astro
make publish-astroThis builds the package from scratch (ReScript + tsup bundle) and runs npm publish. The version in package.json was already bumped by changesets in step 2.
Note: Only
@frontman-ai/astrohas a publish target currently. To add more, create apublishtarget in the package's Makefile and a correspondingpublish-<name>target in the root Makefile.
Contributions to client libraries (libs/) are licensed under the Apache License 2.0. Contributions to the server (apps/frontman_server/) are licensed under the AGPL-3.0.
No CLA is required — the Apache 2.0 license (Section 5) covers contribution grants.