Install
Run goflag once with pnpm dlx, or add it as a pinned dev dependency. Node 22 or newer, and Playwright Chromium when the site is not totally static.
Requirements
Two things, in this order:
- Node
>=22. The package declares that range; CI and local development run on Node 24. - Playwright Chromium, if your site is not totally static. Client-rendered
pages (Next.js App Router without full SSR for every route, SPAs, anything
that fills
<head>in the browser) need a headless browser. Without it, goflag judges the empty shell and the findings look wrong. That is not a bug in the tool; install Chromium before you decide the report is lying. See Chromium below. Pure static HTML can skip this.
Run it once
You do not have to install anything to try it:
pnpm dlx @goflag/cli https://example.comThe binary is called goflag, so once it is on your PATH (locally or in a
project) every example in these docs works verbatim.
Add it to a project
pnpm add -D @goflag/cliThen wire it to a script, so the flags live in the repository rather than in somebody's shell history:
{
"scripts": {
"seo": "goflag http://localhost:3000 --start \"pnpm start\" --no-external"
}
}--start boots the command, waits for the URL to answer, audits, then stops it
again; --no-external keeps third-party outages out of the result. See
CI for why both belong in a gate.
Pin the version you gate on
In a pipeline, do not float:
pnpm dlx @goflag/cli@0.2.12 https://example.comA floating version turns somebody else's release into a red pipeline on a commit that touched nothing, and the job is only worth having if red means you broke something.
Chromium
By default, a page whose <head> is empty of every discriminating signal — no
title (or a placeholder one like "React App"), no description, no canonical, no
Open Graph, no twitter:*, no JSON-LD and no hreflang alternate — is
re-rendered in headless Chromium, so a client-rendered application is not
reported as missing everything it actually declares at runtime.
The test is a conjunction, and deliberately conservative: one server-rendered
hreflang link or one twitter:card in an otherwise empty shell is enough to
keep the page on the static path.
That path needs playwright, which is an optional peer dependency: nothing
is downloaded unless you ask for it.
Not totally static? Install this first.
If metadata is filled in the browser and you skip Chromium, the report will look broken. Install Playwright and Chromium before filing an issue.
pnpm add -D playwrightpnpm exec playwright install chromiumWithout it, goflag does not fail: the page is judged on its static HTML, and the
report says so. Any page that wanted the browser and did not get it is counted in
diagnostics.warnings, naming what could not be started and warning that the
metadata findings on those pages may be phantoms. That warning is the signal to
install Chromium and re-run before believing a page is missing everything.
--static, if you are certain
--static turns off both the re-render and the detection that triggers it, and
never downloads anything:
goflag https://example.com --staticIt makes a run several times faster, and it is only safe when every page
emits its metadata on the server. That is rarer than it sounds, and it drifts:
one route that fills its <head> in the browser is enough to make findings
misleading, and nothing will warn you when somebody adds it next quarter. Opt
in when you are sure, re-check the assumption when the stack changes, and
leave the default alone otherwise.
Verify the install
goflag --version
goflag --helpBoth exit 0. If goflag https://example.com exits 1, that is not an
installation problem: 1 means findings were reported. See
exit codes.