| name | review-static-site |
| description | Use this skill to inspect, validate, QA, or sanity-check a generated static website, personal blog, portfolio, digital garden, or style recreation before handoff or publishing. Use it for local folders such as site/, dist/, out/, or public/ to check broken links, missing page types, browser rendering, console errors, desktop/mobile screenshots, UTF-8 source readability, mojibake, relative asset paths, direct-open/file compatibility, placeholder content, and leftover copied source-specific text. |
Review Static Site
Goal
Validate a static website output before the user edits it further, publishes it, or treats it as finished.
This skill is a quality gate for generated HTML/CSS/JS sites. It does not choose a theme, recreate a reference, migrate content, or deploy the site. It verifies that the generated folder behaves like a real static site.
Core checks:
- Source files are valid UTF-8 and human-readable.
- Local links, scripts, stylesheets, images, and other assets resolve.
- Site-local links and assets use page-relative paths by default, not root-absolute paths such as
/assets/style.css.
- The output can be opened directly from
index.html for manual preview unless the user explicitly accepted server-only behavior.
- The generated pages cover the expected page types.
- The site renders in a real browser over local HTTP.
- Desktop and mobile layouts are usable.
- Console errors, broken interactions, leftover placeholders, and copied source-specific text are reported or fixed.
Contract
Inputs:
- Static site root such as
site/, dist/, out/, public/, docs/, or repository root.
- Optional expected page scope, local preview URL,
EDITING.md, reference URL/screenshot, and forbidden source-specific strings.
Outputs:
- Findings ordered by severity, or fixes when validation is part of a build/fix task.
- Static audit results, browser pages/viewports checked, and changed files if any.
- Clear pass/fail state for publishing or handoff readiness.
Boundaries:
- Do not choose themes, recreate websites, migrate content, personalize identity, or deploy.
- Do not redesign the site during validation unless a visual issue blocks usability and the user asked for fixes.
- Do not bless root-absolute site-local paths unless
--allow-root-absolute is intentionally used and the limitation is stated.
Success gate:
- No blocker remains: broken primary nav, missing required page type, unreadable source encoding, local asset failure, console crash, mobile unusability, or accidental root-absolute path issue.
- Warnings are either fixed, documented, or accepted by the user.
If gate fails:
- Fix straightforward local issues when validation is part of the build.
- Route larger failures to
make-personal-site, copy-website-style, personalize-site, add-blog-posts, or edit-site-part depending on the failed surface.
- Re-run deterministic audit and affected browser checks.
Use With
Use this skill after:
make-personal-site creates or redesigns an original static personal site.
copy-website-style recreates a target site's style as static files.
- A user points to an existing static output folder and asks whether it is good enough.
- A user asks to check, validate, QA, inspect, audit, or test a static site before publishing.
If the user gives a framework source project, validate the already-built static output folder when possible. Do not introduce a framework build workflow here unless the user explicitly asks.
Inputs
Use any available inputs:
- Static site root folder, such as
site/, dist/, out/, or public/.
- Local preview URL, if a server is already running.
- Expected page scope: homepage only, full personal site, blog, portfolio, notes, links, style recreation, etc.
EDITING.md, page map, or any handoff notes produced by another skill.
- Reference URL or screenshot, when validating a style recreation.
- Known strings that must not remain, such as original author names, domains, emails, analytics IDs, or old placeholder text.
If the site root is unclear, inspect nearby folders and choose the one containing index.html and static assets.
Workflow
- Identify the static site root and expected page scope.
- Read
EDITING.md or infer the page map from HTML files and navigation links.
- Run the deterministic file audit script.
- Start or reuse a local HTTP server for the static root.
- Validate the site in a real browser at desktop and mobile widths.
- Open at least one representative page for every generated page type.
- Test core interactions such as navigation, theme toggle, search/filter, copy buttons, mobile menu, and pagination.
- Check browser console errors and missing network resources.
- Audit relative path compatibility, placeholders, UTF-8 readability, and source-specific leftover text.
- Fix straightforward defects when the user asked for validation as part of a build; otherwise report findings first.
Deterministic File Audit
Use the bundled script before browser validation:
python scripts/static_site_check.py <site-root>
For style recreations or copied-site cleanups, pass forbidden source-specific strings:
python scripts/static_site_check.py <site-root> --forbid "original-author" --forbid "original-domain.com"
The script checks:
- UTF-8 decoding for HTML, CSS, JS, JSON, Markdown, SVG, XML, and text files.
- Suspicious mojibake and replacement characters.
- Missing
<meta charset="utf-8"> in HTML files.
- Broken local
href, src, srcset, poster, action, and data-src references.
- Root-absolute site-local references such as
/assets/..., /posts/..., /data/..., or /images/... unless explicitly allowed.
- CSS
url(...) asset references, including missing or root-absolute local URLs.
- Common root-absolute site-local strings inside HTML, JavaScript, and JSON data.
- Links that escape the site root.
- Common placeholder strings.
- Forbidden strings supplied with
--forbid.
- Privacy-sensitive deploy-root files such as
.env, private keys, credentials files, and local service-account artifacts.
- Secret-like assignments, known token patterns, private key blocks, and local absolute filesystem paths in source text.
- Temporary, log, backup, and OS artifacts that should not be published.
- HTML page count and inferred page types.
- Whether
EDITING.md exists.
The file audit should still verify UTF-8 readability for vendor files, but should not treat placeholder-like words inside third-party minified vendor bundles as site placeholder content.
Treat script errors as blockers unless the user only wanted a quick exploratory review. Treat warnings as items to inspect manually.
If the site is intentionally designed to require root-relative paths under a custom domain root, run the script with --allow-root-absolute and state that direct file:// opening and GitHub project-subpath deployment are not guaranteed. Do not use this exception for generated plain static personal sites unless the user explicitly accepts that tradeoff.
Path Compatibility
Generated plain static sites should work in three common contexts:
- Directly opening
index.html from the filesystem for a quick manual preview.
- Serving the folder over local HTTP for browser automation and console/network checks.
- Deploying to a static host that may serve the site from a domain root or a subpath.
Default rule:
- Use page-relative paths for site-local links and assets.
- From root pages, use
assets/style.css, posts/example.html, and about.html.
- From nested pages, use
../assets/style.css, ../blog.html, and sibling-relative links as appropriate.
- Do not use
/assets/style.css, /posts/example.html, /data/posts.json, /images/foo.png, or / for internal navigation by default.
Also check JavaScript-generated links, search results, tag filters, copy buttons, dynamic cards, RSS/sitemap references, image covers, CSS url(...) values, favicons, fonts, and KaTeX/math vendor assets. It is not enough for static HTML attributes to be relative if JavaScript later inserts root-absolute paths.
Root-absolute paths are only acceptable when the user explicitly wants a server-root-only deployment, such as a custom domain root, and understands that direct file opening and GitHub project Pages subpaths may break.
Browser Validation
Use a real browser before final delivery. Serve local files over HTTP, not file://:
python -m http.server 8000
Then open:
http://127.0.0.1:8000/
Use an actually available interactive browser tool as the first-choice validation path for local HTTP targets. "Available" means the tool is exposed in the current turn's callable tool list, not merely mentioned in a skill, plugin list, or system description. In Codex this may be the Browser/in-app browser plugin when the user or client has routed it into the turn; in other agents it may be an equivalent visible browser, browser-use tool, or devtools-backed browser. It should open the local URL, inspect desktop/mobile viewports, exercise interactions, and check visible console/network problems.
If no interactive browser tool is exposed in the current turn, do not pretend the browser pass happened. If the validation depends on it, ask the user to enable or invoke the browser tool using their client's routing method; 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, static audits, or shell checks and state that this was a fallback, not full interactive browser validation.
Do not default to Playwright, headless-only screenshot scripts, shell-opened browser windows, or static screenshot generation when an interactive browser tool is actually callable. Screenshots are useful evidence, but they do not replace an interactive browser pass. Use Playwright only as a fallback when no interactive browser tool is callable, when the user explicitly asks for Playwright, or when a repeatable scripted regression is specifically needed.
Use Chrome automation only when the task needs the user's Chrome profile, existing tabs, extensions, authenticated remote pages, or Chrome-specific behavior. Do not rely on Chrome extension automation for file:// pages; use local HTTP instead.
Even though automation should use local HTTP, the generated source should still be direct-open compatible by using relative paths and avoiding server-only assumptions for core content. If the app/browser allows a quick file:// smoke check, open the root index.html directly and verify that CSS, images, navigation, and representative subpages are not broken. If file automation is unavailable, rely on the deterministic root-absolute path audit and mention whether direct-open was manually or automatically checked.
Browser checks:
- Desktop first screen: composition, spacing, typography, visible navigation, and obvious overflow.
- Mobile first screen: navigation behavior, text wrapping, content priority, and horizontal overflow.
- Internal navigation: all primary nav links render.
- Page-type coverage: at least one browser pass or screenshot for every generated page type.
- Interaction coverage: theme toggles, menus, filters, search, copy buttons, pagination, accordions, tabs, hover/click states, or other visible controls.
- Console state: no obvious JavaScript errors.
- Network state: no missing local CSS, JS, image, or font assets.
- Accessibility basics: focus visibility for interactive controls, readable contrast, meaningful page titles, and non-empty image alt text when practical.
For small sites, click every generated page. For larger sites, sample every page type and any route called out in EDITING.md.
Page-Type Coverage
Infer page types from filenames, routes, visible navigation, and EDITING.md.
Typical page types:
- Home.
- About or profile.
- Blog, archive, category, tag, notes, or list page.
- Article or detail page.
- Projects, portfolio, publications, or work page.
- Links, friends, resources, now, uses, garden, search, theme/settings, or other special page.
If a generated site claims to be a blog but has no article/detail page, report it. If it has navigation to subpages that do not exist, report it as a blocker.
Encoding And Source Readability
Browser screenshots are not enough. Source files must be readable by future models and humans.
Require:
- HTML files include
<meta charset="utf-8">.
- Non-ASCII text is stored as UTF-8.
- HTML, CSS comments, JavaScript strings, JSON/data files, SVG text, and
EDITING.md are readable in source form.
- No mojibake, replacement characters, or accidental browser encoding recovery.
If a terminal displays mojibake but the browser looks correct, confirm with a UTF-8-aware read before calling it broken. If the file content itself contains mojibake, rewrite affected strings from clean text instead of layering another encoding conversion.
Placeholder And Residue Audit
Check whether the generated site still contains:
TODO, FIXME, lorem ipsum, placeholder, replace me, your name, example.com, or sample/demo text.
- Dummy emails, fake social links, empty buttons, or dead calls to action.
- Original-site author names, domains, article titles, emails, analytics IDs, social links, friend links, or private URLs in style recreations.
Do not remove placeholders blindly if the user still needs them as intentional editable markers. Report them clearly, or replace them only when the user has supplied real content.
Privacy And Local Residue
Treat these as blockers before publishing:
.env, .npmrc, .pypirc, private key files, credential JSON files, service-account files, or password vault/export files inside the deployable root.
- Secret-like assignments, access tokens, private key blocks, or API keys in HTML, CSS, JavaScript, JSON, Markdown, SVG, or text files.
- Local absolute filesystem paths such as Windows drive paths,
file:///..., /Users/..., /home/..., or /mnt/... in generated source.
Treat logs, backups, temp files, and OS metadata as warnings unless they expose private content. Remove them from the deployable output before packaging or publishing.
Fix Policy
When the user asks to "check", "review", or "tell me what is wrong", report findings first and avoid broad edits.
When validation is part of a build task or the user asks to fix issues:
- Fix broken local paths, missing charset declarations, obvious HTML mistakes, and JavaScript errors.
- Convert accidental root-absolute site-local paths to page-relative paths, including nested article pages and JavaScript-generated links.
- Add missing representative subpages only when the site scope clearly requires them.
- Replace copied source-specific content with neutral placeholders unless the user owns or supplied that content.
- Do not redesign the site during validation unless the visual problem blocks usability.
- Rerun the deterministic audit and at least the affected browser checks after fixes.
Report Format
Lead with findings ordered by severity.
Use these severity meanings:
- Blocker: broken primary navigation, missing required page type, unreadable source encoding, local assets missing, console crash, or page unusable on mobile.
- Major: placeholder/source residue that should not ship, incomplete interaction, missing
EDITING.md, partial subpage coverage, or serious visual mismatch for a recreation.
- Minor: polish issues, small responsive awkwardness, harmless warnings, or optional accessibility improvements.
Then include:
- Static root checked.
- Commands or scripts run.
- Browser viewports/pages checked.
- Files changed, if any.
- Remaining risks or checks that could not be performed.
Keep the final response concise. Do not paste long audit logs unless the user asks.