Skip to content

feat: start the docs site - #1

Merged
MobileMage merged 27 commits into
mainfrom
feat/site
Oct 3, 2026
Merged

MobileMage merged 27 commits into
mainfrom
feat/site

Conversation

@MobileMage

@MobileMage MobileMage commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

This starts the Gatepost docs site, built with Astro and Starlight and
served from GitHub Pages. It has the brand theme and the unofficial
notice on every page, a playground that parses postcodes in the
browser, guides for the TypeScript packages and the PHP package, the
API reference of both, the grammar, client contract and glossary copied
from the spec on each build, and a tracker of the fixes sent to other
tools.

Every code example in a guide runs in a test against the mock gateway,
and its shown result is compared with the real one. Each guide says
that the first alpha is not published yet, and a test ties that
sentence to one flag, so it goes when the packages are released.

Every page is checked in a real browser: axe for WCAG 2.2 AA in both
themes at desktop and phone width, reflow at 320 pixels, the skip link,
no request to another site and no stored key that the privacy page does
not name. A link check runs on the built site as Pages serves it. The
site loads nothing from another site and keeps no tracking, and no test
or build step can reach a NIPOST host.

This change is larger than the 400 lines that GIT-5 suggests, because
it starts the repo. Most of it is checks, pages copied from the spec
and generated reference.

Signed-off-by: MobileMage aidelojejoshua@gmail.com

Gatepost needs one site for the guides, the API reference, the spec
and a playground. Astro and Starlight build it as static files for
GitHub Pages. The theme uses the brand colours, with text colours that
reach 4.5:1 in both themes. Each page carries the line that NIPOST did
not make the site, and the site tests fail when a page lacks it or
loads anything from another website.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
The docs site must meet WCAG 2.2 AA, and the privacy page makes
promises that a browser can check. axe now checks each page in the
light and the dark theme, a page must fit 320 pixels with no sideways
scroll, and the first Tab reaches the skip link. The privacy tests fail
on a request to another site, on a cookie, and on a stored key that the
privacy page does not name.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
Each public symbol of the TypeScript packages has a doc comment with an
example. TypeDoc now turns those comments into pages of the site, in
the same theme and under the same accessibility checks as the guides.
A test reads the API report of each package, so a public symbol
without a page fails CI.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
The spec ranks above the standards and the code, so readers need it in
the docs. The build copies grammar.md, client.md and the glossary from
the spec submodule, with a link to each file at the pinned commit. A
test fails when an SDK of the site implements another spec version.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
The no-third-party check read only the fetching attributes and the
built style sheets. An inline style element, a style attribute or a
script could still name another host. The check now reads those too,
and it reads the built script files. Pagefind keeps a dummy base host
and translator credit links in its scripts, so the check ignores those
two patterns and the XML namespaces.

The deploy job also runs only on main, because a manual run may start
from any branch. A test fails when the workflow gains a trigger other
than a push to main or a manual run, or when a checkout keeps its
credentials. The theme comment now names the test that checks contrast.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
The stored-key test visited two pages, so a script on any other page
could keep an unnamed key in the browser. It now runs on every page of
the sitemap and on the 404 page.

The API reference test read only five kinds of export. An enum, an
abstract class or a namespace had no page and no failure, and an empty
report passed. The reader now knows those kinds, fails on any other
line that starts with export, and fails on a report with no export.

The privacy page now says that the side menu key also keeps the scroll
position, as Starlight stores it.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
On a narrow screen the tables of the grammar and the client contract
scroll sideways inside their own box. A keyboard user could not reach
that box. The spec pages now put each table in a labelled region that
takes the focus, and the style sheet lets that box scroll instead of
the table.

The axe run used the desktop width only, so it could not see the fault.
It now also runs at 320 pixels on every page.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
Readers learn the parser fastest by typing into it. The playground runs
@gatepost/core in the browser and shows the segments, the forms and
the suggestion for each input. It makes no request and keeps nothing,
and its strings come from a message catalogue. The tests drive it with
the keyboard alone and run axe while a suggestion shows.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
The client needs a key and a network, so the playground cannot run it.
The build now runs the real client against the mock gateway and shows
its answers, an error included, as static code on the playground page.
Each answer uses a synthetic postcode, and the page makes no call.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
The branch floor never ran, because the test script had no coverage flag
and the coverage provider was not installed. The script now measures
coverage, and a run with the playground tests skipped fails on the floor.

The accuracy status now waits for a pause in typing, like the postcode
status. A negative or invalid accuracy gets its own message. The unused
district message is gone, so a new district rule fails loudly. New tests
pin the message of each error, the delay of the status and the layout of
the page at 320 pixels.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
The sample recorder turned every client error into a recorded answer, so
a broken mock gateway could pass the build and appear on the page as
normal output. Each sample now names its outcome, success or one exact
error code, and the build fails with both outcomes when they differ.
The recorder also refuses a gateway that is not on a loopback host, and
the tests check that the gateway stops after a failure.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
Developers start from a guide, not from the reference. The guides show
how to read a postcode offline and how to ask the gateway about it.
Each example runs in CI against the built packages and the mock
gateway, and each result that an example shows is compared, so a page
cannot show an answer that the SDK does not give.

Each table sits in a labelled region that takes the focus, so a
keyboard user can scroll it on a narrow screen.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
PHP developers need the same guide and reference as TypeScript ones.
The guide's examples run with PHP against the mock gateway, and a
small reflection script writes the reference from the doc comments,
in the theme and the checks of the site. A test compares the pages with
the API dump of the PHP repo, so a public class without a page fails.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
The extractor found only plain fences, so a fence with a title, a
tilde fence or a fence in a list showed code that no test ran. It now
finds all of them and fails any block that has text after the
language, has no closing fence or is in a language with no check. A
block that cannot run carries the mark "notrun".

A result comment that the comparer cannot read, such as a double-quoted
string or an array, now fails too. The install check needs every line
of a block to be an install command. The test also type-checks each
TypeScript example, and the paths no longer depend on the working
directory.

The client guide now says what the client retries: a 502, 503 or 504,
a network error, and a timeout of lookup and reverse. The guide shows
a cancelled autocomplete call. The search test waits 15 s, because
Pagefind loads cold under parallel test load.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
An empty or missing package gave an empty PHP reference with exit 0.
The script now stops with a message. The timeout sentence of the guide
said the client waits, but the client only reads a failed attempt, so
the sentence now says that the HTTP client owns the limit.

A PHP example that missed the expected factory line kept the default
base URL and could call the real gateway. The helper now throws unless
the example calls only loopback addresses. A PHP line with a result
comment that no output check compares now fails too. The reference
script also keeps typed parameters with spaces, hides internal members,
reads nested folders, and the build names a missing PHP.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
The press and the upstream projects look for the readiness tracker next
to the tools, so the docs site now holds it. Every build checks each
link inside the site, with its fragment, and a weekly job checks the
links to other sites. No check ever calls NIPOST's gateway or platform.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
The helper edited an example only when it held the short form
new PostcodeClient(. An example with the full class name skipped the
edit and the check, and could then call the real gateway. The helper
now acts on any mention of the client class, and it throws, with the
name of the example, unless the result names the loopback gateway.

The PHP child process had a 60 s limit under a 5 s test limit, so the
child could outlive a failed test. The test limit is now above the
child limit, so the child stops first.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
The link check served the build at its root and rewrote /docs/ away,
so a link without the /docs base passed here and gave a 404 on GitHub
Pages. The check now serves the build under /docs/ and reports such a
link as broken. It also skips the /api path of NIPOST's website in
every form, retries after a 429 answer and fails when the crawl finds
too few links. The readiness page now says which fixes are sent and
which are not, gives its date and links NIPOST's docs.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
The weekly link job may fetch only docs.postcode.gov.ng from NIPOST.
The skip list named the gateway, the platform and one API path, so the
dashboard link was fetched, and a new NIPOST host would have been
fetched too. The check now skips every host of postcode.gov.ng except
the docs host.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
The install check compared the whole argument with the package name, so
it rejected a line such as composer require gatepost/postcode:^0.1@alpha,
which Composer needs for an alpha. It now reads the package before the
constraint and still rejects any text that is not one install line.

The check that keeps the PHP examples away from NIPOST read the source
text only. It edited the first client of an example, trusted a class
name built from strings, and left TypeScript examples with no address
check. It now counts the clients against the edited lines, refuses a
class built from text, and fails closed. Below the text checks, the PHP
child process sends every request to a dead local proxy, and the unit
tests replace fetch with one that refuses any host but this machine, so
an example that escapes the text check still reaches no other host.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
The three install guides gave a command that fails today, because no
package is on npm or Packagist yet. Each guide keeps the real command
and adds one sentence that the first alpha is not published and that
the page will say when it is. The PHP command now carries the alpha
constraint that the package README gives, because Composer installs
only stable releases otherwise.

A flag in src/release-state.json holds the state. A test fails when a
guide gives an install command without the sentence while the flag says
"not published", and when a guide keeps the sentence after the flag says
"published". One later commit removes the sentence and sets the flag.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
The tracker said that every sent fix accepts both postcode forms and
rejects 00. The faker fix makes postcodes and accepts nothing, and it
makes the new form only. The page also promised the same for the two
fixes that are not sent, and the WooCommerce fault is a hidden field,
not a rule. Each row now matches its pull request. The faker row also
says that one maintainer approved the pull request.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
The link check skipped every absolute link to the published address, so
a wrong hand-written link of that kind passed. The check now rewrites
the published address to the local server and follows the link. It skips
only the canonical link of the 404 page, which has no page of its own.

The decision about the exit code moved into a function that a test can
reach, so a crawl that finds too few links is covered by tests.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
A shared link showed an empty large card, because no page named an
image. Every page now names a 1200 by 630 card of the site. The 404 page
now has its own content entry with a noindex mark, which removes the
build warning about the missing entry. The home page had the title
"Gatepost | Gatepost", so it now has a title that says what the site
is. The font sentence moved to the privacy page, and the home page ends
on a link to the readiness tracker. The preview command no longer builds
the generated pages, because it reads none of them.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
The start page said that test keys work on a staging gateway whose
address NIPOST does not publish, so a reader with a test key got 401
from every example. The playground promised that a guide explains each
field, and the API reference does. The README and the agent notes said
that every page runs its examples, and only the hand-written pages do.
The agent notes named a decisions folder that does not exist, and a
style comment named a plugin that does not exist.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
The pin was one commit behind the tag of the first PHP alpha. The
difference is the changelog only, so the reference does not change.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
@MobileMage
MobileMage marked this pull request as ready for review October 3, 2026 15:16
The check that a PHP example cannot reach another host compared one
exact curl message. curl on Linux words the same refusal differently,
so the test now accepts both and still fails when the request leaves
this machine.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
@MobileMage
MobileMage merged commit 98d78e3 into main Oct 3, 2026
4 checks passed
@MobileMage
MobileMage deleted the feat/site branch October 3, 2026 15:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant