customer-presentation/architecture boxes/design_handoff_architecture_diagram
Jonathan Hvid 547515061c product-pages: add deepdive subpage and platform assets
Adds a new standalone /deepdive page with its own platform.css/platform.js,
wires it into the dot-nav as an external entry, and updates the dot-nav
docblock to reflect the new seven-entry layout. Also drops in BUSINESS.md
and reference material under architecture boxes/ and examples/.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 09:28:23 +02:00
..
reference product-pages: add deepdive subpage and platform assets 2026-05-07 09:28:23 +02:00
README.md product-pages: add deepdive subpage and platform assets 2026-05-07 09:28:23 +02:00

Handoff: Fenja architecture diagram

Overview

A right-side architecture diagram for a section of the Fenja AI website. The left side of the section will hold explanatory prose (the developer adds this in their codebase). The right side is this stacked, three-layer diagram showing the Fenja system at a glance: Foundation → Tools → Agents.

The diagram is the visual anchor of the section. As the user reads down the left column, each paragraph cues the next layer of the diagram to enter — creating a guided "build" of the architecture in concert with the prose.


About the design files

The files in reference/ are a design reference — a working HTML/React prototype that shows the intended look, layout, and entry animation. They are not production code to copy verbatim.

  • reference/preview.html — open this in a browser to see the diagram rendered.
  • reference/approach-fenja.jsx — the React component (inline JSX, transpiled by Babel in the prototype). Use it as a structural and styling reference.
  • reference/colors_and_type.css — Fenja design tokens (CSS variables) and base type styles. Use these tokens — do not invent new ones.
  • reference/fonts/ — Manrope (sans) and Newsreader (serif) self-hosted TTFs. The diagram requires both families — Newsreader for italic descriptors, Manrope for everything else.

Recreate the design in your existing environment (Next.js, React, Vue, Astro, whatever the Fenja site uses), wired up to the site's real design tokens and motion primitives.

Fidelity

High-fidelity. Colors, typography, spacing, and corner radii are final. Recreate pixel-perfectly using the established Fenja design tokens.


What this diagram is

A vertically stacked diagram with three layers, top to bottom:

┌──────────────────────────────────────────────────────────┐
│ FOUNDATION                          Sovereign by design  │
│ ┌──────────────────────┐  ┌──────────────────────────┐   │
│ │ Language model       │  │ Knowledge   (taller)     │   │
│ │ italic descriptor    │  │ italic descriptor        │   │
│ │ mono · tag           │  │ mono · tag               │   │
│ │                      │  │ italic descriptor        │   │
│ │                      │  │ mono · tag               │   │
│ └──────────────────────┘  └──────────────────────────┘   │
└──────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────┐
│ TOOLS                                  How Fenja acts    │
│ ┌────┐ ┌────┐ ┌────┐ ┌────┐                              │
│ │ 4 boxes, equal width and height                        │
│ └────┘ └────┘ └────┘ └────┘                              │
└──────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────┐
│ AGENTS                                How Fenja scales   │
│ ┌────┐ ┌────┐ ┌────┐ ┌────┐                              │
│ │ 4 boxes, equal width and height                        │
│ └────┘ └────┘ └────┘ └────┘                              │
└──────────────────────────────────────────────────────────┘

Critical asymmetries

  • Foundation has 2 boxes (narrower row) — the irreducible base.
  • Tools and Agents each have 4 boxes (full row) — they extend the base.
  • Within Foundation, the Knowledge box is intentionally taller than Language model (5 content rows vs 2). Do not equalize them. The asymmetry is the point.
  • Within Tools and Agents, all 4 boxes are equal height (stretch). Do not let content drift the heights.

No connecting lines

The first pass has no lines between layers. Stacking + vertical order communicates "lower layers depend on what's above." If that's unclear after live testing with copy, a second pass can add subtle connectors.


Layer content (exact)

Use this content verbatim. Do not paraphrase.

Layer 1 — Foundation

  • Eyebrow (top-left of layer): Foundation (rendered uppercase via text-transform: uppercase)
  • Descriptor (top-right of layer, serif italic): Sovereign by design

Box 1 — Language model

  • Bold name: Language model
  • Italic role: State-of-the-art, open-source
  • Mono tag: On-prem

Box 2 — Knowledge (taller — 5 content rows, no min-height equalization)

  • Bold name: Knowledge
  • Italic: Organizational memory at every level
  • Mono: Organizational · Departmental · Personal
  • Italic: Facts, context, and how things get done
  • Mono: Wiki · Routines · Working memory

Layer 2 — Tools

  • Eyebrow: Tools
  • Descriptor: How Fenja acts
Bold name Italic role Mono tag
Document retrieval Find and cite RAG
Structured data Query and extract NL → SQL
System actions Read and write APIs · integrations
Custom tools Your specific work Defined by you

Layer 3 — Agents

  • Eyebrow: Agents
  • Descriptor: How Fenja scales
Bold name Italic role Mono tag
Supervisor Plan and dispatch Orchestration
Specialists Focused expertise Subagents
Skills Reusable capability Portable across specialists
Workflows Composed by you Governed end-to-end

Layout & sizing

The diagram is meant to occupy the right column of a two-column section (roughly 50% of the viewport width on desktop, ~600760px wide). It is fully fluid — it scales to its container.

Element Spec
Outer container padding: 56px 56px 64px on the standalone prototype. In the site, drop the outer padding and let the section's own grid drive margins.
Layer (group) background: var(--surface-container) · border-radius: 20px · padding: 24px 24px 28px
Layer-to-layer gap 20px (vertical flex gap)
Layer header flex row, baseline-aligned, eyebrow left + italic descriptor right, margin-bottom: 18px
Eyebrow label Manrope · 11px · weight 600 · letter-spacing: 0.14em · uppercase · color: var(--on-surface-variant)
Italic descriptor Newsreader italic · 14px · color: var(--on-surface-muted)
Card grid display: grid · gap: 14px · 2 cols (Foundation) or 4 cols (Tools, Agents)
Card grid alignment Foundation: align-items: start (preserves Knowledge's taller height) · Tools & Agents: align-items: stretch (equal heights within row)
Card background: var(--surface-container-lowest) · border-radius: 12px · padding: 18px 20px · column flex · gap: 6px · min-height: 76px · box-shadow: 0 1px 0 rgba(56,56,49,0.04), 0 8px 20px -16px rgba(56,56,49,0.18)
Card name Manrope · 15px · weight 600 · letter-spacing: -0.005em · color: var(--on-surface)
Italic row Newsreader italic · 13px · line-height: 1.35 · color: var(--on-surface-variant)
Mono row Mono stack · 10.5px · letter-spacing: 0.04em · line-height: 1.4 · color: var(--on-surface-muted)

No borders anywhere. Containment is expressed entirely through the tonal step from --surface-container (group) to --surface-container-lowest (card). The card's tiny ambient shadow is the only depth cue.


Design tokens (use existing Fenja tokens; do not invent)

These come from colors_and_type.css. Map to whatever variable system the codebase uses.

--surface                       #faf6ee   /* page canvas */
--surface-container             #efeadc   /* group / layer background */
--surface-container-lowest      #fffcf7   /* card background */
--on-surface                    #383831   /* card name, primary text */
--on-surface-variant            #5f5e5e   /* italic role, eyebrow */
--on-surface-muted              #8a887f   /* mono tag, descriptor */

--font-sans   Manrope, Inter, system-ui  (weights 400, 500, 600 used)
--font-serif  Newsreader, Source Serif Pro, Georgia  (italic, 400)
--font-mono   JetBrains Mono, IBM Plex Mono, ui-monospace

--radius-md   12px   (cards)
--radius-lg   20px   (groups)

Entry animation

The user requested: "each element jumps in together with text I'll add in Claude Code."

Intent

As the section scrolls into view, the diagram builds layer-by-layer in step with the prose on the left. Each paragraph the reader passes "summons" the corresponding layer.

Use whatever scroll-trigger primitive the site already uses (Framer Motion whileInView, GSAP ScrollTrigger, IntersectionObserver, etc.). Do not introduce a new motion library just for this.

Animation values — match Fenja system motion

The Fenja design system has one easing and page entrances are fade + 4px translate-up, never scale. Use those.

duration:  240ms       (use --duration-med)
easing:    cubic-bezier(0.2, 0.0, 0, 1)   (use --ease-standard)
from:      opacity: 0; transform: translateY(8px)
to:        opacity: 1; transform: translateY(0)

Note the design system says 4px translate-up, but for cards inside a build sequence 8px reads better. Stay within 410px.

Choreography

Three trigger points, each tied to a paragraph on the left:

Trigger Reveals Stagger
Paragraph 1 in view Foundation layer (group + 2 cards) Layer fades, then cards stagger 60ms each
Paragraph 2 in view Tools layer (group + 4 cards) Same — group, then cards 60ms apart
Paragraph 3 in view Agents layer (group + 4 cards) Same

Within a single layer, the group container (with eyebrow + descriptor) appears first, then its cards stagger in left-to-right.

Reduced motion

Honor prefers-reduced-motion: reduce — fade in over 120ms, no translate.

What to wire on the developer side

The component should expose a controllable visibility state per layer, e.g.:

<FenjaArchitecture
  visibleLayers={{ foundation: true, tools: paragraph2InView, agents: paragraph3InView }}
/>

…or accept three IntersectionObserver refs (one per paragraph) and drive its own visibility internally. Either is fine — pick whichever suits the codebase's conventions.


Behavior when the section is statically rendered (no JS)

If the page renders without JS (SSR, RSS preview, screenshot tool, print), all three layers must be visible. Animation is a progressive enhancement — the static state is the final state, and the animation should ramp from that final state's opposite, not block on JS to render content. (Translation: render at full opacity by default and let the animation library set initial opacity:0 only when it's ready.)


State

No app state. Pure presentational component. All content is static; nothing is fetched.

If the prose paragraphs and the diagram need to coordinate, expose a single currentLayer: 'foundation' | 'tools' | 'agents' | null prop or use shared IntersectionObserver hooks — implementer's choice.


Assets

None. The diagram is text-on-paper — no icons, no images, no SVG illustrations.


Files in this bundle

design_handoff_architecture_diagram/
├── README.md                        ← you are here
└── reference/
    ├── preview.html                 ← open this to see the diagram render
    ├── approach-fenja.jsx           ← the React reference component
    ├── colors_and_type.css          ← Fenja design tokens (variables + base styles)
    └── fonts/                       ← Manrope + Newsreader TTFs (self-hosted)

Implementation checklist

  • Component scaffolded in the codebase's preferred framework (React, Vue, etc.)
  • All three layers render with the exact copy above
  • Foundation: Knowledge box visibly taller than Language model (do not equalize)
  • Tools: 4 cards flush-equal in height (align-items: stretch)
  • Agents: 4 cards flush-equal in height (align-items: stretch)
  • Eyebrow + italic descriptor in the header of every layer
  • Mono tags use the site's monospace stack (do not substitute regular text)
  • Bullet separator · (interpunct U+00B7) used in mono tags — not or -
  • No borders anywhere (containment = tonal step only)
  • No connecting lines between layers
  • No icons inside boxes
  • Entry animation: fade + 8px translate-up, 240ms, cubic-bezier(0.2, 0, 0, 1)
  • Per-layer trigger tied to corresponding left-column paragraph entering viewport
  • Cards within a layer stagger 60ms left-to-right
  • prefers-reduced-motion: reduce honored
  • Static render is fully visible without JS