Deploying
Build and deploy modules from GitHub
Deployments build your module from GitHub and deploy it to the Odel runtime. Each deployment creates an isolated instance in your dev environment for testing before publishing.
Connect GitHub
Before deploying, connect a GitHub repository:
Go to your project's Overview tab
Click Connect Repository
Select a repository from your GitHub account
Choose the default branch
By default the module is expected at the repository root, with a package.json there. If it
lives in a subdirectory, that's what advanced build settings are for.
Triggering a deployment
From the Deployments tab:
- Click Deploy Now
- The build starts from your default branch
- Watch progress in the live build log
Deploying is always something you do — there is no push trigger, so the branch is read at the moment you click.
The build
Each deployment goes through four stages:
| Stage | Description |
|---|---|
| Validating | Checking project configuration and GitHub connection |
| Building | Fetching code, installing dependencies, bundling |
| Deploying | Uploading to the Odel runtime |
| Complete | Success or failure |
The build runs in a sandboxed container with pnpm support.
Advanced build settings
The defaults assume the repository is the module: install with pnpm at the root, run
pnpm build, deploy what lands at dist/index.js. When that isn't true — a module living in
examples/foobar, a repo that builds with something else — open Advanced build settings on
the deploy card.
| Field | Default | What it's for |
|---|---|---|
| Root directory | repository root | The subdirectory the module lives in, e.g. examples/foobar |
| Install command | pnpm install --no-frozen-lockfile | Anything that installs dependencies |
| Build command | pnpm build | Anything that produces the bundle |
| Entry point | dist/index.js | Where your source lives — see below |
Each field shows its default as placeholder text, and blank means default — you only fill in what you're overriding.
Entry point is the one that surprises people. It names a built file, but it is used to locate your
source: the leading dist/ is swapped for src/ and the .js for .ts, so the default
dist/index.js means src/index.ts. That source file is bundled with esbuild and that bundle is
what gets deployed — whatever your build command emitted is never read. Point it at a path whose
.ts twin actually exists.
Settings are saved when you deploy and pre-fill on your next visit, so a repo with an awkward layout is configured once rather than every time. A dot beside the section title means something is overridden, and the section opens by itself when a project already has settings saved. A deploy that's rejected because another build is running leaves the saved settings alone.
What the fields accept
Root directory and entry point are interpolated into the build container's shell, so they're restricted to letters, digits, /, ., _
and -, must be relative, and can't contain .. (256 characters max). The two commands are free-form — the container is the isolation
boundary — but have to stay on one line (512 characters max).
Live build logs
Build output streams in real-time. The log panel:
- Shows progress during active builds
- Persists across page navigation
- Can be downloaded as a text file
- Displays the full build history
Deployment history
View all past deployments in the history table:
- Status — Success, failed, or in progress
- Version — Module version at deployment time
- Commit — Git commit hash
- Branch — Source branch
- Timestamp — When the deployment ran
Click any deployment to view its full logs.
Your dev instance
Successful deployments create an instance in your dev environment:
@your-org-slug/project-name → dev instanceThis instance is accessible for testing via the Inspector tab before publishing to production.