| name | publish-static-site |
| description | Publish, deploy, or prepare a finished static personal website, blog, portfolio, or style recreation for hosting on GitHub Pages, Cloudflare Pages, Netlify, or Vercel. Use when the user asks to publish a static site, configure deployment settings, add GitHub Pages workflows, choose a static hosting platform, prepare a repo for Pages/Cloudflare/Netlify/Vercel, verify a deployed URL, or explain how to deploy a site folder such as site/, dist/, out/, public/, or docs/. |
Publish Static Site
Goal
Publish or prepare deployment for a finished static website.
This skill is for deployable HTML/CSS/JS output such as site/, dist/, out/, public/, or docs/. It can also publish framework projects after they produce a static output folder, but it should not turn a plain static site into a framework project just to deploy it.
Default posture:
- Prefer simple static hosting over framework-specific deployment.
- Prefer Git-based deployment for sites the user will continue editing.
- Prefer direct upload only for quick one-off publishing.
- Do not create remote repositories, push code, change DNS, add domains, or deploy to a paid account unless the user explicitly asks for that action.
Contract
Inputs:
- Static deploy root such as
site/, dist/, out/, public/, docs/, or repository root.
- Preferred platform or target: GitHub Pages, Cloudflare Pages, Netlify, Vercel, custom domain, guidance only, or live deployment.
- Current Git/repository state, platform account access, CLI/browser login, and any deployment constraints.
Outputs:
- Concrete deployment settings: platform, branch, build command, base directory, publish/output directory, and config files when needed.
- Optional platform-specific config such as GitHub Pages workflow,
netlify.toml, vercel.json, .nojekyll, or CNAME.
- Live URL and post-deploy verification when deployment is actually performed.
- Manual dashboard steps when credentials or account access are unavailable.
Boundaries:
- Do not build or redesign the site; route defects to the appropriate child skill.
- Do not push, create repos/projects, upload, bind domains, change DNS, or use paid resources unless explicitly authorized.
- Do not use deployment as a workaround for broken local/static path compatibility unless the user explicitly accepts server-root-only behavior.
Success gate:
review-static-site has passed or unresolved risks are explicit.
- The deploy root contains
index.html and the platform will publish the correct folder.
- Online URL loads homepage, assets, navigation, and representative subpages after deployment.
If gate fails:
- Fix path, asset, encoding, or page-type blockers before deployment.
- Route content/design/import issues to
personalize-site, edit-site-part, add-blog-posts, make-personal-site, or copy-website-style.
- Re-run
review-static-site and then retry or update deployment settings.
References
Load only the reference needed for the chosen platform or issue:
- Path strategy and direct-open compatibility:
references/path-strategy.md.
- Cloudflare Pages Git integration and Direct Upload:
references/cloudflare-pages.md.
- GitHub Pages branch source and Actions workflows:
references/github-pages.md.
- Netlify dashboard and
netlify.toml: references/netlify.md.
- Vercel dashboard and
vercel.json: references/vercel.md.
Official docs:
Deployment Modes
First determine what the user actually wants:
- Guidance only: explain platform choice and exact settings. Do not edit files unless useful.
- Prepare repo: add the needed config files and tell the user what to click in the hosting dashboard.
- Deploy now: perform remote actions only if the user explicitly asked and the required CLI/auth/session exists.
- Verify live URL: open the deployed URL in a browser and check it against the local site.
If credentials, account access, browser login, or CLI authentication are missing, provide exact dashboard steps instead of inventing a workaround.
Workflow
- Identify the static output folder and the user's preferred platform, if any.
- Call or suggest using
review-static-site before publishing.
- Confirm the deploy root contains
index.html.
- Inspect asset paths and convert accidental root-absolute site-local paths before publishing. Load
references/path-strategy.md when path behavior is unclear.
- Choose the simplest matching platform and deployment mode.
- Load the chosen platform reference and add only the config files required by that platform.
- If deploying through Git, check Git status and avoid including unrelated or private files.
- If the user authorized remote actions, push or deploy exactly what was agreed.
- After publishing, open the live URL and verify the deployed site in a browser.
Preflight Checklist
Run these checks before writing deployment configs or telling the user settings:
- Deploy root: choose the folder that directly contains
index.html.
- Entry page:
index.html must exist at the deploy root top level.
- Direct-open preview: the root
index.html should keep CSS, JS, images, and navigation when opened directly from the filesystem, unless the user explicitly accepted server-only behavior.
- Local HTTP: serve the deploy root with
python -m http.server and confirm it works over http://127.0.0.1:<port>/.
- Static audit: run or recommend
review-static-site for links, UTF-8 readability, placeholder residue, browser rendering, privacy residue, and mobile layout.
- Asset paths: inspect
href, src, srcset, CSS url(...), fonts, favicons, cover images, RSS, sitemap, and manifest links.
- Private data: make sure tokens, local filesystem paths, draft notes, source-site identities, and personal secrets are not being published.
- Output completeness: confirm subpages, posts, images, vendor fonts, KaTeX/math assets, and copied media are inside the deploy root.
Treat these as blockers:
- No
index.html in the deploy root.
- Broken local CSS, JS, image, font, RSS, sitemap, or vendor asset paths.
- Source files contain mojibake or unreadable encoding.
- The generated personal site still contains copied source identity that should have been replaced.
- Accidental root-absolute site-local paths such as
/assets/..., /posts/..., /data/..., or /images/... remain in a generated plain static site.
- The site works over local HTTP only because root-absolute paths are being served from
127.0.0.1, but direct file opening or subpath deployment would lose CSS/JS/images.
- Privacy-sensitive files or secrets would be deployed.
- The platform would deploy the wrong folder.
Platform Choice
Use this default ranking for plain static personal sites:
- Cloudflare Pages Git integration: best default for a generated
site/ folder and future updates.
- GitHub Pages with GitHub Actions: best when the user wants everything inside GitHub.
- Netlify: simple static hosting with friendly previews and dashboard settings.
- Vercel: good when the user already uses Vercel or may later move to Next.js, but not the default for plain HTML.
Decision rules:
- If the user wants the least friction and has a GitHub repo: Cloudflare Pages Git integration. Load
references/cloudflare-pages.md.
- If the user wants GitHub-only hosting: GitHub Pages. Load
references/github-pages.md.
- If deploy files live in repository root or
/docs: GitHub Pages branch source is acceptable.
- If deploy files live in
site/, dist/, out/, or another custom folder: prefer GitHub Actions for GitHub Pages.
- If the user wants manual upload today: Cloudflare Direct Upload or Netlify manual deploy.
- If the user already has a Vercel account/project: use Vercel with explicit output directory settings.
Framework Static Output
If the site is not plain HTML/CSS/JS:
- Inspect
package.json, framework config, and existing scripts.
- Use the project's existing build command; do not invent npm workflows.
- Publish the final static output folder, not the source folder.
- Common outputs include
dist, out, build, .output/public, and public, depending on the framework.
- For Next.js static export, verify the project is actually configured for static export before treating
out/ as final output.
- For Vue/Vite/Astro-style projects, publish the configured output directory after a successful build.
If the user asked for plain static publishing and no framework files exist, do not introduce npm.
Config File Policy
Only add config files that match the chosen platform:
- GitHub Pages Actions:
.github/workflows/pages.yml.
- GitHub Pages custom domain:
CNAME in the deployed root, only when the user supplied the domain.
- GitHub Pages Jekyll bypass:
.nojekyll in the deployed root when useful.
- Netlify:
netlify.toml only when dashboard settings are not enough or the user wants config in Git.
- Vercel:
vercel.json only when Vercel needs explicit output settings.
- Cloudflare Pages: usually dashboard settings are enough for plain static sites.
Do not add deployment configs for every platform at once.
Git And Remote Safety
Before any remote action, state what will happen and confirm the user asked for it:
- Creating a GitHub repository.
- Adding a remote.
- Staging or committing files.
- Pushing commits to a remote branch.
- Enabling GitHub Pages.
- Creating Cloudflare, Netlify, or Vercel projects.
- Uploading files to a hosting provider.
- Adding environment variables.
- Adding custom domains or changing DNS records.
Before staging or pushing:
- Run
git status --short.
- Identify generated site files versus unrelated user changes.
- Do not stage unrelated changes.
- Do not publish private notes, credentials, local paths, screenshots with secrets, or temporary files.
Never put secrets, tokens, private notes, or local filesystem paths into the static site or deployment config.
Post-Deploy Verification
After the platform reports a live URL:
- Open the deployed URL with an actually available interactive browser tool. "Available" means it is exposed in the current turn's callable tool list. In Codex this may be the Browser/in-app browser plugin when routed into the turn.
- Verify the homepage is not a 404, blank page, or directory listing.
- Verify CSS, JavaScript, images, fonts, favicon, RSS, sitemap, and vendor assets load from the deployed domain.
- Click primary navigation and at least one representative subpage per page type.
- Test desktop and mobile widths.
- Check browser console for missing assets or JavaScript errors.
- Confirm metadata, title, description, Open Graph image, canonical URL, RSS, sitemap, and robots files when present.
- If using GitHub project Pages, specifically check subpages and asset URLs under the repository subpath.
- If using a custom domain, verify HTTPS and redirects between apex and
www if configured.
If no interactive browser tool is callable, do not pretend live browser verification happened. Ask the user to enable or invoke the browser tool if live visual verification matters; for Codex, that may mean sending a request that explicitly mentions @browser. If the user does not re-route or the client has no such tool, fall back to Playwright, screenshots, HTTP checks, or static checks and state the limitation.
Do not default to Playwright or screenshots-only live verification when an interactive browser tool is actually callable. Use Playwright only as a fallback, or when the user explicitly asks for scripted deployment checks.
If the deployed site differs from local preview, inspect the deploy log, output directory, and asset path strategy before changing design code.
Output
Keep the final user-facing report concise:
- Platform chosen and why.
- Static folder published or prepared.
- Deployment mode: guidance, prepared config, Git integration, direct upload, or live deploy.
- Settings used: branch, build command, base directory, publish/output directory.
- Config files changed, if any.
- Official guide URL for the chosen platform.
- Live URL, if deployment happened.
- Verification performed and any remaining manual step.
If only guidance was requested, do not pretend the site was deployed. Give concrete platform settings and official guide links.