Preview URLs for branch deploys
When pull-to-host is set up with previews enabled (the default), every push to a non-primary branch deploys to its own preview URL. Production stays untouched until you merge.
Preview URL format:
<branchSlug>--<siteId>.preview.turtini.com
Where:
• <branchSlug> is the branch name lowercased and slugified (e.g. feat/redesign → feat-redesign)
• <siteId> is your Turtini hosted-site id (visible on the site card)
How it works:
1. You push to a branch other than the connected primary (e.g. feature-x)
2. The hosted-site webhook fires
3. Turtini verifies HMAC, then pulls feature-x via the GitHub Trees API
4. Files are scanned and uploaded to a separate GCS prefix at hosted-sites/<siteId>/preview/<branchSlug>/
5. The preview URL goes live within a few seconds
The primary branch (the one you set at Connect time) deploys to your custom domain as before. Previews never overwrite the primary.
Use cases:
• Pull request previews — open a PR for feature-x, share the preview URL with reviewers, get visual feedback before merge
• Staging environments — keep a long-lived staging branch with its own stable preview URL
• Per-customer demos — branch + push, share the preview link with one customer, kill it after
Enabling / disabling:
• At Connect time — checkbox in the modal, default ON
• Later — Settings → Hosting → Toggle previews on/off (calls setHostedSitePreviews)
Stale-preview cleanup:
Preview deploys auto-delete after 14 days of inactivity. The cleanupStaleHostedPreviews scheduled function runs daily and removes any preview where the last sync timestamp is older than 14 days — both the GCS files and the previewDeploys map entry. Activity = a fresh push to that branch resetting the clock.
Manually deleting a preview:
There's no per-preview delete UI in V1. Push an empty commit to the branch (resets the clock for 14 more days), or wait for the cleanup cron, or have an admin clear the previewDeploys map entry from Firestore directly.
Browsing active previews:
The site card shows the count of active preview deploys. The preview URLs themselves live on hostedSites/{siteId}.previewDeploys — admins can read this in the Firestore console or via the listHostedSites callable. A first-class preview-list UI is on the roadmap.
Preview hostnames + DNS:
The wildcard DNS record *.preview.turtini.com → ghs.googlehosted.com (DNS only) is pre-staged. You don't add anything per-preview; the hostnames just work.
Auth / scoping:
Previews are public — anyone with the URL can view the site. Treat them like staging environments, not like production secrets. If you need auth-gated previews, the Turtini-hosted Builder route at /s/<orgSlug>/<siteSlug> (in-app, sign-in required) is the right surface.