One WebGL canvas. Five synchronized audit theatres. Two languages, one version of the truth.
A permanent engineering signature of YASLOGIST · yaslogist.com
The System · Capabilities · Architecture · Blueprint · Execution · Ignition · Deep Access · Status · YASLOGIST
Note
Abstract. Supply-chain margin does not leak in one place — it leaks in the gap between four systems that each believe a different number. LOGISDATA is an executive audit instrument that puts those four disagreements on one canvas: freight billing versus telematics, consumer demand versus order amplification, planned routes versus GPS reality, and WMS master data versus what is physically on the shelf. It ships as a five-stage, scroll-choreographed control room with synchronized 3D operational models, full English/Arabic parity, and a hardened production posture.
Margin leakage is not a reporting problem — it is a reconciliation problem. Each theatre of LOGISDATA stages one disagreement between systems of record, renders it twice (semantically in HTML, spatially in WebGL), and derives both surfaces from a single typed model so the numbers cannot drift apart.
| Dimension | Value | Engineering consequence |
|---|---|---|
| Audit theatres | 5 (hidden cost → invoice → bullwhip → routes → warehouse) | one narrative spine, one scroll container, one camera rig |
| WebGL contexts | 1 | all scenes stay mounted; transitions are transforms, not remounts |
| Locales | en / ar with native RTL |
layout direction, numerals and currency invert at runtime |
| Initial JS on first paint | zero Three.js | the engine is code-split and loaded only once the device is known to support WebGL |
| Runtime data fetches | 0 on the critical path | the domain model is typed, static and tree-shaken |
| Database | optional | the presentation is fully functional with no DATABASE_URL |
| Source surface | 53 TypeScript/TSX modules (7,087 lines) + 3,156 lines of tokenized CSS | measured from src/ on 2026-10-10 |
| Automated coverage | 213 passing unit tests + 60 Playwright checks | unit suite re-run 2026-10-10: 213/213; the browser suite runs in CI |
| Initial shell payload | 202,616 B gzip | measured against the 205,000 B production budget |
| Known vulnerabilities | 0 (npm audit) |
pinned toolchain plus an esbuild override |
Every row below is implemented, exercised by the test suite, and visible in the running experience. Nothing on this matrix is aspirational.
| # | Capability | Surface | Implementation | State |
|---|---|---|---|---|
| Experience | ||||
| 01 | Five-stage audit narrative | sections/* | Full-viewport sections bound to a shared section index | ✅ Shipped |
| 02 | Synchronized 3D models | three/* | Supply network, laser audit gate, demand matrix, route terrain, warehouse grid | ✅ Shipped |
| 03 | Cinematic camera choreography | IndustrialScene | Dual-target interpolation with frame-rate-independent damping | ✅ Shipped |
| 04 | Deferred engine boot | PresentationShell | next/dynamic + ssr:false after the WebGL capability probe; no cover-screen CTA | ✅ Shipped |
| 05 | Animated metric counters | MetricCounter | IntersectionObserver (0.35) → rAF cubic ease-out over 1250 ms | ✅ Shipped |
| Localization | ||||
| 06 | English / Arabic parity | lib/data.ts | Every copy node is LocalizedText; the compiler enforces coverage | ✅ Shipped |
| 07 | Native RTL inversion | Presentation | documentElement.dir + lang flipped on toggle; CSS logical properties | ✅ Shipped |
| 08 | Locale-correct numerals | lib/i18n.ts | Intl.NumberFormat with ar-EG digits and compact USD | ✅ Shipped |
| 09 | Arabic display typography | @fontsource-variable/cairo | Self-hosted variable font — no third-party font request | ✅ Shipped |
| Accessibility | ||||
| 10 | Keyboard navigation | Presentation | Arrows · Page Up/Down · Home · End, with modifier and text-field guards | ✅ Shipped |
| 11 | Semantic analytics | sections/* | Real <table> markup, aria-labelledby, aria-current="step" | ✅ Shipped |
| 12 | Motion reduction | useReducedMotion | Programmatic scrolling drops to behavior: "auto" | ✅ Shipped |
| 13 | Visible focus states | globals.css | :focus-visible outline on every interactive control | ✅ Shipped |
| Performance | ||||
| 14 | Background-tab suspension | Presentation | visibilitychange → frameloop="never": no GPU work when hidden | ✅ Shipped |
| 15 | Tiered fill cost | Canvas | Device-derived DPR clamp, adaptive regression while scrolling, alpha:false, powerPreference:"high-performance" | ✅ Shipped |
| 16 | Allocation-free render loop | IndustrialScene | Module-level vectors + refs; no per-frame object churn | ✅ Shipped |
| 17 | React-free label updates | FocusFadeLabel | Opacity written straight to the DOM node inside useFrame | ✅ Shipped |
| Resilience & platform | ||||
| 18 | Recoverable engine failure | ExperienceBoundary | Class boundary with a retry action and telemetry-friendly logging | ✅ Shipped |
| 19 | Database-optional runtime | db/index.ts | Pool constructed lazily; importing the module never throws | ✅ Shipped |
| 20 | Bounded connection pool | db/index.ts | max clamped to 1–50, 5 s connect timeout, 30 s idle reap | ✅ Shipped |
| 21 | Honest health contract | api/health | 200 live · 503 only when a configured database is unreachable | ✅ Shipped |
| 22 | Production security headers | next.config.ts | CSP plus eight defense headers, including HSTS preload in production builds | ✅ Shipped |
| 23 | Animated social card | tools/og-image | Reproducible 1200×630 GIF + PNG fallback from design tokens | ✅ Shipped |
| 24 | Scenario-consistent evidence | lib/export.ts | CSV rows and executive JSON summaries derive from the selected scenario; JSON includes illustrative provenance | ✅ Shipped |
| 25 | Honest simulation state | LiveTelemetryFeed | Bilingual fixture-simulation disclosure; no interval or audio work while closed | ✅ Shipped |
| 26 | Native modal lifecycle | useNativeDialog | Platform modality and Escape handling, deterministic initial focus, invoker-focus restoration | ✅ Shipped |
| 27 | Calculator provenance | RecoveryCalculator / HandoutView | Bilingual fixed-assumption disclosure; illustrative, not a forecast | ✅ Shipped |
| 28 | Context-safe global shortcuts | lib/keyboard.ts | Section keys yield to focused controls, IME composition, handled events, modifiers, and open modals | ✅ Shipped |
| 29 | Accessible operating modes | ScenarioSwitcher / LiveTelemetryFeed | Roving radio focus, arrow/Home/End selection, localized pressed filters, and truthful running/paused status | ✅ Shipped |
The application is deliberately split into three cost tiers. The 3D tier is requested only after the client capability probe confirms that WebGL is available; there is no cover-screen CTA or intent gate.
| Tier | Boundary | Payload | Trigger |
|---|---|---|---|
| T0 — Shell | page.tsx → PresentationShell → EngineLoader |
Static HTML, CSS, React shell, small icon subset | first paint |
| T1 — Engine | dynamic(() => import("@/components/Presentation"), { ssr: false }) |
React Three Fiber, drei, Three.js, Framer Motion, all five scenes | hydration, once the device probe confirms a WebGL context |
| T2 — Data plane | getDb() inside api/health |
pg pool, Drizzle |
a readiness request and a configured DATABASE_URL |
Important
ssr: false is a correctness requirement, not an optimization. The scene graph reads window, document.visibilityState and localStorage during initialization; server-rendering it would produce a hydration mismatch and a flash of unthemed content.
Five operational models share one <Canvas>, one camera and one scroll container. Section transitions are therefore pure transform interpolations — no WebGL context is created or destroyed while the user navigates.
ScrollControls(pages = 5, damping = 0.12)
│
├─ ScrollBridge ───────────► exposes scroll.el to React for programmatic nav
├─ DeckOverlay portal ─────► 5 semantic <section> elements in the native scroller
│
└─ IndustrialScene ────────► per-frame rig (useFrame)
├─ pagePosition offset × (SECTION_COUNT − 1)
├─ camera.position lerp(CAMERA_TARGETS[i], [i+1]) → damp(1 - e^(-4.6·Δt))
├─ camera.lookAt lerp(LOOK_TARGETS[i], [i+1]) → damp(1 - e^(-5.2·Δt))
└─ group[i] scale 0.56 + focus·0.44 · depth (i − pagePosition)·2.2
The focus curve is the single source of truth for "how present is section i right now".
pagePosition = clamp(offset, 0, 1) × (SECTION_COUNT − 1)
focus(offset, i) = clamp(1 − |pagePosition − i| / 1.08, 0, 1)IndustrialScene applies it to mesh scale; FocusFadeLabel applies the identical curve to label opacity through lib/sceneFocus.ts. Both consumers therefore stay aligned by construction—the regression tests lock the exact section peaks at offsets 0, 0.25, 0.5, 0.75, and 1.
The plot above is computed from the same constants as the runtime — FOCUS_SPREAD = 1.08, BASE_SCALE = 0.56, FOCUS_SCALE = 0.44, label hide threshold 0.05 — and animated as the scroll position dwells on each section in turn. Labels fade exactly as applyLabelFocus fades them.
| Path | Responsibility | Contract |
|---|---|---|
src/app/layout.tsx |
Document shell, font loading, Open Graph / Twitter metadata | Animated GIF card first, static PNG as fallback |
src/app/page.tsx |
Server entry | Renders the shell only — no client state |
src/components/PresentationShell.tsx |
Capability probe ↔ engine handoff, ExperienceBoundary |
A WebGL failure degrades to a retryable panel, never a white screen |
src/components/Presentation.tsx |
Navigation, preferences, keyboard map, visibility gating | Owns all cross-cutting UI state |
src/components/three/IndustrialScene.tsx |
Camera rig, per-section transforms, section change events | Zero allocations inside useFrame |
src/components/three/* |
Five scene models + FocusFadeLabel |
Read-only consumers of lib/data.ts |
src/components/sections/* |
Accessible HTML analytics for each theatre | Semantic tables; never canvas-only content |
src/lib/data.ts |
The audit model: 3 metrics, 5 freight rows, 5 demand tiers, 5 route regions, 4 warehouse specs, 42 bins, 8 nodes, 10 edges | Every string is { en, ar } |
src/lib/i18n.ts |
text / number / integer / currency via Intl |
en-US and ar-EG numeral systems |
src/lib/export.ts |
Scenario-aware CSV and executive JSON evidence packages | Exported rows and summaries match the active scenario; JSON carries illustrative provenance |
src/lib/useNativeDialog.ts |
Shared native modal lifecycle | Initial focus, Escape/platform close, and invoker-focus restoration |
src/lib/types.ts |
Domain types | LocalizedText makes an untranslated string a compile error |
src/db/index.ts |
Lazy, bounded PostgreSQL pool | Never constructed at import time |
src/app/api/health/route.ts |
Liveness + optional readiness | Honest status codes — see Operations |
tools/og-image/ |
Deterministic social-card renderer | Regenerates the animated GIF from design tokens |
flowchart LR
classDef edge fill:#0b1c2a,stroke:#4de1c1,stroke-width:1px,color:#edf7fb
classDef srv fill:#10283a,stroke:#7dd3fc,stroke-width:1px,color:#edf7fb
classDef cli fill:#0b1c2a,stroke:#f59e0b,stroke-width:1px,color:#edf7fb
classDef opt fill:#0b1c2a,stroke:#6e8795,stroke-width:1px,stroke-dasharray:4 3,color:#a8becb
visitor["Visitor<br/>desktop · tablet · mobile"]:::edge
subgraph server["Next.js App Router — server"]
direction TB
layout["layout.tsx<br/>metadata · OG · fonts"]:::srv
page["page.tsx<br/>server component"]:::srv
health["api/health<br/>nodejs · force-dynamic"]:::srv
end
subgraph client["Client experience — use client"]
direction TB
shell["PresentationShell<br/>capability probe + error boundary"]:::cli
loader["EngineLoader<br/>static, engine-free"]:::cli
pres["Presentation<br/>nav · prefs · keyboard"]:::cli
canvas["Canvas · ScrollControls<br/>single WebGL context"]:::cli
rig["IndustrialScene<br/>camera rig + focus curve"]:::cli
scenes["5 scene groups<br/>network · scanner · matrix · terrain · grid"]:::cli
html["5 HTML sections<br/>semantic tables + charts"]:::cli
end
subgraph domain["Domain layer — pure TypeScript"]
direction TB
data["lib/data.ts<br/>typed audit model"]:::srv
i18n["lib/i18n.ts<br/>Intl EN/AR formatters"]:::srv
focus["lib/sceneFocus.ts<br/>shared focus curve"]:::srv
end
subgraph plane["Optional data plane"]
direction TB
db["db/index.ts<br/>lazy bounded pool"]:::opt
pg[("PostgreSQL<br/>Drizzle ORM")]:::opt
end
visitor --> layout --> page --> shell
shell --> loader
shell -. "dynamic import once WebGL is confirmed" .-> pres
pres --> canvas --> rig --> scenes
canvas --> html
scenes --> focus
html --> data
scenes --> data
html --> i18n
visitor --> health --> db -. "only if DATABASE_URL" .-> pg
One scroll offset drives the camera, every scene transform and every label's opacity — deriving all of them from a single number is what keeps 3D and HTML in lockstep at any frame rate.
flowchart LR
classDef n fill:#0b1c2a,stroke:#4de1c1,color:#edf7fb
classDef o fill:#10283a,stroke:#7dd3fc,color:#edf7fb
s["scroll.offset<br/>0 → 1"]:::n --> p["page = offset × (5 − 1)"]:::n
p --> i["current = floor(page)<br/>local = page − current"]:::n
i --> t["transition = smoothstep(local)"]:::n
t --> cam["camera position + lookAt<br/>lerp → exponential damp"]:::o
p --> f["focus = clamp(1 − abs(page − index) ÷ 1.08)"]:::n
f --> sc["group scale 0.56 → 1.00"]:::o
f --> lb["label opacity + visibility"]:::o
s --> native["native scroll geometry<br/>sectionFromScrollTop"]:::n
native --> ui["hash · nav highlight · progress · live region"]:::o
flowchart TD
classDef q fill:#10283a,stroke:#7dd3fc,color:#edf7fb
classDef ok fill:#0b1c2a,stroke:#4de1c1,color:#edf7fb
classDef bad fill:#0b1c2a,stroke:#fb5b5b,color:#edf7fb
a["GET /api/health"]:::q --> b{"DATABASE_URL set"}:::q
b -- no --> c["database: not-configured<br/>HTTP 200"]:::ok
b -- yes --> d["race: SELECT 1 vs 2000 ms timeout"]:::q
d -- resolves --> e["database: ready<br/>HTTP 200"]:::ok
d -- rejects or timeout --> f["database: unavailable<br/>HTTP 503"]:::bad
g["HEAD /api/health"]:::q --> h["HTTP 204 · no body · no DB touch"]:::ok
Tip
Point container liveness probes at HEAD /api/health (cheap, never touches the pool) and readiness probes at GET. A presentation with no database attached stays healthy by design — it is not degraded, it is simply stateless.
First paint must not depend on WebGL. The engine chunk is requested only after the preference/device probe confirms that the browser can create a rendering context, so a device that cannot run the deck does not request the Three.js chunk—it is served the /handout text briefing instead.
sequenceDiagram
autonumber
participant V as Visitor
participant S as PresentationShell
participant D as Dynamic import
participant P as Presentation
participant G as WebGL
V->>S: GET /
S-->>V: EngineLoader — crest and status line (no Three.js)
S->>S: probeDevice() — WebGL, cores, memory, reduced motion
S-->>V: experience-loader (role=status, aria-live=polite)
S->>D: import("@/components/Presentation")
D->>P: module resolved
P->>G: create single Canvas context
G-->>P: context ready
P-->>V: control room ready at section 01
Note over S,P: Any throw inside P is caught by ExperienceBoundary →<br/>"Retry engine" panel instead of a blank document
- URL, navigation, progress, and live-region state derive from the native scroll event—not the GPU frame loop—so they remain correct when rendering is throttled or suspended.
- Damping uses
1 − e^(−k·Δt), which is frame-rate independent across 30, 60, and 144 Hz. goToSection()scrolls the real DOM container obtained throughScrollBridge, so keyboard, nav-chip, and progress-dot navigation all share one code path.
sequenceDiagram
autonumber
participant U as User
participant P as Presentation
participant L as localStorage
participant DOM as documentElement
participant I as Intl
U->>P: toggle AR / EN
P->>L: setItem("logisdata.language", next)
P->>DOM: lang = next · dir = rtl or ltr
P->>I: NumberFormat ar-EG or en-US
I-->>P: localized numerals, percentages, compact USD
P-->>U: mirrored layout, Arabic copy, Eastern Arabic digits
Note over P,L: On next visit the preference is read<br/>synchronously in useState's initializer — no flash
Theme follows the same pattern against logisdata.theme, additionally setting colorScheme so native form controls and scrollbars match the active surface.
| Step | Input | Control | Output |
|---|---|---|---|
| 1 | Contracted distance | Carrier rate agreement | billedMileage |
| 2 | Telematics distance | GPS / ELD stream | actualMileage |
| 3 | Duplicate detection | Invoice-line fingerprinting | duplicateBillingPct |
| 4 | Rate reconciliation | Tariff versus applied rate | overchargePct |
| 5 | Verdict | Threshold policy | red-flag | passed |
The HTML table renders the ledger; the AuditScanner scene renders the same rows as a laser gate reconciling telemetry against contract. Both read the identical array — there is no "presentation copy" of the numbers that can drift from the model.
Requirements — Node.js 22+, npm. A GPU is recommended but not required; the experience degrades gracefully through ExperienceBoundary.
git clone https://github.com/YASLOGIST/LOGISDATA.git
cd LOGISDATA/LOGISDATA
npm ci
npm run devOpen http://localhost:3000. The deck loads straight into the overview section; individual stages are deep-linkable (/#warehouse).
Optional — attach PostgreSQL for readiness checks
cp .env.example .env.local
# edit DATABASE_URL, then restart the dev server
curl -s localhost:3000/api/health | jq| Variable | Default | Purpose |
|---|---|---|
DATABASE_URL |
(unset) | Postgres connection string. Unset ⇒ database: "not-configured", still 200. |
DATABASE_POOL_MAX |
10 |
Pool ceiling, clamped to 1…50. |
DATABASE_SSL |
false |
true enables TLS with rejectUnauthorized. |
NEXT_PUBLIC_SITE_URL |
http://localhost:3000 |
metadataBase — drives absolute OG/Twitter image URLs. |
| Command | Gate | Blocking |
|---|---|---|
npm run typecheck |
tsc --noEmit under strict |
✅ |
npm run lint |
ESLint flat config, Core Web Vitals | ✅ |
npm run build |
Production compile + route collection | ✅ |
npm audit |
Dependency advisories (currently 0) | ✅ |
npm run test |
213 Vitest tests in 16 files | ✅ |
npm run test:coverage |
80% statements/branches/functions and 85% lines; current measured result 89.78% / 85.83% / 89.57% / 92.55% | ✅ |
npm run test:e2e |
60 Playwright checks across desktop, reduced-motion and mobile—including axe accessibility and performance budgets; requires Chromium | ✅ 60/60 in CI |
npm run budget |
Gzipped landing payload against a 205,000 B ceiling; current measured result 202,616 B | ✅ |
npm run check |
Types, lint, unit tests, and production build in sequence | ✅ |
Application runtime — framework, 3D, motion, typography
| Layer | Technology | Version | Why it is here |
|---|---|---|---|
| Framework | Next.js (App Router) | ^16.3.7 |
Server components for the shell, route handlers for health, first-class code splitting for the engine boundary |
| UI runtime | React | 19.2.6 |
Concurrent rendering; useState initializers read persisted preferences without a flash |
| Language | TypeScript | 5.9.3 |
strict: true; LocalizedText turns a missing translation into a build failure |
| 3D | Three.js | ^0.185.1 |
Industry-standard WebGL abstraction with a predictable memory model |
| 3D bindings | @react-three/fiber | ^9.7.0 |
Declarative scene graph; useFrame for allocation-free animation |
| 3D helpers | @react-three/drei | ^10.7.7 |
ScrollControls, Scroll, Html, Line, Float |
| Motion | Framer Motion | ^12.43.0 |
Entry choreography plus useReducedMotion as a first-class input |
| Icons | lucide-react | ^1.48.0 |
Tree-shaken SVG icons, no icon font |
| Styling | Tailwind CSS 4 + CSS custom properties | 4.1.17 |
Utility layer for structure, tokenized variables for theme and RTL |
| Typography | Cairo Variable | ^5.3.0 |
One self-hosted variable face that covers Latin and Arabic |
Data plane (optional) — ORM, driver, migrations
| Layer | Technology | Version | Why it is here |
|---|---|---|---|
| ORM | Drizzle ORM | 0.45.2 |
Typed SQL with zero runtime reflection |
| Driver | node-postgres | 8.20.0 |
Explicit, bounded pooling with predictable timeouts |
| Migrations | drizzle-kit | ^0.31.11 |
schema.ts is intentionally empty — the deck owns no tables yet |
Toolchain and asset pipeline
| Layer | Technology | Version | Why it is here |
|---|---|---|---|
| Linting | ESLint 9 flat config + eslint-config-next |
9.39.4 |
Core Web Vitals ruleset, .next/out/build globally ignored |
| CSS build | @tailwindcss/postcss | 4.1.17 |
Tailwind 4 pipeline without a legacy PostCSS chain |
| Supply chain | overrides.esbuild |
0.25.12 |
Pins a transitive dependency to keep npm audit at zero findings |
| OG renderer | @napi-rs/canvas + gifenc | see tools/og-image |
Deterministic vector rasterization and a hand-tuned GIF encoder |
Operations — health endpoint contract
GET /api/health # readiness — Cache-Control: no-store
HEAD /api/health # liveness — 204, no body, no pool access{
"ok": true,
"service": "logisdata-control-room",
"version": "3.1.0",
"database": "ready | unavailable | not-configured",
"uptimeSeconds": 42,
"timestamp": "2026-10-02T19:42:00.000Z"
}version defaults to package.json and can be replaced by a non-empty NEXT_PUBLIC_APP_VERSION deployment identifier.
| Situation | database |
HTTP | Interpretation |
|---|---|---|---|
No DATABASE_URL |
not-configured |
200 |
Stateless deck — healthy |
SELECT 1 succeeds |
ready |
200 |
Fully operational |
| Unreachable or >2 s | unavailable |
503 |
Page the on-call, not the presenter |
Operations — security posture
Applied to every route by next.config.ts. Production responses carry nine security headers; API responses additionally carry Cache-Control: no-store, max-age=0.
| Header | Value | Threat addressed |
|---|---|---|
Content-Security-Policy |
self-origin defaults; objects/frames disabled; documented inline-script exception | Injection and embedding surface |
X-Content-Type-Options |
nosniff |
MIME confusion |
X-Frame-Options |
DENY |
Clickjacking |
Referrer-Policy |
strict-origin-when-cross-origin |
Referrer leakage |
Permissions-Policy |
camera, microphone, geolocation, payment, usb = () |
Silent capability acquisition |
Cross-Origin-Opener-Policy |
same-origin |
Cross-origin window tampering |
Cross-Origin-Resource-Policy |
same-origin |
Speculative cross-origin reads |
X-DNS-Prefetch-Control |
on |
Explicit DNS-prefetch policy |
Strict-Transport-Security |
max-age=63072000; includeSubDomains; preload (production only) |
Protocol downgrade |
poweredByHeader is disabled, compress is enabled and reactStrictMode is on.
Social preview pipeline — the compiled Open Graph card
The Open Graph card is not a screenshot — it is compiled, from the same tokens and the same graph data the product renders.
| Property | Value |
|---|---|
| Primary asset | LOGISDATA/public/og-image-animated.gif |
| Static fallback | LOGISDATA/public/og-image.png |
| Geometry | 1200 × 630 (1.91:1 — Open Graph and summary_large_image) |
| Motion | 36 frames · 60 ms · 2.16 s seamless loop |
| Colour | One global 255-colour table + 8×8 Bayer ordered dither |
| Compression | Inter-frame delta with a transparent index and dispose: 1 |
| Weight | ≈1.6 MB — inside Facebook, LinkedIn and X card limits |
| Build time | ≈1.5 s, deterministic (same input ⇒ same bytes) |
| Source | tools/og-image/generate-og.mjs |
What animates — and why each element earns its place
| Motion | Mirrors | Product meaning |
|---|---|---|
| Emerald gate sweeping left → right | AuditScanner laser gate |
The audit pass itself |
| Metric digits scrambling, then a tick | MetricCounter |
Simulated re-verification of an illustrative figure |
| Packets travelling the node graph | SupplyNetwork (the real 8 nodes / 10 edges) |
Signal flow between facilities |
| Red and amber rings pulsing | status: "leak" | "phantom" |
Unverified nodes demanding attention |
| Five-segment rail illuminating 01 → 05 | The five sections | The narrative spine of the deck |
| Crest watermark and pill pulse | HeroSection lockup |
Institutional provenance |
Engineering notes — how the file stays under 2 MB at 1200×630
- Supersampled vector rendering. Every frame is drawn at 2× (2400×1260) and box-filtered down, so type and hairlines are antialiased without relying on a browser or GPU.
- Pixel-grid hairlines. 1 px rules are placed on half-pixel centres at 1× so they survive downsampling as a single crisp pixel rather than a 2 px blur.
- One global palette. Colours are fitted once across a stratified sample of frames, so no frame carries a local colour table.
- Ordered dithering, not error diffusion. An 8×8 Bayer matrix at low amplitude removes gradient banding while preserving the long horizontal runs that LZW compresses — Floyd–Steinberg would look marginally smoother and roughly double the file.
- Delta frames. Pixels identical to the previous frame are written as the transparent index with
dispose: 1; typical frames mutate only 8–17% of the canvas. - Deterministic noise. The digit scramble uses a hash function rather than
Math.random, so the asset is byte-reproducible and reviewable in a diff. - Loop-closure invariant. Every animated quantity is periodic over the loop, and the gate parks off-canvas for the final 18% — so frame 36 and frame 1 are visually identical and the loop has no seam.
cd tools/og-image
npm run build # gif + png
npm run preview # png only — fast design iteration
node generate-og.mjs --frame=13 # inspect any single frameMetadata is wired in src/app/layout.tsx: the animated GIF is listed first for both openGraph.images and twitter.images, with the PNG immediately behind it for scrapers that cannot decode GIF. Set NEXT_PUBLIC_SITE_URL in production so both resolve to absolute URLs.
The cinematic hero at the top of this document is an original, procedurally rendered animation made for this repository. It is not a screenshot, stock footage or a typing banner. Every element in it comes from the product: the 8 nodes and 10 edges of lib/data.ts with their real verified / leak / phantom statuses, the app's own status vocabulary (Verified · Leak Risk · Phantom Signal), the five theatres from the navigation copy, and the three illustrative model metrics.
| Property | Value |
|---|---|
| Animated hero | assets/readme/yaslogist-hero.gif — 1920 × 720, 120 frames × 80 ms = 9.6 s seamless loop, 5.8 MB |
| Static poster | assets/readme/yaslogist-hero.png — full-colour frame at the Act III peak; served automatically to visitors with prefers-reduced-motion |
| Renderer | assets/readme/source/render-hero.mjs — Skia (@napi-rs/canvas), deterministic, no browser |
| Typography | Space Grotesk + JetBrains Mono, composited as real vector type (no generated lettering) |
Direction — what moves, and why
| Act | Loop window | What happens |
|---|---|---|
| I · Emergence | 0.00 – 0.18 | Calm baseline. Packets idle on the graph, range rings breathe outward on the floor, a light glint passes through the LOGISDATA wordmark |
| II · Activation | 0.18 – 0.45 | The emerald audit gate materialises and sweeps the floor plan. The floor grid lights where it passes. Each node it crosses flashes and resolves to its real status, and the four reconciliations flip from Awaiting to Reconciled |
| III · System intelligence | 0.45 – 0.74 | Reticles lock on the four flagged nodes, edges between audited nodes turn emerald, and the read-out reaches 8/8 nodes · 4 verified · 4 flagged |
| IV · Brand resolution | 0.74 – 1.00 | The gate dissolves and audit state settles back to baseline. A glint passes through the YASLOGIST signature, and the frame returns to its opening state |
A slow orbital camera (yaw, pitch and dolly, all periodic) gives the scene real parallax. The floor shadows, dashed drop-pins and depth-scaled labels sit in the same 3D projection as the graph.
Encoder — how a 1920 × 720 loop stays under 6 MB without banding
- One fitted global palette. 9 brand colours are pinned, and 246 more are fitted by median cut and refined with k-means over 16 frames sampled across all four acts. The palette is checked against the source render: mean error ≈ 4/765 per pixel, 99th percentile ≤ 15. The previous hero's palette mapped faint light shafts to saturated cyan; this encoder replaces it.
- Ordered dither. An 8 × 8 Bayer matrix is position-stable, so static regions produce identical indices in every frame and cost almost nothing.
- Display-referenced deltas. Each frame is diffed against what the decoder is showing, not against the previous source frame, so the bounded tolerance can never accumulate into drift. Each frame is also cropped to its dirty rectangle.
- Run extension. A changed pixel reuses its left neighbour's index when the two are perceptually indistinguishable, which gives LZW longer runs.
- Loop closure. Every animated quantity is a periodic function of loop time, and event state fades out before the wrap. Measured on the decoded GIF, the wrap step (0.83) falls inside the range of interior frame steps (mean 0.52, max 1.07), so the loop has no visible seam.
| Supporting motion | Role |
|---|---|
kinetic-statement.svg |
The four reconciliations, cycling on a 12 s rail |
focus-curve.svg |
The runtime focus curve, animated from the real constants |
divider-pulse.svg |
Luminous section divider |
yaslogist-signature.svg |
Closing brand signature |
GitHub renders README SVGs through <img>, which cannot load web fonts. So every glyph in these SVGs is outlined to a path from the real font files, and type looks identical on every machine. Motion is native SMIL: no script and no CSS.
cd assets/readme/source
npm install
npm run build # hero GIF + poster + SVGs
node render-hero.mjs --frame=60 --out=/tmp/f.png # inspect any single frame| Category | State |
|---|---|
| All 29 capability-matrix rows | ✅ Implemented and tested — unit suite locally, full browser suite in CI |
| Architecture diagrams, module map, health contract | ✅ Verified against source at the documented commit |
| Metrics, freight rows, demand tiers, routes, bins | |
| PostgreSQL layer | schema.ts is empty; the deck owns no tables |
Warning
Every figure in this deck is illustrative and presentation-realistic — modelled to be defensible in an executive conversation, not extracted from a production system. Validate against authoritative ERP, TMS, WMS, invoice and telematics sources before any operational or investment decision. The architecture is built so that swapping lib/data.ts for a live adapter changes no component contract.
LOGISDATA/
├── README.md this document
├── assets/readme/ cinematic hero, poster and secondary motion
│ ├── yaslogist-hero.gif animated README hero (primary)
│ ├── yaslogist-hero.png static poster (reduced-motion fallback)
│ ├── kinetic-statement.svg the four reconciliations, cycling
│ ├── focus-curve.svg animated scene-focus curve
│ ├── divider-pulse.svg luminous section divider
│ ├── yaslogist-signature.svg closing brand signature
│ └── source/ deterministic renderers for all of the above
├── LOGISDATA/ the Next.js application
│ ├── public/
│ │ ├── og-image-animated.gif animated social card (primary)
│ │ ├── og-image.png static social card (fallback)
│ │ └── aast-logo.png institutional crest
│ └── src/
│ ├── app/ layout, page, globals.css, api/health
│ ├── components/ shell, presentation, sections/, three/, ui/
│ ├── db/ lazy Drizzle + pg adapter
│ └── lib/ data, i18n, sceneFocus, types
└── tools/
└── og-image/ deterministic OG card renderer
LOGISDATA is the product. YASLOGIST is the permanent engineering signature beneath it — the creative-technical system this control room is designed, rendered and documented under.
| Product identity | LOGISDATA — Supply-Chain Audit Control Room |
| Signature | YASLOGIST |
| Website | yaslogist.com |
| Repository | github.com/YASLOGIST/LOGISDATA |
Control the signal. Protect the margin.
Ahmed Yasser Ali · Reg. 211010269
Arab Academy for Science, Technology & Maritime Transport — Executive Data Lab
© YASLOGIST · LOGISDATA v3.1.0 · engineered, animated and documented as one visual system
