The /campaign route (campaign.astro, 1790 lines) — the campaign’s
status / evidence hub. It is an investigation/status-tracking page with three
parts: (1) a long, documented list of withheld unpublished Aajonus material
(books, consult tapes, lectures, legal docs, …) with the evidence each exists; (2) a
condensed scam-coaching recap (Phoenix’s coaching vs. Aajonus’ teachings) that
reuses the shared comparison chart; and (3) a campaign-goals status board driven
by an in-file typed data model. It is composition-heavy — almost all substance is
delivered through already-documented components (DataItem, Quote,
CampaignLink, BigButton, CoachingComparisonChart, Contact) plus astro:assets
Image and one hard-coded <video>. A single-file node — no Children section. The
documentation value is the page’s shape, its in-file data model + helpers, and its
composition, not its editorial prose; the campaignGoals/DataItem text values are
not transcribed here. This is the smallest of the four giant pages but carries
the most in-frontmatter logic and the largest dead-import set of any page node.
:1-153)export const prerender = true (campaign.astro:72) — static page.Image from astro:assets (:3); MainLayout (:5);
and 10 components from ../components/* — PersonProfile (:7),
PersonProfiles (:8), Quote (:9), External (:10), CampaignLink (:11),
BigButton (:12), Table (:13), DataItem (:14), CoachingComparisonChart
(:15), Contact (:18). All 10 are documented in src/components/DOCS.md —
see Components used + Dependencies; not re-summarized here. Only 6 are
rendered; PersonProfile, PersonProfiles, External, Table are imported but
never used (dead — see Invariants).:16): pageMeta from ../data/pageMeta → consumed as
pageMeta.campaign in the layout call. A Phase 5 file; only the import is noted here.../assets/* media imports (:20-69): 40 image imports + 2 .mp4
imports (phoenix_overcooking :54, phoenix_scream :55). Names not
transcribed. Only 9 are live; 33 are dead (31 images + the 2 .mp4s) — by far
the heaviest dead set of any page node (see Invariants). Live: jim (:20),
aajonus (:21), paul (:28), community_submit_consults (:31),
jim_hoarding_community_consults (:32), jim_email_hoarding_consults (:33),
consult_recordings_collection_announcement (:34),
consult_recordings_collection_comments (:35), and paul_nego_04 (:62, the only
surviving member of the paul_nego_* set).:74-152)This is the page’s main documentation-worthy artifact — richer than the other giants.
CampaignGoal interface (:74-81) — copied verbatim:
interface CampaignGoal {
title: string;
description: string;
progressPercent: number;
importance: 1 | 2 | 3 | 4 | 5;
dueDate?: string;
statusDetail: string;
}
campaignGoalImportanceLabels (:83-89, as const) — the 1→5 = Low → Moderate → High → Very High → Critical label map.campaignGoals: CampaignGoal[] (:91-128) — 4 entries. Document the
schema (the interface above) + count; the goal prose / statusDetail values are
not transcribed. importance (1–5) drives both the text label and the status-dot
color/glow (below). Of the optional fields, none of the 4 entries set dueDate,
so the dueDate block (:1328) never renders at HEAD.getCampaignGoalImportanceLabel (:130-132) — returns
campaignGoalImportanceLabels[level].getCampaignGoalImportanceDotStyle (:134-152) — returns an inline CSS
custom-property string — `--goal-importance-dot:${colors[level]}; --goal-importance-glow:${glows[level]};` — from two hard-coded as const maps
keyed by importance (colors :135-141, glows :143-149; e.g. 5 → #f2353f / rgba(242,53,63,0.62)). This is build-time string generation, not
client JS — the returned string is injected into the style= attribute of each
goal’s dot at :1322.Everything renders inside one <MainLayout> → <section> → <div> (:157-160). The
page <h1> is “Save Aajonus’ legacy” (:161), followed by a plain table-of-contents
(.table-of-contents--plain, :165-171) linking the three <h2> anchors. One line per
top-level block:
#unpublished-data (<h2> :175) — “The unpublished data”: the long
DataItem list of withheld items (intro :179-190), each <DataItem> holding
prose + <Quote> evidence + occasional <Image> screenshots/<video>. Closes with a
“Summary of the gatekept data” <ul> (:1216-1229) and a <CampaignLink text="Sign the petition on change.org" /> (:1239).#official-coaching (<h2> :1244) — “The scam coaching”: a short recap
(:1248-1259) then <CoachingComparisonChart /> (:1261, the chart reused by the
scam pages), a verdict line (:1263), and a <BigButton href="/official-coaching-scam" targetBlank> (:1267).#campaign-goals-status (<h2> :1277) — “Campaign goals status”: the goals
board. A <div class="campaign-goals-list"> renders
campaignGoals.map((goal, index) => …) at :1286 — one <article class="campaign-goal"> per entry with an index, a progress block (goal.progressPercent
→ style={width: …%} at :1304), title/description, an importance row calling both
helpers (getCampaignGoalImportanceLabel(goal.importance) :1315,
getCampaignGoalImportanceDotStyle(goal.importance) :1322), a conditional dueDate
block (:1328, never rendered — no entry sets dueDate), and a statusDetail block.
The dot also gets is-bright/is-critical classes via class:list from
goal.importance >= 4 / === 5 (:1317-1321). Closes with a second <CampaignLink>
(:1345), <Contact /> (:1348), and a <BigButton href="/"> “return to the main
page” (:1350).Counts are literal <Tag occurrences in source at e32f3ef (live unless noted);
reconcile against the importer table in src/components/DOCS.md. Link, don’t
re-derive — each is documented there.
| Component | Count | Prop(s) this page passes |
|---|---|---|
DataItem | 19 live (+1 commented :1059) | title, importance ({1..5}), likelihood ({n}), and location on only 2 of the 19 (:199, :552); + slotted body. location is received-but-never-rendered by the component (Phase 3) — see Open questions. |
Quote | 26 live (+4 commented: :520,:525,:783,:1069) | photo (.src of aajonus/jim/paul), name, content or slotted <p>s, source, date (new Date(...)), url; some dialogue turns use followUp={true} |
CampaignLink | 2 | text="Sign the petition on change.org" (:1239, :1345) |
BigButton | 2 | href (/official-coaching-scam :1267 with targetBlank={true}; / :1350) |
CoachingComparisonChart | 1 | none (:1261) |
Contact | 1 | none (:1348) |
PersonProfile | 0 | imported (:7) but never rendered — dead import |
PersonProfiles | 0 | imported (:8) but never rendered — dead import |
External | 0 | imported (:10) but never rendered — dead import |
Table | 0 | imported (:13) but never rendered — dead import (also a “dead component”: renders an empty <div> per Phase 3) |
Image (astro:assets) | 6 | src (imported ImageMetadata), alt, width={500}, quality={75} |
So 6 of the 10 imported components are live, 4 are dead. (Note: DataItem’s
brief estimate of ×20 is one high — there are 19 live opens + 1 commented; the
location brief estimate of “every DataItem” is also off — only 2 pass it.)
../layouts/MainLayout.astro — rendered as
<MainLayout {...pageMeta.campaign} wrapContent={false}> (:157). Note the one
non-default boolean wrapContent={false} (suppresses the layout content wrapper);
unlike index it does not also set showHeader={false}. See src/layouts/DOCS.md
for the MainLayout → Layout chain and what the prop does; ../data/pageMeta is a
Phase 5 file (import only, consumed as pageMeta.campaign).src/components/DOCS.md): the 10 imported above — 6 live (DataItem
is the structural workhorse, ×19; Quote ×26; CampaignLink, BigButton,
CoachingComparisonChart, Contact) and 4 imported-but-unused
(PersonProfile, PersonProfiles, External, Table).astro:assets: the Image component (×6) + the imported ImageMetadata assets
under src/assets/** (9 live of 40 image imports) and the 2 bundled .mp4 imports
(both dead — see Invariants).<video> (:706-708): one on-page <video controls> whose <source>
points at the public/ path /media/video/paul_aajonus_hard_drives.mp4 with
poster /media/video/posters/paul_aajonus_hard_drives.jpg — not a bundled import
(which is why the two .mp4 imports are dead).pnpm check at e32f3ef (not
assumed). pnpm check is clean overall: 0 errors, 0 warnings, 108 hints. For
campaign.astro the flagged set is 37 declarations (all ts(6133) “declared but
never read”) — the heaviest of all four giants (phoenix-be 16, index 8,
iris-reading 0). Breakdown:
PersonProfile (:7), PersonProfiles (:8),
External (:10), Table (:13)..mp4 imports: phoenix_overcooking (:54), phoenix_scream
(:55) — the page’s only on-page <video> (:706) sources a public/ path
instead (above), so the bundled video imports are dead.phoenix :22, avyanna :23,
chris :24, kimberley :25, jeff :26, sam :27); 14 evidence images
(:39-52: avyanna_lie_frozen, chris_lie_frozen, the five sam_*,
jeff_slay_transformation, jeff_slay_now, fat_cattle_kingdom,
phoenix_crowdfunding, jim_misquote, aajonus_instruction_fb_group,
detox_is_not_disease_video_cover); the paul_nego_* near-miss — 9 of the 10
imports (paul_nego_09…01 incl. 01b, :57-66) are dead, only paul_nego_04
(:62) is rendered (:504), reading like a WIP negotiations gallery where one
screenshot survived; plus paul_email (:67) and paul_working_with_phoenix
(:69)..mp4) + 31 (images) = 37 flagged.<script>, no client:* directive, no Vue
island, no getImage(), no import.meta.env, and the page does not import
RevealToggles — all confirmed by search (combined count of those patterns: 0). Any
DataItem collapse/reveal behavior is the component’s, not the page’s. The only
“dynamic” bit is the build-time getCampaignGoalImportanceDotStyle string
generation (:134-152) injected into each goal dot’s style= at :1322 — server
rendered, no runtime JS.location= is passed on only 2 of 19 live DataItems (:199, :552, both
"Aajonus' hard drive") — and DataItem does not render location (Phase 3,
src/components/DOCS.md), so even those two have no visible effect. (Inconsistent with
the brief’s “every DataItem”.)<style> block (:1362-1790, ~429 lines). A single scoped <style>
(no is:global, no :global(...) selectors) — it styles h1/h2, the plain ToC,
and the whole .campaign-goal* board, including the --goal-importance-dot /
--goal-importance-glow custom props consumed from the inline style strings
(:1651-1664), a @keyframes campaignGoalCriticalPulse for importance === 5 dots
(:1681-1690), a @media (max-width: 620px) responsive layout, and a @media (prefers-reduced-motion: reduce) guard that disables the critical-dot pulse
(:1785-1789).aajonus.net/...#:~:text= quote deep-links inside <Quote url=…> (not enumerated);
youtube.com/watch?v=… source links (:713, :735);
facebook.com/groups/primaldietersunite (:647);
https://primal-diet.net/official-reply (:499); the public/ video +
poster paths (:706-707). The change.org petition link is supplied by the
<CampaignLink> component, not inline here..mp4s, the 31 dead
images including the 9-of-10 paul_nego_* set) WIP or abandoned? The structure —
whole evidence/screenshot sets imported but unrendered, and a negotiations gallery
where only paul_nego_04 survives — reads like staged-then-cut content, but intent is
unclear from code — needs author input.location= to DataItem (:199, :552) intentional, given the
component never renders it and only 2 of 19 items pass it? Unclear from code.CampaignGoal.dueDate field is defined and rendered conditionally (:1328) but
no entry sets it — placeholder for future use or vestigial? Unclear from code.