# Publishing with your own accounts Source: [Publishing with your own accounts](https://typeroll.com/docs/guides/customer-publishing/) > Connect GitHub, Cloudflare, domains and media once per organization, then publish static sites from Typeroll. ## Start editing before connecting accounts [Section titled “Start editing before connecting accounts”](https://typeroll.com/docs/guides/customer-publishing/#start-editing-before-connecting-accounts) You can create sites, connect an AI agent, edit pages, save drafts and share an expiring preview before setting up publishing. With customer publishing enabled, new uploads use the hosting operator’s private draft storage until your R2 access is ready. Public deployment stays locked and links to **Publishing** with the missing setup steps. A public website address appears after the exact deployment has been verified at that address. Your hosting operator must enable customer publishing and configure private draft storage. Existing managed sites retain their existing publishing mode until they are explicitly migrated. ## Organization setup [Section titled “Organization setup”](https://typeroll.com/docs/guides/customer-publishing/#organization-setup) Open the sidebar, select the correct **Organization**, then select **Publishing** under **Account**. On mobile, open the menu first. Organization owners and admins manage these connections. 1. Select **Connect GitHub**, sign in as an owner of your GitHub organization, and authorize Typeroll. If prompted, install the Typeroll publisher GitHub App with **All repositories**, then return to connect. Choose an organization only if more than one is available. No organization name or ID needs to be typed. 2. Select **Connect Cloudflare**, sign in and approve the account. Optional DNS and URL rewrite permissions let Typeroll configure domains automatically. You can decline these and let your administrator or AI agent manage DNS. 3. Typeroll checks R2 automatically. If activation is required, follow the account link to **Storage & databases → R2 object storage → Overview** and complete Cloudflare’s subscription checkout. Return and select **I’ve activated R2 — check again**. Typeroll creates separate private-original and public-media buckets and configures browser uploads. 4. In **R2 object storage → Overview → Account Details → API Tokens → Manage**, create an **Account API token** with **Object Read & Write** for **both buckets shown in Typeroll**. Enter its **Access Key ID** and **Secret Access Key**, then select **Verify keys and finish setup**. These are different from the API token value. A Super Administrator can create account tokens; a User API token is an alternative whose access depends on that user’s continued membership. 5. In **Builds**, select the organization’s build provider and complete its shared-engine setup. Cloudflare builds need a one-time builder repository connection and build token; GitHub Actions uses the existing Typeroll App connection. See [Cloudflare hosting and builds](https://typeroll.com/docs/publishing/cloudflare/). 6. Under **Organization domains**, choose a **Cloudflare domain** from the connected account. Enter short labels in **Media subdomain** and **Sites subdomain**, such as `media` and `sites`. The complete addresses appear below the fields. Select **Configure domains** to connect the media hostname to R2 and queue media migration. HTTPS activation is checked automatically. Each site and version gets its own website address when you publish. Use the refresh icon beside **Cloudflare domain** to retrieve newly added domains. Refreshing keeps the existing account connection. An empty result does not mean you need to reconnect. If the saved OAuth grant lacks domain permissions, **Allow domain access** appears. It opens Cloudflare’s approval screen and keeps the existing account and R2 setup. Typeroll will not replace an existing DNS destination or an existing shared media hostname through this setup action. For external DNS or agent-managed settings, open **Manual settings or external DNS**. Enter the complete **Site address base** and **Shared media host**, choose **Me or my AI agent**, and save. Read **Setup instructions**, apply the records, then select **Check domain status**. Each Hosting Group owns a Cloudflare hosting account and a site address base. Default reuses the organization connection. The Organization owns shared media, DNS access, GitHub and the build-provider selection. Each site gets its own generated private repository and static Pages project. Adding a site or version reuses the organization connections. Account ID is only needed in advanced token setup. In Cloudflare, select the account and use **Search → Copy account ID**, or **Workers & Pages → Account Details → Account ID**. Copy the 32-character account value, not a Zone ID. ### Approve a GitHub permission update [Section titled “Approve a GitHub permission update”](https://typeroll.com/docs/guides/customer-publishing/#approve-a-github-permission-update) An existing connection does not need to be disconnected or connected again. In **Publishing → GitHub account**, select **Approve GitHub update** when it appears. This opens the existing installation in your GitHub organization. Review and accept the requested permissions as a GitHub organization owner, then return to Typeroll. Typeroll checks automatically and confirms when the permissions are up to date. **Check GitHub permissions** repeats the check. If Typeroll says it needs to enable GitHub build access first, your hosting operator must update the publisher App registration before an approval is available. You do not need to edit an App, create a token or reconnect. Your existing connection remains active. Permission approval alone does not change the selected build provider. ### When DNS is hosted elsewhere [Section titled “When DNS is hosted elsewhere”](https://typeroll.com/docs/guides/customer-publishing/#when-dns-is-hosted-elsewhere) R2 media domains must belong to a zone in the same Cloudflare account as the bucket. You do not need to move your root website, email or unrelated subdomains. Cloudflare’s partial CNAME setup connects selected hostnames while keeping your existing authoritative DNS provider and nameservers. It requires Business or Enterprise. Selecting external DNS management in Typeroll means you or your agent manage the records, including records in Cloudflare; it does not bypass this provider requirement. If your domain already uses Cloudflare DNS, keep other records pointing at their existing services. A CNAME pointing to an `r2.dev` address is unsupported. See [R2 custom domains](https://developers.cloudflare.com/r2/buckets/public-buckets/) and [partial setup availability](https://developers.cloudflare.com/dns/zone-setups/partial-setup/). ### Read status and complete setup [Section titled “Read status and complete setup”](https://typeroll.com/docs/guides/customer-publishing/#read-status-and-complete-setup) **Shared media domain status** distinguishes missing Cloudflare access, unfinished R2 setup, an unattached or disabled media domain, pending ownership/certificate activation, and an active Cloudflare media domain. Provider errors are shown as an unknown status, not as proof that a working domain is disconnected. The panel names the connected account and public bucket and records when it was checked. For manual setup, open **Cloudflare → R2 object storage → the public bucket → Settings → Custom Domains → Add**. Enter the shared media hostname, select **Continue**, review the record and select **Connect Domain**. Use **Manage DNS** in the connected domain’s menu to view the record. With partial setup, also apply Cloudflare’s supplied verification and CNAME records at your DNS provider. The UI links to Cloudflare’s current instructions; do not guess a target or point the hostname at the S3 API endpoint. An active media-domain status does not verify every site address or publish a site. Website and version addresses have their own DNS requirements and public verification in the site’s Publishing flow. The address base itself does not serve a website; generated addresses are below it. Deployment verifies actual published media files before exposing the live link. The organization API `GET /api/v1/publishing/domains` and MCP `read_organization_publishing_domains` return the same `domain_status`, including `state`, `checked_at`, `zone_check`, certificate/ownership state and structured `steps`. Set `sites_domain` and `media_host` independently using the corresponding PUT route or `set_organization_publishing_domains`. Legacy `default_domain` configurations retain their old addresses until explicitly updated. Changing the site address base affects subsequent deployments; an existing shared media host cannot be replaced by a plain settings overwrite. To use the same automatic setup from an agent: 1. Call `GET /api/v1/publishing/zones` or MCP `list_organization_publishing_domains` to list available domains. 2. Read the current configuration revision from the domains endpoint. 3. Call `POST /api/v1/publishing/domains` or `configure_organization_publishing_domains` with `revision`, `zone_id`, `media_subdomain` and `sites_subdomain`. The labels contain no dots or URL. 4. Poll the domains endpoint while `domain_status.state` is `pending`. A `setup_error` means settings were saved but provider setup needs attention; use the returned revision when retrying. These endpoints require an organization API key. Site keys cannot discover or configure organization domains. Setup creates the selected R2 media connection; it does not publish a website or modify unrelated DNS records. ## Publish a site or version [Section titled “Publish a site or version”](https://typeroll.com/docs/guides/customer-publishing/#publish-a-site-or-version) Choose the site and its **Version**, save changes and select **Deploy**. The `main` version publishes the live site. Other versions use `version-` Git branches and separate public test addresses under the organization’s site address base. Those versions and default-domain demos use `noindex`. Typeroll freezes the selected version, including inherited blocks, templates, collections and runtime settings, and pushes generated source to GitHub. The selected shared build engine installs the pinned dependencies and runs Astro. The resulting static files go to the Site’s Hosting Group on Cloudflare Pages. While the build or domain propagation is pending, the interface shows progress. The link appears automatically after verification. The repository is generated output. Edit through Typeroll’s UI, API or MCP. Manual repository changes are unsupported and may be replaced by a publication. ## Website and media hosts [Section titled “Website and media hosts”](https://typeroll.com/docs/guides/customer-publishing/#website-and-media-hosts) Open **Site settings → Publishing → Website and media addresses**. Set the website host and, optionally, a separate media host. For example: | Setting | Example | | ------------------------------ | ----------------------------------------------------------------------- | | Organization shared media host | `media.example.com` | | Site website host | `www.customer.com` | | Site media host | `images.customer.com` | | Media path prefix | Empty for a separate media host; `/media` when sharing the website host | Before a site has its own media host, an image can use `https://media.example.com/media//photo.png`. With a separate site media host it can use `https://images.customer.com/photo.png`. Referenced public media is included in the static site output; shared media aliases remain available through organization storage and configured URL rules. No dynamic Worker serves the website or the images. A media item’s `public_path` can preserve a legacy path such as `/wp-content/uploads/2024/photo.jpg`. Public paths are immutable: a different file must use a new path. This protects older deployments and cached links. Organization media URLs and previously published aliases remain available after a site changes its preferred host. Builds use the new preferred addresses; images are not moved into GitHub. ## Prepare a domain change before switching traffic [Section titled “Prepare a domain change before switching traffic”](https://typeroll.com/docs/guides/customer-publishing/#prepare-a-domain-change-before-switching-traffic) 1. Save the future website and media addresses. This records intent and keeps the current website address active. 2. Select **Prepare domain change from published content**. The candidate uses the last successful public snapshot, including its renderer, rather than newer saved CMS edits. Internal absolute links on the old website origin, canonicals, sitemap addresses and media references are retargeted. 3. Review **Domain verification**. Apply any validation records shown if you manage DNS externally. For Cloudflare DNS, use **your domain → DNS → Records**. Refresh verification or wait for its automatic update. 4. When the candidate and certificate checks permit it, select **Switch website traffic**. With external DNS management, apply the reviewed CNAME yourself. Version custom domains require a **proxied** Cloudflare CNAME. 5. Typeroll checks the public address before marking it live. Cloudflare Pages may require traffic DNS to validate a hostname. Typeroll does not overwrite an existing destination while its certificate is unverified. If validation cannot finish with current DNS, the change stays blocked and needs a provider-specific migration arrangement; it is not a promise of a zero-downtime cutover for every external DNS setup. Reviewed DNS changes also stop if another administrator changed the records in the meantime. ## Media migration and independent builds [Section titled “Media migration and independent builds”](https://typeroll.com/docs/guides/customer-publishing/#media-migration-and-independent-builds) After R2 and the organization shared media host are connected, Typeroll copies old originals to your private bucket, verifies SHA-256 hashes, and changes storage references only after verification. Concurrent edits and uploads granted before connection are handled without switching them to an unverified destination. Progress and retry instructions appear in Publishing. Existing source files are retained while older publications may still need them. New browser uploads go directly to your R2 account after it is ready. Disconnecting that account does not silently move uploads back to the hosting operator. The generated repository includes public content, renderer source and a dependency lock. Run `npm ci` and `npm run build` with its pinned Node version to build it on your own infrastructure. R2 originals remain separate. Cloudflare builds receive short-lived grants for the exact original and output objects. For independent builds, provide your own R2 access as described in the generated README. Forms, Apps and Extensions can still depend on their runtime services; the repository lists these in `publication.json` under `runtime_dependencies`. A generated site repository is not a full CMS backup. ## API and MCP [Section titled “API and MCP”](https://typeroll.com/docs/guides/customer-publishing/#api-and-mcp) Site API keys need admin permission for domain writes. Organization settings require an organization API key. An external agent can use its own Cloudflare access to configure DNS and R2 rules, then ask Typeroll to verify them. | Action | MCP tool | API route below `/api/v1` | | -------------------------------- | -------------------------------------- | ----------------------------------------- | | Check setup | `read_publishing_readiness` | `GET /sites/{site}/publishing` | | Read site hosts | `read_publishing_domains` | `GET /sites/{site}/publishing/domains` | | Save future hosts | `set_publishing_domains` | `PUT /sites/{site}/publishing/domains` | | Prepare last public snapshot | `prepare_publishing_domain_change` | `POST /sites/{site}/publishing/prepare` | | Approve verified traffic switch | `approve_publishing_domain_cutover` | `POST /sites/{site}/publishing/cutover` | | Read organization domain | `read_organization_publishing_domains` | `GET /publishing/domains` | | Save organization domain | `set_organization_publishing_domains` | `PUT /publishing/domains` | | Read media migration | `read_organization_media_migration` | `GET /publishing/media-migration` | | Retry media migration | `retry_organization_media_migration` | `POST /publishing/media-migration` | | Read a private image temporarily | `read_private_media_url` | `GET /sites/{site}/media/{media}/content` | | Revoke a preview | `revoke_preview_link` | `POST /sites/{site}/preview-link/revoke` | Domain writes include the current `revision`. Cutover also includes `candidate_id`. A stale revision returns 409. Use the normal deploy-status API to inspect build progress and `read_publishing_domains` for structured DNS requirements.