---
title: "Właściwa architektura to ta zwymiarowana pod problem."
url: "https://simonebova.com/pl/colophon"
lang: "pl"
author: Simone Bova
alternates:
  it: "https://simonebova.com/md/it/colophon"
  en: "https://simonebova.com/md/en/colophon"
  pl: "https://simonebova.com/md/pl/colophon"
---

# Właściwa architektura to ta zwymiarowana pod problem.

Problem jest tu precyzyjny: osobiste archiwum, które ma być szybkie, kosztować zero, dać się czytać ludziom, crawlerom i agentom, i dać się utrzymywać na autopilocie. Cała reszta tej strony z tego wynika.

## Wymagania → decyzje

- **Lekkość:** Statyczny HTML z CDN, client JS tylko tam, gdzie jest interakcja. Wąskim gardłem ma być czytanie, nigdy ładowanie.

- **Zero overheadu:** Żadnego serwera, bazy, CMS-a: nic do patchowania, nic, co można włamać, nic, co dzwoni o 3 w nocy. Osobiste archiwum nie może wymagać operacyjnej uwagi.

- **Tanio:** Statyczny build na planie hobby: koszt krańcowy wizyty to ~zero, koszt stały też. Pieniądze idą w treść, nie w hosting.

- **Autopilot:** Strona utrzymuje się sama: ja mówię, co trzeba, [code-os](https://github.com/yempik-ai/code-os) to buduje, gate decyduje, czy się wdraża. [agent-memory](https://github.com/yempik-ai/code-os) z zasadami i definition of done, decyzje zapisane jako ADR: świeża sesja agentowa jest produktywna od pierwszego prompta, beze mnie w roli pamięci.

- **Findability / tokeny:** Architektura danych też jest dla agentów: typowane dane w src/content z przewidywalnymi ścieżkami, jeden komponent na odpowiedzialność, nazwy mówiące, co robią. Wszystko da się znaleźć bez palenia tokenów na eksplorację: minimalny wystarczający kontekst to właściwość repo, nie prompta.

- **SEO + GEO:** Statyczne jest crawlowalne z definicji, a Next wykorzystuję do tego, co umie: Metadata API dla canonicali i OpenGraph, typowane sitemap i robots, OG images generowane w build time przez ImageResponse, fonty self-hosted przez next/font (zero layout shift), JSON-LD w layoutach. Dla szukających przez AI: llms.txt i /api/dossier, z tego samego źródła co strony.

- **Niekomercyjność:** Żadnych funneli, popupów, trackerów firm trzecich (cookieless analytics i tyle). To archiwum do czytania, nie landing do konwersji.

*// ta strona też: powiedziałem, czego chcę, harness ją zbudował, gate zatwierdził.*

## Architektura

- **CONTENT / SSoT:** src/content/*.ts: eseje, zasady, work: typowane dane, 3 języki

- **REACT SERVER COMPONENTS:** cienkie route, sekcje SRP, client JS tylko przy interakcji

- **STATIC BUILD:** każda route to HTML w build time, także OG, llms.txt, JSON

- **EDGE / CDN:** Vercel: zero compute w runtime, koszt krańcowy ~0

ta sama treść wychodzi przez /llms.txt i /api/dossier

- **GATE:** eslint, tsc --noEmit, next build. zielone, albo nie ma commita

- **INWARIANTY:** a11y AA, reduced motion, jeden akcent, SSoT-derived, parytet i18n. regresja = bug

## Decision record

### ADR-001: Zero zależności, plus jedna

2026-07-12 · accepted

Runtime: Next + React + react-aria-components (dostępność widgetów: focus management, press semantics, focus trap: rzeczy, które psujesz, jeśli piszesz je od nowa). Bez Tailwinda, CMS-a, UI kitów, bibliotek animacji. Konsekwencja: minimalna powierzchnia update'ów, każda linia w bundlu jest uzasadnialna.

### ADR-002: Wszystko statyczne, zawsze

2026-07-12 · accepted

Każda route (HTML, OG image, llms.txt, /api/dossier) jest generowana w build time i serwowana z CDN. Zero compute w runtime: bez cold startów, powierzchnia ataku zredukowana do minimum, ~zerowy koszt krańcowy requesta. Ograniczenie zaakceptowane: nowa treść = nowy deploy.

### ADR-003: Treść to typ, nie strona

2026-07-12 · accepted

Eseje, zasady, work żyją w src/content jako typowane obiekty (SSoT). Archiwum, strona główna, sitemap, OG, llms.txt i /api/dossier pochodzą z jednego źródła. Konsekwencja: treść pisze się raz i nie może się rozjechać między formatami.

### ADR-004: Jeden akcent

2026-07-12 · accepted

#E35B2D, wszędzie; na śniegu ciemniejszy odcień (#B8481C) dla kontrastu AA na małym tekście: ta sama barwa, nie drugi kolor. Obowiązuje też w easter eggach: każda śnieżyca ma dokładnie jeden pomarańczowy płatek.

### ADR-005: Motion jako dekoracja, nigdy jako gate

2026-07-12 · accepted

Ukryty stan scroll-reveala istnieje tylko przy włączonym JS (@media scripting) i dozwolonym motion. JS wyłączony albo prefers-reduced-motion: treść nietknięta. Animacje są warstwą nad treścią, nie warunkiem jej czytania.

### ADR-006: Dostępność jako inwariant

2026-07-12 · accepted

Skip-link z fokusowalnym celem, widoczny focus ring, aria-current w nawigacji, kontrasty AA, linki zewnętrzne ogłaszane, aria-live nawet dla easter eggów. Traktowana jak testy: regresja to bug, nie kompromis.

### ADR-007: Czytelne dla maszyn

2026-07-12 · accepted

/llms.txt dla agentów, /api/dossier dla curla, JSON-LD dla crawlerów: wszystko generowane z tego samego SSoT co strony, więc nigdy rozsynchronizowane. Kontekst o mnie serwuję sam, w formacie odbiorcy.

### ADR-008: Trzy języki, jeden SSoT

2026-07-16 · accepted

IT, EN, PL jako statyczne route (/it /en /pl), hreflang per strona, wspólne slugi. Bez middleware: detekcja to statyczny redirect. Parytet między językami sprawdzany w build time: brakujące tłumaczenie psuje build, nie zaufanie.

### ADR-009: Świat to baner

2026-10-28 · accepted

Strona staje się SimoFree: baner z LinkedIna, na żywo. Canvas rysowany raz na rozmiar (bez pętli); wszystko, co da się przeczytać lub kliknąć, to DOM nad nim, w tej samej kamerze. Śnieg, tusz, jeden akcent. Easter egg to prawdziwa, opcjonalna gra.

### ADR-010: Dwóch czytelników: ludzie i agenci

2026-10-28 · accepted

Każda strona ma bliźniaka w Markdownie z tego samego źródła, do tego llms.txt, llms-full.txt i serwer MCP tylko do odczytu. HTML pozostaje kanoniczny; Markdown ma noindex. Przełącznik Człowiek / Agent pokazuje, co czyta agent.

### ADR-011: Zjazdy i trasy

2026-10-28 · accepted

Case'y to zjazdy (wspólne slugi, historie bez liczb klientów); sposoby współpracy to trasy (slugi w każdym języku, jedna wyszukiwana fraza na stronę, trudność kodowana kształtem, nigdy samym kolorem).

### ADR-012: Ranking SimoFree weryfikowany przez powtórkę

2026-10-30 · accepted

Serwer nie ufa liczbom. Wydaje seed, przeglądarka zapisuje wejścia ze stałym krokiem (120 Hz), a serwer odtwarza zjazd tą samą czystą symulacją i sam liczy wynik. Jednorazowe tickety, minimalny czas rzeczywisty, limity na IP zapisane jako HMAC, tylko dodatnie wyniki, top 100 w Upstash.

### ADR-013: Jeden ciągły ruch: niebo w stopce

2026-11-08 · accepted

Zjazd kończy się nocą: w stopce jest niebo z kropek (dither 1-bit) z yeti na orbicie. Canvas rysuje się raz na rozmiar; yeti to warstwa DOM przesuwana tylko przez transform, zapisywana tylko gdy poza zmienia się o piksel. Pętla działa tylko, gdy niebo jest na ekranie i nikt jej nie zatrzymał (WCAG 2.2.2). Przy reduced motion yeti stoi, a pętla się nie uruchamia. To wyjątek od zasady zero nieskończonych animacji; ADR-014 rozszerza ten sam kontrakt na resztę strony.

### ADR-014: Świat się rusza: jedna choreografia, jeden przełącznik

2026-11-08 · accepted

Nagłówek to żywy baner: Simone zjeżdża, skacze z nawisu (inny trik na każdym okrążeniu, wywrotka co czwarte), a yeti go goni i przegrywa. Choreografia to czysta, przetestowana funkcja czasu i zaczyna się dokładnie od klatki banera. Canvas stoi; ruszają się tylko warstwy DOM przez transform. Każda animacja tła przechodzi przez jeden hook (tylko na ekranie, nigdy w tle) i jeden przełącznik pauzy dla całej strony. Przewijanie to zjazd: jedna bramka na sekcję w nawigacji. Turyn, Mediolan i Warszawa na horyzoncie.

### ADR-015: Pasek przewijania też należy do stoku

2026-11-08 · accepted

Na myszy i gładziku natywny pasek staje się cienką szyną: suwak w trakcie używania zamienia się w box HUD w kolorze akcentu, a każda numerowana sekcja to nazwana bramka, do której można przeciągnąć albo kliknąć. Natywne przewijanie zostaje nietknięte (klawiatura, kółko, dotyk, technologie asystujące); szyna tylko je odzwierciedla i jest aria-hidden. Natywny pasek znika dopiero, gdy szyna się zamontuje, więc bez JS albo na dotyku zostaje systemowy. Podąża za przewijaniem, to nie ruch tła: jedna zmienna CSS na klatkę.

## Dla maszyn

Treść o mnie serwuję sam, w formacie tego, kto ją konsumuje. Agenci czytają /llms.txt; kto woli terminal, ma endpoint JSON generowany z tego samego SSoT co strony:

- [llms.txt](https://simonebova.com/llms.txt): concise site index.
- [llms-full.txt](https://simonebova.com/llms-full.txt): every English page in full.
- [Dossier JSON](https://simonebova.com/api/dossier): structured public profile.
- [MCP](https://simonebova.com/mcp): POST JSON-RPC over stateless Streamable HTTP, initialize then tools/list and tools/call.

*// jedno źródło, trzy formaty: HTML dla ciebie, llms.txt dla agentów, JSON dla curla.*

[simone@yempik.ai](mailto:simone@yempik.ai) · [Book a call](https://calendar.app.google/LKDrQPKGV2EAFCMN9)
