Alex Rajcoomar portfolio

Colophon

How this site is built, and how it counts.

Every number on this site is measured from the published files rather than estimated. This page states each definition, so a reader can disagree with one.

The measurements

9 definitions
Pieces
An entry in content/pieces.json with a file behind it.
Edge cases
The three run transcripts are measured and held to the same record but are not entries, so they are not pieces and not in the corpus line.
Words
The text of the rendered document after its own scripts have run, with script, style and noscript removed and collapsed answers included, whether or not a reader has opened them.
Edge cases
The site's own chrome around a piece is not counted: the header, the return bar, the footer, the contents rail, the search dialog and the line that says what the piece was built from. A word is a whitespace-separated token containing at least one letter or digit. Question banks inside the interactive tools are held in code, so they are not counted anywhere.
Reading time
Derived, not counted: words divided by 230 words per minute, rounded, minimum one minute.
Edge cases
A page that renders under 1,200 words is treated as an instrument rather than a document and carries no reading time.
Figures
A top-level svg element in the rendered page, not nested inside another one, covering at least 6,000 square units, which excludes inline glyphs and icons.
Edge cases
Counted after render, so it includes charts a script draws on load; charts built purely from HTML and CSS are not counted, so the number is a floor rather than a ceiling.
Tables
A table element in the rendered document after its scripts have run, wherever it stands.
Checkpoint questions
A details element in the rendered document: a question or a worked answer folded away for the reader to try first.
Density
Figures plus tables per thousand words. Under 1.0 is Prose, 1.0 to 3.0 is Mixed, 3.0 and above is Dense.
Edge cases
Documents under 400 words carry no label, because the ratio is unstable at that length. It is a rough signal of what the page will feel like, not a quality measure: a dense page is not a better page.
Where the counts stop
The interactive tools read as 221 to 14208 words and are genuinely much larger than that: their question banks are held in code.
Edge cases
The 230 words per minute behind the reading time is a middle estimate for careful reading of technical prose; a skim is faster and a first pass through a figure-heavy section is slower. The instrument threshold is applied to what a page renders, not to what I would like it to be, and it is why the 8 interactive tools carry no reading time at any length.
Independent, coursework, personal
Independent means I chose the question, scoped it and finished it without a course asking for it. Coursework means it was built while taking the course, for the assessment that was coming. Personal means read and written for its own sake, with no claim on either.
Edge cases
The split is mine and I have made it conservatively: anything built alongside a course is filed as coursework even where the question was my own.

The design rules

Conventions
One declared rule per piece
Each research page states once, near the top, what its marks mean, then holds that rule to the end. The rule is derived from the subject, so no two pieces share one. The corpus figure obeys the same convention: one square is 500 words, solid is independent, an open outline is coursework.
Colour
Chart colours come from a validated categorical palette, checked for lightness band, chroma floor, colour-vision separation and contrast against both the light and the dark surface before use. Colour never carries meaning on its own: every figure's numbers are restated in a table or in the running text, and every mark that means something also differs in fill or shape.
Typography
Inter Variable, subset to the 267 characters the corpus actually uses and self-hosted at 80,976 bytes, with a metric-matched fallback face so the page does not reflow when the font lands. If the file fails to load, the site keeps working on the system stack. The build fails on any page character the subset lacks, so the number above is checked rather than believed.
A number you can open
A counted number on these pages is set with a dotted underline. Pointing at it or pressing it shows the definition it was counted under, the file it was measured from, the script that measured it and the record that holds it. The totals sit in the Tab order; a number inside a row opens with a pointer only, so a keyboard reader is not made to stop at every figure of every row, and what its dialog would say is the row's own link and the definition above. With scripts off the number stands as text and the definitions are the list above; nothing about the number itself depends on the script.
Surfaces
Warm paper in light, a near-black ground in dark, hairline rules, no rounded corners. The shell pages paint no drop shadow; the search panel sits on the browser's own backdrop. On a piece a shadow sits only under what floats over its text: the contents drawer on a phone, the reading-position pill, the section menu and the tips; a piece's own sheet keeps whatever it declared. One accent, blue, for the independent work on the sphere and for links. A second accent, violet, means one thing: a link one document's prose makes to another. It is the colour of the chords on both spheres, of the key entry that names them, of the link counts in the sphere's card and of the one count of recorded links under the home sphere, and it appears nowhere else; it is violet because no figure on this site has spent that hue. A panel sits one step above the ground behind a one-pixel edge. The one gradient on the site is the light around the sphere, which encodes nothing and is drawn outside the disc so it darkens no mark. Dark mode is a selected set of tokens rather than an inversion, and the manual toggle wins over the system setting in both directions.
The thumb index
A generated page with three or more parts carries tabs on its right edge, one for each section head in the order the page sets them, the way a bound reference is cut on its fore-edge so a reader can open it at a part. The build reads the tabs off the finished page, so each says only what its heading says, and it gives a heading an address where it had none. The tab for the part being read is pulled: inked, and held a few pixels proud of the others. At rest the index stands in the margin and covers no text; a tab draws out to show its heading only while it is pointed at or focused, and a screen wide enough to hold the headings shows them at rest. The tabs are plain links, so they work with scripts off. The Atlas and the controls page are instruments of their own and carry none.

How it is built

Technical

No framework, no runtime dependency, and nothing loaded from another origin except where the exceptions below say so. No tracking, no cookies, no analytics. 69 pieces served as static files by GitHub Pages. The 12 pages the build generates, this one included, share one stylesheet and one script; each piece carries its own styling inside itself, so a change to the site's look cannot reach into a piece and a broken piece cannot reach the site.

The listing pages are generated. Content lives in one file, content/pieces.json: every piece's title, description, tags, section and position. A script reads it and rewrites the listing pages, and a GitHub Action runs that script after every change. Any piece whose file changed is opened in a headless browser first and counted, which is where every number on this page comes from. Nothing here is typed in by hand, which is the only way the counts stay true.

Figures are static SVG generated at build time, so every chart renders with JavaScript disabled. JavaScript adds only enhancements: the theme toggle, the search palette, the library filters, the reveal-on-scroll, and the count of passages this browser has opened on the Atlas.

Accessibility: skip link, visible focus, headings in order, every figure labelled, colour never load-bearing on its own, and reduced motion respected. The generated pages print: sticky elements release, nothing stays hidden, and figures avoid breaking across pages. Each of those sentences is a row in the register, with the check that tests it and the last result, or the word asserted where nothing tests it yet.

6 of these pages began as Word documents and 18 as markdown notes. Each was converted once, by a script that lives outside this repository, and the HTML it produced is the record: it is what the build counts, what the Atlas harvests and what a reader saves. Nothing is converted at build time. The build does own the sentence at the foot of each converted piece that says so, and the footer under it, and it proves on every run that the text outside those two blocks is byte for byte what it was.

The content pass that began on 2 September 2026 was carried out by an AI assistant under a check that holds every numeral, citation, provenance label, anchor and result sentence of every piece to a record. Of the 69 pieces it could touch, 50 received copy edits, 8 received styling only, 3 were left untouched, and 8 were added in the pass. The ledger of every change is content/ledger.json.

The corpus as of this build: 69 pieces, 511,988 words, 206 figures, 856 tables and 359 checkpoint questions. 268,124 of those words were not assigned by anyone.

What this site claims about itself, and what checks it

The register

Every sentence the generated pages say about this site is a row in a register, beside the check that tests it, the last result with its denominator, and what happened when the claim was deliberately made false. This build: 50 claims, 50 held, 0 untested, 0 not yet measured, 0 asserted with no check, 0 failed. The register, and the same records drawn one glyph each, are on the controls page.

What the last pass got wrong, and what it left undone

15 notes

The content pass that began on 2026-09-02 kept its own account of its mistakes and its omissions in build/ledger-notes.json. A site that scores its own claims should also print what it knows is wrong with itself, so the notes are here, as written, rather than in a file a reader would have to know to open. The numbers in them are the pass's own, as it wrote them; this build reproduces the notes and does not recompute them.

Got wrong

  1. Two commits in the middle of the pass went in with a failing build twice, because a shell pipeline masked the build script's exit status; both were reset and redone from clean files before anything was built on them, and the build script was then called without a pipe for every later commit. The ledger's history is the redone one; the mistake is recorded here because the prompt asked for it.
  2. The invariance check was rewritten three times as the passes found cases it read wrongly (a sentence boundary moved by a dash, a callout title glued to its first sentence, a respelled strike). Each time the record was regenerated from the baseline commit, not from the working tree, so the record never absorbed an edit; but a reader should know the check that stands at the end is not the check that stood at the start.
  3. Clarity edits (step 10) were not made. With the check in place, every sentence that carries a numeral, a reference, a label or a verdict word is held word for word, which is most of the sentences an editor would touch in these pieces; the remaining candidates are the owner's own voice, and rewriting them without him is a judgement an autonomous pass should not make. The mechanical classes were done in full; the sentence-level pass waits for a session with him.
  4. The em-dash rules were applied by machine to 4,499 dashes. Sampled pages read correctly, and the invariance check proves no word moved, but nobody has read all 49 pieces end to end after the change; a comma where a colon would read better is possible on any page, and the full readable-text diff is in content/ledger.json for exactly that reason.
  5. Nine derived dark palettes were audited rendered, but only at one viewport, with one contrast rule, and without a person looking at them; a colour that passes the ratio can still be wrong for the page.
  6. Phase four: one interactive piece, the AFM 291 study system, does not count the same twice. Its file was unchanged and CI's own script counted 14,208 words where the record held 14,144; five further measurements by the same rule on the same file ranged from 14,107 to 14,183. The page's script assembles part of its text at load, and the definition of a word does not say that such a count is one sample. The record holds the last sample; the definition should say so, and the measurement should fix what the page's script draws from before it counts.

Left undone

  1. Sentence-level clarity edits: none, for the reason in section 0.
  2. The second-person sentences that carry a gap statement, a verification caveat ("supplied per your explicit instruction"), a scope decision or a legend were left in place in the seven AFM 291 chapter notes, the journal-entry reference and the reconciliation, because striking them would take a claim or a caveat with them and paraphrasing them is what the prompt ruled out; they are listed per piece above as left. Second-person sentences that address the reader (the study advice in The Delayed Test, the exam trainers) were never candidates.
  3. Tables whose header row uses paired group headings over unlabelled sub-columns (six in the Chapter 10 and Chapter 6 notes, two in Financial Assets I) still fail the audit's header rule; the fix is a colspan header structure, a restructure of the piece's own table markup, left for the owner.
  4. Dark palettes were not derived for three pieces on purpose: the revenue guide is dark by design, and the field manual and the workbook are print sheets.
  5. The transformers guide's heat-map cells keep white text on a translucent rust tint at 4.29:1 (one cell), because the tint is the datum.
  6. The study system's diagrams carry one generic accessible name; a truer name per diagram needs each caller of the drawing helper to pass one.
  7. The colophon's word definition changed to name the chrome the count leaves out, but no page was re-measured for that reason alone: the measurement was already excluding that chrome.
  8. The Atlas keeps its seed and placement rule; the four new pieces add 109 marks (1,552 to 1,661) by the same rule, so every existing mark moved with the lattice, which the redesign's honesty contract allows (positions are deterministic for a given corpus) and which a reader who bookmarked a mark's screen position would notice.
  9. A stable per-mark keying for the Atlas, so that adding a piece leaves the existing marks where they were, is a later pass. The key on the page and context/ARCHITECTURE.md said positions never change between builds; with four pieces added every mark moved, so both now say deterministic for a given corpus.

The exceptions

Counted, not remembered
  1. No piece loads a typeface from another origin: every face the site uses is self-hosted, subset to the characters each piece shows, and the build fails on any character a subset lacks.
  2. 14 pieces render under 1,200 words. They are counted in every total and not drawn in the corpus figure; together they hold 7,962 words.
  3. 3 run transcripts are measured, held to the same record as every piece, and kept in the offline copy, but not listed and not counted in the corpus line: crucible-run-0-transcript, crucible-run-b-transcript, crucible-run-c-transcript. Together they hold 166,808 words, so the site as a whole carries 678,796 measured words over 72 documents; the corpus line counts the 69 pieces.
  4. The 8 interactive tools stand on the shelf of the course or research that produced them and on the tools shelf. Every total counts each of them once.

The marks, the glyphs and the seal

93 elements in 10 files

The identity is drawn rather than typed: a monogram whose A and R stand on one vertical datum, in the header of every generated page, on the bar at the top of every standalone piece, and in the tab icon. In the header it holds two layers. At rest it draws the 4 strokes of the letters; point at it or reach it with a keyboard and it draws the 5 construction elements those letters were measured from, which are the circle the A sits in, the datum both letters stand on, and the ticks at the apex and the two feet. The other two marks stand where they mean something. The delta heads the tests of controls because its own sequence is that page's: evidence, a change, a verified datum, a ledger record. The polar datum heads the Atlas and stands beside the author's name because it is this site's own sphere abstracted, and the filled node at its north pole is the author's mark among the 1,755 on that sphere.

A stroke renders at its width times the size it is drawn, over the 64 unit grid the marks are authored on, so a line thinner than one device pixel cannot hold an edge. Each surface therefore draws only what it can hold and multiplies every stroke it keeps by one factor. The thinnest line any surface draws measures 1.01 device pixels. Nothing is resized by the stylesheet, because a mark scaled after the fact would be a mark whose arithmetic was done for another size.

The seal is the same discipline closed into a medallion: the monogram at its centre, a type band on a real arc, and a calibration band of 24 stations exactly 15 degrees apart, 20 of them fine ticks, 3 cardinal rules, and the north station left to the observer rather than drawn as a tick. The sheet intends divisions every 15 degrees for the polar datum and that file carries them every 45; this one carries them every 15. Of its 40 elements the site draws 39: the innermost ring is 0.5 units and could not hold an edge at any size this site uses, so it is dropped rather than drawn as a smear.

What each surface draws, from which mark, how much of it, and how thin its finest line ends up. The figure on a row has no file to draw a share of, so its count is what the whole statement's figures draw between them.
SurfaceMarkElements Stroke factorDrawn atThinnest line
The header, at restmonogram4 of 92.2241.24
The bar at the top of every piecemonogram4 of 92.4191.07
The tab iconmonogram3 of 93.3161.24
The tests of controlsdelta8 of 81.5441.03
The Atlasdatum14 of 141.8481.01
Beside the author's namedatum4 of 143261.22
The header, under a pointermonogram5 of 93.6241.01
The seal, above the factsseal39 of 401.51281.05
The figure on every statement rowfingerprint494 across 69 figures2.9561.01

Six further glyphs carry the state of a claim rather than the identity of the site. They are authored on a 24 unit grid at stroke 1.25, which renders at 1.04 and 1.25 device pixels at the two sizes this site draws them, so unlike the brand marks they need no factor at all. They head the columns of the whole statement, and they say what a column is before a reader has read a single number in it.

The six verification glyphs, what each one asserts, and what its authored stroke renders as.
GlyphWhat it assertsElements StrokeRenders at
SourceThree intake streams converge on one node. Nothing enters the record unlabelled.31.251.04 and 1.25
EvidenceA plotted observation carrying its own interval. The point is never shown without it.31.251.04 and 1.25
MethodInput, a declared transfer, output. The diagonal is the stated rule, not a decoration.41.251.04 and 1.25
TestedA specimen loaded between two platens until a failure plane opens. The claim was attacked, not asserted.31.251.04 and 1.25
LinkedOne passage cites another. The chord carries direction, so a reader can walk the claim back to its source.41.251.04 and 1.25
VerifiedTwo scales at different pitch, five against four. Exactly one pair of graduations coincides, and that coincidence is the reading.51.251.04 and 1.25

Every row of the whole statement also carries a figure of its own document, built from four values this build measured: the outer radius from the word count, one calibration ray per table, one node per figure, and one chord per recorded link between that document and another on this site. There is no random source anywhere in it, so the same document draws the same figure on every build, and a figure that changes means one of those four values changed.

A layer is drawn only where its value is, and one of them is thin on the ground: of the 69 figures, 53 carry rays and 22 carry nodes, 31 belong to a document with a recorded link, and 6 draw a chord. A chord joins two of the ring's nodes, so a document with fewer than two figures has nowhere to put one however many links it records. That is the arithmetic the figure was specified with, kept as specified rather than widened to make the layer show up more often.

How a document becomes a figure. W is its words, F its figures, T its tables and C its recorded links.
FeatureRule
Outer radiusR = 12 + 16t, t = (log10 W minus 3) / (log10 50000 minus 3)
Calibration raysone per table, at 360 / T
Node ring0.62 R
Figure nodesone per figure, at 360 / F
Chord strideround(0.382 F), plus one if that would be a diameter
Link chordsorigin round(i F / C), target origin plus stride

The marks arrived with a sheet of stated geometry. 16 of its values are readings this build takes from the files themselves, and 13 of those readings bear the sheet out. The rest do not, so the site draws the files: the sheet gives the monogram's bowl a radius the path does not describe, sets the delta's two ledger rules closer together than they sit, and asks the polar datum for finer angular divisions than it carries. Below, 15 dimensions of the monogram and the polar datum, each one read off a vertex or an arc boundary of the shipped path data rather than copied from the sheet. Check 34 recomputes what the pages draw on every build without asking the module that drew it, and check 35 walks these 15 readings a second time, with its own reader, and refuses the build if the two walks disagree.

Fifteen dimensions, the coordinates each is read from, and what kind of feature carries it.
CalloutMarkCoordinates Read fromCheck
56monogram32, 4 and 32, 60central datum, M32 4 V60path vertex
R28monogram32, 32 and 60, 32construction circle centre to its rightmost boundarycircle centre
APEX y6monogram32, 6A apex, M12 56 L32 6 L52 56path vertex
BASE y56monogram12, 56A left foot, M12 56 L32 6 L52 56path vertex
40monogram12, 56 and 52, 56A left foot to A right footpath vertex
24monogram20, 38 and 44, 38crossbar, M20 38 H44path vertex
18monogram42, 18 and 42, 36R bowl entry and exit, M32 18 H42 C51 18 51 35 42 36 H32path vertex
4monogram16, 56 and 20, 56left verification tick, M16 56 H20path vertex
dia 56datum4, 32 and 60, 32outer ring, r 28 about 32, 32arc r28
dia 44datum10, 32 and 54, 32second ring, r 22 about 32, 32arc r22
dia 32datum16, 32 and 48, 32third ring, r 16 about 32, 32arc r16
28datum32, 4 and 32, 32north pole centre to field centrearc r28
60datum32, 2 and 32, 62vertical longitude axis, M32 2 V62path vertex
dia 5datum34.5, 4north pole observer, r 2.5 about 32, 4arc r2.5
dia 3datum33.5, 32author datum, r 1.5 about 32, 32arc r1.5

On your phone

Offline

This site installs. In Safari on a phone, open the share sheet and choose Add to Home Screen: the site becomes an app icon, and every page you have visited already works with no connection. To hold all of it, every piece, the atlas, the tools and the data files, press the button below once while online. A saved copy survives a publish: the new worker carries every saved file across, then fetches only the files whose digest changed. The line under the buttons is read from the cache each time this page opens, not remembered.

The full copy is about 22 MB. One honest caveat: a phone can reclaim the space if the icon goes unused for many weeks; opening it once while online brings everything back.

↑↓ moveEnter openEsc close

Keyboard

/
Search every piece
⌘K
The same search
g h
Home
g r
Research
g c
Coursework
g t
Tools
g l
Library
g a
About
?
This list