Bring-your-own-CI: auto-bootstrap a build workflow
Turtini doesn't run npm install or arbitrary build commands inside its hosting infrastructure — that's a privilege-escalation surface (postinstall scripts, supply-chain attacks) we'd rather not own. Instead, the convention is: your CI builds the site, commits the built output to a dedicated branch, and Turtini watches that branch.
Two ways to set this up:
OPTION A: Auto-bootstrap (recommended)
On the Connect modal for pull-to-host, check "Add a build workflow to my repo". When you click Connect & deploy, Turtini writes .github/workflows/turtini-deploy.yml to your repo via the GitHub Contents API. The workflow:
1. Triggers on every push to main (and on workflow_dispatch)
2. Sets up Node 20 with npm cache
3. Runs npm ci && npm run build
4. Detects the build output directory (tries dist, build, out, .next)
5. Force-pushes the output to your connected branch (which Turtini watches)
Connect the site's "watch" branch to dist (or whatever the workflow targets). Push code to main, the workflow runs, output lands on dist, Turtini's webhook fires, deploy happens.
Refusal cases: if turtini-deploy.yml already exists in your repo, Turtini refuses to overwrite it (returns 422 already-exists) — your existing workflow is preserved. Edit the existing one to match the convention if you want Turtini to drive deploys.
OPTION B: Roll your own
If you want a different CI pipeline (build matrix, cypress tests, S3 cache, custom node version, monorepo, etc.), don't check the bootstrap box. Build whatever workflow you like as long as it eventually pushes static files to the connected branch. Examples:
• Vite + custom env vars: VITE_FOO=bar npm run build && publish dist
• Next.js: next build && next export → publish out
• Astro: npm run build → publish dist
• Hugo: hugo → publish public
Editing the bootstrapped workflow:
The generated turtini-deploy.yml is just a YAML file in your repo — edit it freely. Common edits:
• Bump Node version
• Add an npm test step before build
• Add env: values for build-time secrets (set them as GitHub Actions secrets first)
• Change the build output directory detection if your build emits to a non-standard path
• Trigger on different branch patterns
Bypassing CI entirely:
If your site doesn't need a build (plain HTML/CSS/JS, or a templating system that runs at request time), connect Turtini directly to the branch where your raw source lives — main, master, whatever. Skip the workflow bootstrap. Turtini pulls and serves whatever's committed.
Why this design:
• Free for you: GitHub Actions is free for public repos and cheap for private
• Secure: arbitrary build commands run on GitHub's infrastructure, not Turtini's. Your build secrets stay in GitHub Actions secrets.
• Standard: matches what gh-pages, Vercel, Netlify, and Cloudflare Pages do under the hood
• Replaceable: if you outgrow GitHub Actions, swap to CircleCI / Buildkite / any other CI — the contract is "push static files to a branch", which everything supports