@goflag/cli 0.2.12 → 0.2.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -9
- package/dist/{chunk-QKXUKHXB.js → chunk-YQPL67HX.js} +610 -69
- package/dist/chunk-YQPL67HX.js.map +1 -0
- package/dist/cli.js +63 -1
- package/dist/cli.js.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +3 -2
- package/rules.json +116 -2
- package/dist/chunk-QKXUKHXB.js.map +0 -1
package/README.md
CHANGED
|
@@ -5,6 +5,12 @@ A CLI that audits a site for broken links, missing translation pages, a robots.t
|
|
|
5
5
|
[](https://github.com/tancredesimonin/goflag/blob/main/package.json)
|
|
6
6
|
[](#license)
|
|
7
7
|
|
|
8
|
+
[](https://goflag.tech/docs/report)
|
|
9
|
+
|
|
10
|
+
<sub>The first eleven lines of a real run. Rendered from the same transcript the
|
|
11
|
+
documentation site paints, which is compared to the renderers byte for byte —
|
|
12
|
+
so this picture cannot drift from what the command prints.</sub>
|
|
13
|
+
|
|
8
14
|
Goflag crawls a site once and judges what it found. It is deliberately small: no dashboard, no config system, no social-preview gallery. Just the findings, as a machine-readable report you can pipe, diff, or gate CI on.
|
|
9
15
|
|
|
10
16
|
It is built for the mistakes that are invisible while browsing and expensive in
|
|
@@ -38,14 +44,14 @@ here and carries no code.
|
|
|
38
44
|
- **Open Graph, past its presence** — a declared `og:image` is judged as well as counted: relative URLs no crawler can resolve, an undeclared size (so the first share of a URL renders without the image), a shape far from the 1.91:1 the card is cropped to, a missing `og:image:alt`, and — the one no tag check can reach — whether the URL actually serves an image at all. On a translated page, `og:locale` and `og:locale:alternate` are checked against the hreflang cluster — two vocabularies for one fact, which nothing in a build keeps in step.
|
|
39
45
|
- **Icons** — whether anything declares one at all (nothing in a spec requires it, which is why nothing complains), whether iOS has an `apple-touch-icon` to use instead of screenshotting the page, whether the Web App Manifest and the `<head>` contradict each other about the same file, whether every declared icon answers with an image, whether a `sizes` attribute describes the file it points at (a `.ico` carrying 16, 32 and 48 declared as `48x48` advertises a third of itself), and whether the origin actually serves `/favicon.ico` — a 200 of HTML from a catch-all route does not count. Two icon lists that merely differ are the normal case and are not reported.
|
|
40
46
|
- **Sitemap** — whether there is one, whether it parses (an HTML error page served with a 200 reads as healthy to anything that only checks the status), whether it lists anything, and whether an index can reach its children. Each entry is judged too: a `<loc>` that is not absolute, entries on another host or another protocol, a `<lastmod>` that is not a W3C Datetime or is dated in the future, a `changefreq` or `priority` outside the values the protocol defines.
|
|
41
|
-
- **Where the two files meet the crawl** — the contradictions no single artefact shows. A sitemap entry that `robots.txt` forbids fetching, one whose page declares `noindex`, one whose canonical points elsewhere, one that 404s or redirects, and the indexable pages the crawl found that the sitemap never lists. Entry probing answers from the crawl and the link audit before it fetches anything, so a well-built site costs almost no extra requests — and when the caps stop it short, the finding says how many went unchecked rather than implying the rest are fine. Nothing is broken when you look at either half alone, which is why nobody finds these by reading.
|
|
47
|
+
- **Where the two files meet the crawl** — the contradictions no single artefact shows. A sitemap entry that `robots.txt` forbids fetching, one whose page declares `noindex`, one whose canonical points elsewhere, one that 404s or redirects, and the indexable pages the crawl found that the sitemap never lists — judged only once every sitemap the site declares has been read, since a page listed where goflag could not read looks exactly like one the site forgot. Entry probing answers from the crawl and the link audit before it fetches anything, so a well-built site costs almost no extra requests — and when the caps stop it short, the finding says how many went unchecked rather than implying the rest are fine. Nothing is broken when you look at either half alone, which is why nobody finds these by reading.
|
|
42
48
|
- **Unreachable pages** — a page the crawl reached that answered non-2xx, or that never answered at all (timeout, reset, DNS failure — recorded as `status: 0`), is reported in `unreachablePages`. goflag asks a second time, from the back of the queue, before calling a page unreachable. Each one is an `error`-severity finding: it turns the verdict red, counts toward `--max-debt`, and fails the build even under `--fail-on error`. A page that silently dropped out of the audited set is what poisons a baseline, so it is reported rather than warned about.
|
|
43
49
|
|
|
44
50
|
**Which pages get audited.** When goflag finds a sitemap it does not audit every URL in it. It groups URLs that share a path shape — and therefore a template — into families, audits every page that stands alone, and samples three pages per family. A cap answers "how many" and never "which": on a site of thousands of pages built from thirty templates, the first 200 pages a crawl reaches are four templates out of thirty.
|
|
45
51
|
|
|
46
52
|
The trade is stated in every report rather than hidden. Template rules (`canonical.*`, `hreflang.*`, `og.image.missing`) are conclusive on a sampled family; copy rules (`title.length`, `description.length`), broken links and the translation matrix are only conclusive on the pages that were drawn. The terminal prints a `COVERAGE` line, and `diagnostics.coverage` carries `mode`, `considered`, `selected` and every sampled family with its ratio. Pass `--coverage all` to audit what the sitemap lists in order, up to `--max-pages`, which is the pre-0.2.3 behaviour.
|
|
47
53
|
|
|
48
|
-
Pages that declare a `<link rel="canonical">` pointing at another crawled page are excluded from the checks — the site has said they are duplicates, so linting them would multiply every finding by the number of filtered variants. The count is reported as `diagnostics.duplicatePages`.
|
|
54
|
+
Pages that declare a `<link rel="canonical">` pointing at another crawled page are excluded from the page checks — the site has said they are duplicates, so linting them would multiply every finding by the number of filtered variants. The count is reported as `diagnostics.duplicatePages`. They still count for what the sitemap lists: a variant the sitemap names is the defect `sitemap.entry.non-canonical` reports.
|
|
49
55
|
|
|
50
56
|
**Client-rendered pages.** By default, a page whose `<head>` looks empty — no
|
|
51
57
|
title, no description, no canonical, no OG, no JSON-LD — is re-rendered in
|
|
@@ -61,7 +67,7 @@ fine one.
|
|
|
61
67
|
|
|
62
68
|
## Where it runs
|
|
63
69
|
|
|
64
|
-
|
|
70
|
+
Three packages ship to npm from a tag, published by GitLab CI over OIDC with no stored credential: `@goflag/cli` (`v*`), `@goflag/next` (`next-v*`) and `@goflag/og` (`og-v*`). The documentation site `apps/website` runs at [goflag.tech](https://goflag.tech), with `develop.goflag.tech` alongside it, both deployed with Kamal onto the shared OVH host described in the `infrastructure` repository.
|
|
65
71
|
|
|
66
72
|
## Your first audit
|
|
67
73
|
|
|
@@ -150,8 +156,8 @@ npx @goflag/cli rules > rules.json
|
|
|
150
156
|
```
|
|
151
157
|
|
|
152
158
|
`rules` answers a question about goflag rather than about a site: no URL, no
|
|
153
|
-
crawl, no network. It ships
|
|
154
|
-
|
|
159
|
+
crawl, no network. It ships sixty-four rules — twenty-five page rules,
|
|
160
|
+
thirty-four site rules and five prose rules — and every entry carries its
|
|
155
161
|
scope, severity and summary. All but one also carry a rigor, the documents they
|
|
156
162
|
cite and, where a remedy is a line of code, a fix snippet. The exception is
|
|
157
163
|
`hreflang.sitemap-mismatch`, which emits `rigor: null` with an empty `sources`
|
|
@@ -469,6 +475,11 @@ same confidence would be six unearned claims, so the file says which is which.
|
|
|
469
475
|
It never gates — it exits 0 unless the run itself failed — and it prints the
|
|
470
476
|
path it wrote, so `open "$(goflag preview http://localhost:3000)"` opens it.
|
|
471
477
|
|
|
478
|
+
An example of what it writes — a real audit, frozen, so its footer names the date it was
|
|
479
|
+
taken — is served at <https://goflag.tech/assets/example-preview.html>. The URL is absolute
|
|
480
|
+
because `prepack` copies this file into the package and npm renders it, where a relative link
|
|
481
|
+
is dead.
|
|
482
|
+
|
|
472
483
|
### Multilingual sites
|
|
473
484
|
|
|
474
485
|
Discovery is seeded from the sitemap, not just from links. That matters because
|
|
@@ -547,7 +558,7 @@ Three rules, whichever you use:
|
|
|
547
558
|
stages: [build, deploy, audit]
|
|
548
559
|
|
|
549
560
|
variables:
|
|
550
|
-
GOFLAG_VERSION: "0.2.
|
|
561
|
+
GOFLAG_VERSION: "0.2.14"
|
|
551
562
|
|
|
552
563
|
# Before the merge: build the branch, let goflag boot it, audit that.
|
|
553
564
|
seo:mr:
|
|
@@ -599,7 +610,7 @@ jobs:
|
|
|
599
610
|
- run: corepack enable && pnpm install --frozen-lockfile
|
|
600
611
|
- run: pnpm build
|
|
601
612
|
- run: |
|
|
602
|
-
npx --yes @goflag/cli@0.2.
|
|
613
|
+
npx --yes @goflag/cli@0.2.14 http://localhost:3000 \
|
|
603
614
|
--start "pnpm start" --static --no-external \
|
|
604
615
|
--baseline .goflag/baseline.json --regressions-only --max-debt 41 \
|
|
605
616
|
--report goflag-report.json
|
|
@@ -621,6 +632,25 @@ Audit external links on a schedule instead, where nobody is waiting.
|
|
|
621
632
|
|
|
622
633
|
### Reading a red build
|
|
623
634
|
|
|
635
|
+
A red build says what moved, not what is wrong. The diff lists rule ids and
|
|
636
|
+
absolute page URLs; the messages and the fixes are in the report:
|
|
637
|
+
|
|
638
|
+
<!-- goflag:transcript gate -->
|
|
639
|
+
|
|
640
|
+
```plaintext
|
|
641
|
+
goflag --regressions-only
|
|
642
|
+
REGRESSION 1 new · 13 known findings NOT gating this build · 1 resolved
|
|
643
|
+
baseline https://example.com/ — taken 2026-07-21T09:14:02.881Z (14 days ago)
|
|
644
|
+
|
|
645
|
+
New findings
|
|
646
|
+
+ error seo canonical.absolute on https://example.com/pricing
|
|
647
|
+
|
|
648
|
+
Resolved
|
|
649
|
+
- warn seo og.image.missing on https://example.com/about
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
<!-- /goflag:transcript -->
|
|
653
|
+
|
|
624
654
|
The report artefact is the thing to open. It is the same JSON as `--json`, and
|
|
625
655
|
it is kept whether the job passed or failed, because it is most wanted when it
|
|
626
656
|
is red.
|
|
@@ -683,7 +713,7 @@ finding unrepresentable. Full documentation at
|
|
|
683
713
|
Two of this catalogue's rules had no remedy to point at. `og.image.missing`
|
|
684
714
|
fired 24 times on one site and `og.image.alt` 46 times on another, and the fix
|
|
685
715
|
for both is "either an asset or a route you have to write" — which is how a rule
|
|
686
|
-
becomes permanent debt. [`@goflag/og`](packages/og) is that route, written once.
|
|
716
|
+
becomes permanent debt. [`@goflag/og`](https://github.com/tancredesimonin/goflag/tree/main/packages/og) is that route, written once.
|
|
687
717
|
|
|
688
718
|
```tsx
|
|
689
719
|
// app/[locale]/opengraph-image.tsx
|
|
@@ -701,7 +731,7 @@ embeds satori — turns into a PNG at build time, so nothing installs a second
|
|
|
701
731
|
renderer and a card can be unit-tested with no framework build. It also packs
|
|
702
732
|
the `favicon.ico` **no Next convention emits**, guarded so that a generated file
|
|
703
733
|
living in git is not dirtied by every commit. API reference in
|
|
704
|
-
[`packages/og/README.md`](packages/og/README.md).
|
|
734
|
+
[`packages/og/README.md`](https://github.com/tancredesimonin/goflag/blob/main/packages/og/README.md).
|
|
705
735
|
|
|
706
736
|
## Develop locally
|
|
707
737
|
|