learning.nyuchi.com — the Nyuchi Learning surface, and the home of the classroom tools Nyuchi Web Services builds for schools.
Version: 3.0.0 | Live: learning.nyuchi.com | Default branch: master | Deploy: Vercel
A small static Astro site with two pages:
| Route | What it does |
|---|---|
/ |
Points visitors at the three surfaces the learning content lives on, and at the tool they can use today. |
/toddle-enhancement-extension |
The product page for the Toddle Enhancement Extension. |
The redirect job has not gone away — the content split described in CHANGELOG.md still holds — but this domain is now also where the classroom software lives, so the site is no longer only a signpost.
Nothing here defines a colour, a font or a component class. All of it comes from
@bundu/ui, Nyuchi's implementation
of the Mzizi design system:
/* src/styles/global.css */
@import "@bundu/ui/styles/globals.css"; /* seven minerals, semantic tokens, components */
@import "@bundu/ui/styles/brand-nyuchi.css"; /* gold primary + ring, as on nyuchi.com *//* tailwind.config.mjs */
presets: [preset] /* @bundu/ui/tailwind-preset */This is deliberate, and it is the second thing this repo got wrong before. The
previous version carried a hand-copied subset of the tokens with a comment
claiming they were verbatim; they were not, and the site drifted away from
nyuchi.com without anyone noticing. tests/branding.test.ts now fails the
build if a token is redefined locally.
If a colour looks wrong, it is wrong in @bundu/ui — fixing it there fixes
every Nyuchi surface at once.
Vercel, from master. The site is fully static — every page is known at build
time, so nothing renders per request.
Response headers, including the CSP, are declared in vercel.json.
npm install
npm run dev # http://localhost:4321 — hot reload
npm run check # astro check (TypeScript across .astro files)
npm test # build, then vitest, then the CSP hash check
npm run qa # drive a real browser: accessibility + layout, 18 combinations
npm run format # prettier --write
npm run build # produces .vercel/output for the Vercel adapter
npm run preview # serve the built output locallyvercel.json carries a real Content-Security-Policy, not just the framing and
sniffing headers. script-src is 'self' plus a hash for each inline script,
so nothing inline runs unless it was in the build that was reviewed.
There is exactly one inline script — the theme bootstrap, which has to run
before the first paint or the page flashes light before going dark. A hash
allowlist is only worth something if it cannot silently fall out of date, so
npm test verifies it:
npm run csp # fail if a built inline script is not in the CSP
npm run csp:fix # rewrite vercel.json with the current hashes, then reviewEdit the bootstrap without running csp:fix and CI fails with the missing
hash, rather than the theme quietly breaking in production.
Vite+ was evaluated and cannot be adopted yet — npm cannot install it, and both CI and Vercel install with npm. The evaluation, and the conditions for revisiting it, are in docs/toolchain.md.
- Astro 7 with Tailwind 4.
@bundu/ui@0.1.1ships a Tailwind 3 style config, which Tailwind 4 consumes through@config— that is what makestext-h2,ease-soft,max-w-narrowand the mineral colours resolve, both as utilities here and inside the kit's own@applyrules. Verified in the build output: every component class, the full token set, and thedark:variants are all present. overridespinspath-to-regexpto^6.3.0.@astrojs/vercelpulls in a version with a high-severity advisory and there is no fixed release upstream; the override is within the same major, so it is a patch rather than a behaviour change.vitestis pinned to~4.0.18.4.1.11trips a resolver bug in npm 10.9 (Cannot read properties of null (reading 'edgesOut')) andnpm installcannot complete at all. This is why the advisory on vitest is reported rather than blocking in CI — see below.*.astrois in.prettierignore. The org lint gate runs Prettier fromnyuchi/.github, which has noprettier-plugin-astro, so it cannot parse those files. They are still type-checked bynpm run check.
npm run qa builds the site, serves it, and drives Chromium over every page at
phone, tablet and desktop width in both colour schemes. It runs axe-core
against WCAG 2.1 AA and checks for horizontal overflow, which is the classic
small-screen bug and is invisible in a desktop screenshot.
It is not in npm test because it needs a browser; run it before shipping a
visual change. A sandboxed browser that does not trust the local TLS proxy
fails the Google Fonts request — console errors are reported but do not fail
the run, for that reason. Overflow and accessibility violations do.
CI splits the audit in two:
| Step | Scope | Blocking |
|---|---|---|
| Audit what ships | --omit=dev, high and above |
yes — expected to stay at zero |
| Report advisories in build and test tooling | everything, moderate and above | no |
The split exists because of one specific, temporary situation: every published
vitest up to 4.1.10 carries an advisory, and 4.1.11 — the fix — cannot be
installed under npm 10.9. Blocking on it would pin the job red indefinitely,
which teaches people to ignore a red audit. Surfacing it in the log keeps it
visible without that cost. The second step goes back to blocking as soon as
vitest 4.1.11 installs cleanly.
src/
data/site.ts nav, footer, wordmark, extension links
layouts/BaseLayout.astro head, theme bootstrap, header + footer
components/ Wordmark, SiteHeader, SiteFooter, MineralStrip
pages/index.astro the home page
pages/toddle-enhancement-extension.astro
styles/global.css @bundu/ui imports and nothing else
scripts/check-csp.mjs CSP hash verification
tests/ links, branding, security
See LICENSE if present; otherwise all rights reserved by Nyuchi Africa.