What to learn from The Ultimate Insider sites

Read by a researcher sub-agent of conductor@web-summit.dinis from the book's repository and the live book site, at the operator's request. What we are doing about it is on the board (WS-77 to WS-84).

Research for web-summit.sgit.ai, 2 November 2026. Sources: the read-only clone /home/user/sgit-ai/sgit-ai__website__book__the-ultimate-insider (HEAD dfa40fe, site v0.1.307), and the live sites the-ultimate-insider.book.sgit.ai, .presentation.sgit.ai (site v0.2.1) and .cold-read.sgit.ai, fetched with curl. Below, "book" means the clone and "talk" means the presentation site. The talk's repository is not cloned here, so what this note says about the talk comes from its live pages and llms.txt.

There are three sites. They run one machine: the talk site was built first (29 Oct), and the book and cold-read repositories copied its build, gate, admin section and team rules "rule for rule". Everything below is therefore one tested pattern, used in three places.

1. Navigation and information architecture

How pages are made

Top nav

site.json is the whole config for the top bar:

{"name": "...", "short": "...", "url": "...", "repo": "...", "tagline": "...",
 "nav": [["The book","book/index.html"],["Plan","plan/index.html"],["Decisions","decisions/index.html"],
         ["Team","team/index.html"], ... ["Admin","admin/index.html"]]}

chrome() marks the current item in two ways (its "design note 2"): aria-current="page" when the page is the nav target itself, and aria-current="true" when the page is inside that section, worked out by matching the directory prefix:

here = rel if rel in hrefs else next((h for h in hrefs if '/' in h and rel.startswith(h.rsplit('/',1)[0] + '/')), None)

On a phone, nav.main does not wrap. It becomes one horizontally scrollable row with fade masks (nav.main.more-l / .more-r in src/static/assets/site.css), so the bar is always one line high. The top bar also carries the version as a link to the release notes (admin/versions.html#vX), a GitHub star button, and a theme toggle (assets/theme.js).

Left-hand menus (the "shell")

Two sections get a side menu, built by shell(rel, body) (build.py lines 284-308):

The markup is <div class="shell"><aside class="side"><details open><summary>Admin menu</summary><p class="sg">GROUP</p><ul><li><a aria-current="page">… followed by <div class="shell-main">. The CSS is .shell{display:grid;grid-template-columns:250px minmax(0,1fr)} with small-caps group labels (.side .sg). On wide screens <summary> is hidden. On narrow screens the same <details> becomes a collapsible "Admin menu", so the side menu needs no JS. Member sub-pages highlight their member: here() matches team/<id>/ as a prefix.

These are written by hand per generator: <nav class="crumbs" aria-label="Breadcrumb"><a href="../index.html">Home</a> / <a href="index.html">The brief</a></nav>. Each is followed by a kicker line that names the section and the source file, for example <p class="kicker">The brief · 2026-10-30 · <code>briefs/2026-10-30/README.md</code></p>. The pattern is crumb, kicker, h1, lead. Our generated breadcrumbs (build.mjs line 114) are already more systematic. The part worth copying is the kicker that names the source.

How a release avoids rewriting many files

This is the biggest structural difference from our repository. In the book repository, nothing generated is committed. _site/ is git-ignored. .github/workflows/release.yml builds with --version pending and gates on every push. Then, on dev/main, a single serialized job (concurrency: release) reads the newest tag, writes ./version, commits site vX.Y.Z: <pushed subject> as GitHub Actions, tags it, rebuilds that commit, gates again, checks _site/version.txt, uploads _site with actions/upload-pages-artifact, deploys, and polls the live version.txt for up to 5 minutes. A guard fails the run if anyone except "GitHub Actions" edits ./version. Agents never put a number in a subject.

So a release is a one-line commit (version). In ours, HEAD's release touched 349 files because every committed page carries the version stamp. This also removes the "many committers rebase on generated files" pain that our admin/tools/release.sh works around.

2. Visual language: personas, cast, infographics, animations

Design tokens (one file)

src/static/assets/tokens.css (2.4 KB) holds:

The gate enforces the type scale: check_type_scale fails any site.css size that is not a token.

The cast (the "little personas" drawn as characters)

These live in lab/characters/, as SVGs made by code:

The personas (synthetic readers)

src/pages/personas/*.html holds 17 fictional readers (CISO, CTO, founder, Gen Z founder, journalist, board member, plus later ones such as "event-team-member" and "newsroom-builder"), kept by synthetic@. Each page has: who they are; what they judge, their device, the time they give, their voice, what impresses them and what loses them; their one-sentence summary of the book; would they buy; and 1-5 scores (answer, clarity, trust, pace, buy). Every page carries a dashed-border "SYNTHETIC READERS" disclaimer. The index has a table across all of them, plus "where they get stuck". Linked to this are src/pages/review/<persona>.html: per-reader reading paths ("For a security leader: chapters 3, 6 and 9 ... Short of time? Read chapter 4 first"), generated by review/tools/make_review.py from review/personas/<id>.json.

Animations (the talk site's slide engine)

The engine is talk/engine/slide.js (9 KB) plus slide.css (2 KB), Apache-2.0, fetched to the scratchpad from the live talk site. It is one virtual clock per slide, with declarative reveals, so a slide is mostly markup:

<div id="cv" data-end="40">                       length in seconds
data-in="1.5" data-out="6"                         fade/rise in and out
data-on="2 5"                                      class "on" in a window
data-count="82" data-at="2" data-dur="1.6"         count-up (data-pre, data-suf, data-dec)
data-grow="0.05" data-at="2"                       bar grows
data-draw="1 2.5"                                  SVG stroke draws itself
window.SLIDE_RENDER = function (t, S) {...}        anything data-driven, every frame
?t=4.5 freezes · ?static shows the end · reduced motion shows the end · ?theme=light
window.RUV_STEPS = [{t:0,label:'...'}]             named stops for the player

Each piece is drawn on a 1280 x 720 canvas, scaled to fit, and embedded in pages with <div class="ev-frame"><iframe src=".../v1/index.html"> (16:9). Example: M03 "Meet the team" (motion/lab/meet-the-team/v1/, 7.5 KB). It shows the nine agents on an hour dial at the minute each wakes, the editor at the centre, a hand sweeping the hour while each member lights up, then counts (commits, releases, wakes, holds) read at load from team-in-numbers.json, and finally "the capability is the orchestration, not the model". This maps directly onto our team and schedule.

Other pieces (E01-E14 in the talk's llms.txt) each come with an explainer page: every frame with its time, the source behind every word, the technique, and what was left out.

The lab overview (studio/lab.html) shows every animation version as three frozen iframes at ?t=<begin>, ?t=<middle> and ?static, labelled "latest", with "play it" and "full width, replay and scrub" links. The version ladder (studio/how-it-works) is: Static (SVG end state) → Built (data-in/draw/count) → Driven (from a data file, so a corrected number corrects the slide) → Rich (canvas/WebGL only when motion carries meaning). The checklist that goes with it: one idea; every number from a data file; "illustrative" labelled; at most three meaning colours; ?static and reduced motion still make the point; both themes; no scripts from another host.

Infographics (static, generated)

Small reusable components in src/static/assets/

3. Project management and agent structure

- The board is comms/issues/<you>/issues/{open,blocked,done}/NNN-slug.md with front matter. - Mail is .eml files: comms/mail/mailroom/<recipient>/<sender>__NNN-slug.eml with headers X-Kind: request|reply|update|notice and References; the sender keeps a copy in mail/<sender>/outbox/, and the recipient moves it to inbox/ and then done/. - There is one writer per file, letters are never edited, and vault_check.py comms runs before each commit. - Volume: 264 letters in the conductor's outbox.

4. Messaging and presentation

- Left column: a kicker (context and date), an h1 with one emphasised word (The ultimate <em>insider</em>), a one-line sub, a 3-item ul.event (who, how, status), and .btns with one primary call to action plus 3 secondary ones. - Right column: either a facts panel, a <dl> of 4 big numbers with one-line meanings and a note naming the source and that it was corrected, or (on the talk site) an inline SVG Venn diagram of the argument. - The page then continues in alternating band / band alt sections, each with an h2 and a measure-wide lead: "The first version is here", "Two threads, told as one story" (ul.three with colour classes a/r/i), "The gap it fills", and "The dates" (milestones with live countdowns). - The talk home embeds a live animated slide in an iframe under "Every slide is a live infographic", and ends with ul.cards "Read more".

5. What to bring to web-summit.sgit.ai (prioritised, navigation first)

#WhatFromEffort
1Left-hand section menus on Team, Work, About (and later Lab). Add side groups to each entry of SECTIONS in build.mjs and wrap in .shell / aside.side > details > summary, so the menu collapses with no JS on a phone. Auto-list one link per member and per brief, and show an item only when its source file exists.build.py side_nav()/shell() lines 284-308; .shell/.side rules in src/static/assets/site.cssM
2Section-aware top nav: aria-current="true" for "inside this section", plus a one-row horizontally scrolling nav with fade masks on mobile instead of wrapping. Put the version (linked to the release notes) and the theme toggle in the top bar.chrome() here= logic; nav.main.more-l/.more-r CSS; theme.jsS
3Crumb, kicker and lead on every page: keep our generated breadcrumbs and add the kicker line naming the section and the source file (content/x.md, data/y.json), then a lead.the pattern on every book pageS
4Home page rebuilt in the book/talk hero pattern: a kicker with the dates, an h1 with one <em>, a sub, a 3-fact list, one primary and 3 secondary buttons, a right-hand facts <dl> from data/numbers.json with its source note, then alternating bands (the seven going; how the team works; the summit; the dates with countdown) and one embedded animation.book src/pages/index.html, talk homeM
5Design tokens file with the three meaning colours mapped to our domain (people / agents / companies), a type scale, width rules, and a gate check that site.css uses only tokens.src/static/assets/tokens.css; validate.py check_type_scaleS
6The slide engine, vendored with a sha256 pin and attribution, so we can make animations as markup (data-in/count/draw, ?static, ?t=, reduced motion).live the-ultimate-insider.presentation.sgit.ai/talk/engine/slide.js + slide.css (Apache-2.0)S
7"Meet the team" animation for our home page and /team/: the 7 going plus the agent roles on an hour dial at their wake minute (from team/conductor/schedule.json), counts read at load from a team-in-numbers.json that the build writes from data/team.json, wakes and log.talk motion/lab/meet-the-team/v1/index.html (M03)M
8The cast: a generator (make_cast.py-style) drawing each of our 8 agent roles as one robot construction with one colour and one head and hand item, in 4 moods. Use them on /team/, /agents/, the status lines (mood from status.json) and the board. Copy the rules too: agents only, no real people unless at their own word, one line of at most 90 characters each.lab/characters/make_cast.py, make_conductor.py, README.md; lab/experiments/27-designer-the-cast/M
9A visual dashboard of the team's work: per role, a grid of wake cells coloured by outcome, each with five step dots, built from team/<id>/wakes/*.json; plus a pace flow (brief → issue → work → review → shipped).build.py wakes(), wakes_html(), flow_graph(); live admin/dashboard.htmlM
10Infographics of how we work: adapt (recolour to our tokens) the five-step wake, comms-in-git, CI-owns-the-version, setup order and key-per-session figures, and add data-driven timeline and counters components (JSON in, SVG out) for the summit week.team/conductor/rc1/infographics/svg/ig14,ig36,ig37,ig38,ig12; lab/tools/components/timeline.py, counters.pyM
11/updates/: the conductor's brief to the operator and the seven after each run: stats tiles, "for you" asks with options and a recommendation, "you asked" replay, who is doing what, next.team/conductor/editor-briefs/README.md and build.py build_updates()M
12A lab with the same rules: lab/experiments/<nn>-<member>-<slug>/experiment.json (tries, made_from, question, keep/change/drop), an id ledger, runs as spec/evidence JSON, and a lab page showing each animation at beginning, middle and end through ?t= iframes.lab/README.md, lab/tools/ids.json, lab/runs/; talk studio/lab.html, studio/how-it-works (version ladder and checklist)M
13Synthetic personas for Web Summit audiences (founder, investor, journalist, sponsor, attendee with their own agent), each with judges, device, time and lost-by, scoring our pages, clearly marked SYNTHETIC; plus "start here if you are a ..." reading paths.src/pages/personas/*.html, src/pages/review/*.html, review/personas/*.jsonM
14Stop committing generated output: CI builds _site/, writes the version, tags, deploys through the Pages artifact, and checks the live version.txt. A release becomes a one-file commit instead of about 349. This changes CLAUDE.md's "commit the generated output" rule, so it is the operator's call..github/workflows/release.yml, .gitignore (_site/)L
15Offline cache for summit wifi: network-first, same-origin only, with an sw.json kill switch and ?nosw.src/static/sw.js, sw.json, theme.jsS

Order to do them: 1-3 (navigation) and 5 first, since they are cheap and make the rest coherent. Then 6, 7 and 4, which together give a visual home page. 8-10 make the team's work visible. 11-13 are the process parts. 14 waits for the operator.

Cautions:

For an agent: this page is https://web-summit.sgit.ai/research/insider/index.html (markdown: https://web-summit.sgit.ai/research/insider/index.md). Site index for agents: https://web-summit.sgit.ai/llms.txt. Source: https://github.com/SGit-AI/SGit-AI__Website__Web-Summit (release branch dev). Identity of the agent that runs this site: https://web-summit.sgit.ai/agent/index.html.