1. Guide
  2. Deploy Self-Hosted

Deploy Your Locally Edited Site

You watched our video and customized your LocusPilot website on your own computer. Now you want to put it online, and you don't want to re-upload the whole site every time you add a blog post.

This guide shows you how. By the end, you'll push a change in GitHub Desktop and see it live on your domain in about 30 seconds. We'll also cover how to schedule blog posts to publish on a future date.

Looking for the dashboard publish button? This guide is the advanced path where you manage your own GitHub repo. If you want LocusPilot to keep managing the source code while publishing to your Cloudflare account, use the Publish to Your Own Cloudflare guide.

1The Quickest Way (Manual Upload)

If you just want to test your site online once, you can upload the built files by hand.

  1. In your project folder, run npm run build
  2. This creates a dist folder with your finished site
  3. Go to Cloudflare Pages and pick Direct Upload
  4. Drag the dist folder into the page
Heads up: This works, but you have to repeat all four steps every time you make a change. For real use, the auto-deploy setup below is much easier.

2Push Your Project to GitHub

GitHub is where your code lives online. The easiest tool for this is GitHub Desktop. No command line needed.

  1. Install GitHub Desktop and sign in with your GitHub account
  2. Click File > Add Local Repository and pick your project folder
  3. If prompted, click create a repository instead
  4. Click Publish repository at the top
  5. Tick Keep this code private (recommended for client sites)
  6. Click Publish repository
GitHub Desktop publish repository screen
Tip: Keep the repo private if your factsheet or business notes are inside the project. Private repos still work with Cloudflare Pages.

3Connect GitHub to Cloudflare Pages

This is the magic step. Once linked, every change you push to GitHub will rebuild your site on Cloudflare in about 30 seconds. You only do this once.

  1. Log in to your Cloudflare dashboard
  2. Go to Workers & Pages in the left sidebar
  3. Click Create application > Pages > Connect to Git
  4. Authorize Cloudflare to access your GitHub account
  5. Pick the repository you just published
  6. Click Begin setup
Cloudflare Pages connect to Git screen

On the build settings screen, fill in these exact values:

FieldValue
Framework presetAstro
Build commandnpm run build
Build output directorydist
Cloudflare Pages build settings panel

Before clicking deploy, scroll down to Environment variables and add one:

Variable nameValue
NODE_VERSION20
Important: Without the NODE_VERSION variable, the build often fails on the first try. This is the most common gotcha.

Click Save and Deploy. Cloudflare will build your site and give you a free URL like your-project.pages.dev in about a minute.

4Add Your Custom Domain

Your .pages.dev URL works fine, but you probably want your real domain. The DNS steps are the same as our hosted setup.

Follow our Connect Custom Domain guide. The only difference is you add the domain inside your Cloudflare Pages project (under Custom domains) instead of in the LocusPilot dashboard.

Agent-Ready note: Direct markdown URLs such as /index.md work on any host. Automatic Accept: text/markdown negotiation needs Cloudflare Transform Rules on the domain's Cloudflare zone. If you publish from LocusPilot to your own Cloudflare account, create the API token with Account → Cloudflare Pages → Edit, Zone → Zone → Read, and Zone → Transform Rules → Edit. Set Zone Resources to All zones or the target domain. Enter the domain in the Publish to My Cloudflare modal; don't use the separate LocusPilot-hosted Custom Domain card for this path. Domains that only use Namecheap, GoDaddy, or another DNS provider cannot do this negotiation unless you add equivalent edge rewrite support.

5Add a Blog Post (No More Re-Uploading)

Now the fun part. To add a new post, you have two choices.

Option A: Edit on your computer

  1. Open src/content/blog/ in your code editor
  2. Copy an existing post and rename the file (for example my-new-post.mdx)
  3. Edit the content and frontmatter
  4. In GitHub Desktop, write a short summary, click Commit, then Push

Option B: Edit in your browser

  1. Go to your repo on github.com
  2. Open src/content/blog/
  3. Click any post, then click the pencil icon to edit, or Add file > Create new file
  4. Click Commit changes at the bottom

No download needed. Good for small fixes from any device.

Either way, Cloudflare picks up the change and your post is live in about 30 seconds.

Frontmatter cheat sheet. Every post needs these fields at the top:
---
title: "Your Post Title"
description: "A short summary for SEO"
publishDate: 2026-05-15
author: "Your Name"
category: "Tips"
draft: false
---

6Schedule Posts for the Future

WordPress lets you pick a future date and walk away. With this setup we can do the same, but it needs a small one-time setup. There are two ways. Pick whichever feels easier.

Easy way: Use the draft flag

This works right out of the box. No extra setup.

  1. Write your post and set draft: true in the frontmatter
  2. Commit and push. The post will not show on your site.
  3. On the day you want it live, edit the post and change to draft: false
  4. Commit and push. It goes live in 30 seconds.

Good for: small batches, one or two posts at a time. Bad for: setting up posts months ahead and forgetting them.

Auto-publish on a future date

This is the real WordPress-style scheduler. It needs three small pieces, but once they're set up you never touch them again.

Piece 1: Filter future-dated posts

By default, your blog index shows every post no matter the date. Open src/pages/blog/index.astro and find the line that loads posts. Change it to:

const allPosts = await getCollection('blog', ({ data }) =>
  !data.draft && new Date(data.publishDate) <= new Date()
);

This hides any post whose publishDate is still in the future. Do the same in any other file that lists blog posts (like the homepage).

Piece 2: Get a Cloudflare deploy hook

  1. In your Cloudflare Pages project, go to Settings > Builds & deployments
  2. Scroll to Deploy hooks and click Create deploy hook
  3. Name it scheduled-rebuild and pick branch main
  4. Copy the URL it gives you. It looks like https://api.cloudflare.com/client/v4/pages/webhooks/deploy_hooks/...
Cloudflare Pages deploy hooks settings

Piece 3: Add a daily GitHub Action

  1. On github.com, go to your repo > Settings > Secrets and variables > Actions
  2. Click New repository secret
  3. Name it CLOUDFLARE_DEPLOY_HOOK and paste the URL from Piece 2
  4. Save

Now create a new file in your project at .github/workflows/scheduled-rebuild.yml:

name: Scheduled rebuild

on:
  schedule:
    # Runs every day at 09:00 UTC
    - cron: '0 9 * * *'
  workflow_dispatch:

jobs:
  trigger-build:
    runs-on: ubuntu-latest
    steps:
      - name: Trigger Cloudflare Pages deploy
        run: curl -X POST "${{ secrets.CLOUDFLARE_DEPLOY_HOOK }}"

Commit and push. GitHub will run this every day at 9am UTC and rebuild your site. Any post whose publishDate has passed will appear automatically.

Timezone note: The cron uses UTC. To run at 9am in your local time, convert the hour. For example, 9am Malaysia time (UTC+8) = 0 1 * * * (1am UTC).

7How to Write a Scheduled Post

Once Step 6 is done, scheduling is easy:

  1. Write the post like any other
  2. Set publishDate to the future date you want
  3. Make sure draft: false
  4. Commit and push today

The post sits hidden in your repo. On the morning of the publish date, the daily cron rebuilds your site and the post goes live on its own.

Which Setup Should I Use?

SetupOne-time setupPer-post effortFuture scheduling
Manual uploadNoneBuild + drag every timeNo
Auto-deploy (Steps 2-5)~15 minutesEdit + pushManual (draft flag)
Auto-deploy + scheduling (all steps)~30 minutesEdit + pushYes, fully automatic

Troubleshooting

First Cloudflare build fails

  • Check that NODE_VERSION = 20 is set in environment variables
  • Make sure the build command is npm run build and output is dist
  • Open the build log in Cloudflare to see the exact error

Push to GitHub doesn't trigger a build

  • Check the branch. Cloudflare only builds the branch you set during setup (usually main)
  • Open the Pages project and check the Deployments tab for errors

Future-dated post showed up immediately

  • You missed Piece 1 of Step 6. The date filter goes in src/pages/blog/index.astro
  • Check any other file that lists blog posts (homepage, category pages) and add the same filter

Scheduled rebuild didn't fire

  • GitHub Actions schedule can run a few minutes late. That's normal.
  • Open the Actions tab on your repo to see if the run started
  • If the secret is wrong, the run will fail. Check that CLOUDFLARE_DEPLOY_HOOK matches the URL from Cloudflare.