Ta przeglądarka nie uruchomiła grafiki 3D, treść strony działa bez niej.
Przejdź do treści
Wróć do cennika

Dla nerdów

Specyfikacja strony, na której jesteś. Bez tłumaczenia na ludzki, od tego są pozostałe podstrony.

Stos

serwer
php:8.4-apache w Dockerze, Coolify na Hetznerze; brotli, potem gzip
aplikacja
PHP bez frameworka, bez bazy danych, bez kroku budowania; wspólne części przez require, treść zmienna w dane/*.json
adresy
mod_rewrite: /cennik → cennik.php; mapa strony generowana z plików, które naprawdę istnieją
3D
Three.js 0.186.0, odchudzony esbuildem do tego, czego używa znak (three-znak.min.js, 539 KB, po brotli 127 KB)
kroje
Jost (zmienny, 100–900) i Martian Mono, woff2 z własnego serwera, przycięte do potrzebnych znaków
zewnętrzne
zero CDN: kroje i biblioteki z tej samej domeny; CDN oddaje IP odwiedzającego komuś trzeciemu. Jedyny obcy skrypt to Google Tag Manager z pomiarem odwiedzin, a wczytuje się dopiero po zgodzie z banera; bez niej strona nie łączy się z Google
poczta
formularz → api/kontakt.php → Brevo API; token jednorazowy, pułapka czasowa 3 s, limit 3 / 10 min i 8 / h z adresu

// WordPress? Postawić CMS, a potem wyciąć z niego wszystko, co daje. Już to przerabiałem.

Dlaczego nie WordPress

Treść prowadzi jedna osoba, bez ról i redakcji w panelu. Strona czyta sześć małych plików JSON: realizacje, narzędzia Laboratorium, wycenę z cenami rynkowymi, dane kontaktowe, wyniki PageSpeed do /outsourcing i liczby z tej podstrony. Cały ciężar leży w WebGL, ruchu i preloadzie, a tego żaden motyw ani wtyczka nie daje. WordPress dokładałby bazę, aktualizacje i powierzchnię ataku, nie dając w zamian niczego, czego ta strona używa.

Znak nieskończoności

kontekst
WebGL 2 (GLSL ES 3.00), jedna scena na stronę: galaktyka, znak, pył i poświata w jednym przebiegu
bryła
parametryczna rura po osi lemniskaty (długość łuku u × kąt przekroju), złącze zlewane wygładzonym minimum; od 31 411 (poziom 1) do 182 115 (poziom 5) wierzchołków; faktura farby i włosia pędzla wypieczona w geometrii, liczona w Web Workerze i trzymana w IndexedDB
pył
symulacja na GPU (GPUComputationRenderer): pozycja i prędkość w teksturach; 21 904 punkty na poziomach 1–3 i 54 756 na 5; do tego 170 630 wierzchołków włókien na poziomie 5
rozpad
globalny (przewijanie): bryła i cząstki liczą tę samą funkcję rozpadG(pozycja); lokalny (kursor): mapa ubytku u × kąt na GPU, 60% wyrwanego pyłu wraca i odbudowuje bryłę
barwy
tablica 2049 × 2 (barwa i blask w poprzek znaku) w teksturze; pasma światła, włosie i lakier w cieniowaniu; porwanie prawego górnego łuku jako strefa z kawałkami (Voronoi z szarpaniem)
jakość
cztery poziomy (1, 2, 3 i 5), drabina z histerezą przy pierwszym wejściu, wynik zapamiętany: w górę 1→2 od 40 kl/s, 2→3 od 40, 3→5 od 57 (tylko komputer; na dotyku 3 jest sufitem); w dół 2→1 poniżej 30, 3→2 poniżej 35, 5→3 poniżej 50
ostrość
nigdy poniżej 1 piksela obrazu na piksel CSS; telefon rozciąga najwyżej ~1,35×, tablet i komputer ~2,25×; sufit klatek 60 (dotyk) i 120 (komputer)

// Poniżej poziomu 1 nie schodzimy. Słabszy telefon dostaje mniej klatek, nie brzydszy znak.

Preload

zasada
treść jest w HTML od pierwszego bajtu, preload to nakładka nad gotowym dokumentem, nie blokada renderowania; bez JS nakładki nie ma
wejście
okno rysuje się kreską → tło z cienia (0,8 s) → pył wyłania się (1,2 s) → składa w bryłę (1,7 s) → okno się rozchodzi, znak dojeżdża z pełnym obrotem (1,3 s)
przejście
klik → znak leci do okna ze szkieletem strony docelowej (1,15 s) → rozpyla się (1,4 s), niebo gaśnie (2,2 s) → szew w czerni → przeładowanie; faza pętli okna przechodzi przez szew w sessionStorage, więc okno nie restartuje
awaryjnie
ostrzeżenie po 5 s od wstępu, twardy bezpiecznik 12 s, błąd sceny: wyjście od razu; „pomiń" zawsze pod ręką
rodziny
osobna rodzina przy przejściach wewnątrz Laboratorium: bez okna i szkieletu; znak rośnie ku ekranowi (bryła ~2,6 szerokości ekranu) i rozpyla się na całą treść, bez znaku gaśnie sama nakładka → 0,65 s czerni → treść wchodzi kaskadą, a znak (jeśli podstrona go ma) składa się z pyłu od razu na swoim miejscu

Ruch

tor znaku
1:1 z przewijaniem: kotwice w znaczniku (data-znak-poza="x:.56 y:.34 z:-1 s:.4"), między nimi Hermite ze stycznymi monotonicznymi, prędkość ciągła, bez przestrzeliwania
przewijanie
kółko z własną bezwładnością (przewijanie.js), dotyk systemowy; ruch sekcji: scrollcraft, bez GSAP
zatrzask
oskryptowane przejście 2,4 s, przeskok strony w 45% animacji; próg celowo nieczuły: 150 px kółka, 60 px palca; dogrywa do końca i ignoruje gesty
reduced motion
prefers-reduced-motion: bez preloadu, znak stoi w pozie najbliższej sekcji, zatrzask przeskakuje bez animacji, dryf i fale gasną

Laboratorium

podgląd
iframe z sandbox bez allow-top-navigation; blokady ramki rodzic nie widzi (load ~220 ms i te same wyjątki co przy stronie, która się wczytała), więc heurystyka: lista domen i czas
studio
żywy znak strony + fwScena.studio(): uniform strefy porwania, rozpad, widoczność warstw, przepisana tablica barw, tempo światła
grafika
WebP / PNG / JPEG przez canvas.toBlob; AVIF: @jsquash/avif (libavif w WASM, 3,4 MB) w osobnym wątku, dociągany przy pierwszym użyciu
QR
koder uqr w przeglądarce; eksport PNG, SVG, JPG, WebP i PDF bez udziału serwera
waluty
średnie kursy NBP (tabela A) pobiera serwer i trzyma kopię; przeglądarka pyta tylko /api/kursy, przeliczenie i wykres idą lokalnie

Podłoga techniczna

nagłówki
Strict-Transport-Security, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Cross-Origin-Opener-Policy, Permissions-Policy, Content-Security-Policy (główna i dwa warianty dla narzędzi Laboratorium)
CSP
default-src 'self'; wyjątki per narzędzie w <If>: frame-src https: dla podglądu, 'wasm-unsafe-eval' dla AVIF
dane strukturalne
ProfessionalService, WebSite, WebPage, Person, AboutPage, CollectionPage, ItemList, Service, AggregateOffer, ContactPage, CreativeWork, WebApplication, BreadcrumbList, TechArticle
indeksacja
/sitemap.xml z plików, które istnieją; robots.txt; kanoniczne adresy i Open Graph na każdej podstronie
pamięć
kod i style z ETag i no-cache (304 bez treści), bez wersji w nazwach plików

Liczby

Zmierzone liczby strony głównej i całej witryny
strona główna: przesłane (brotli) / po rozpakowaniu749 KB / 1,61 MB
z tego JavaScript (po rozpakowaniu)1,01 MB w 29 plikach (297 KB przesłane)
zapytania przy pierwszym wejściu49 unikalnych adresów
pliki w obrazie, razem 45,0 MB (PHP / JS / CSS / obrazy / kroje)241: 47 / 53 / 24 / 90 / 6 (+ 21 innych: dane, konfiguracja, WASM)
wynik Lighthouse z 6.10.2026: mobilny / komputer67 / 71
LCP / CLS / TBT (mobilny, symulowane)1,8 s / 0 / 4,7 s

Pomiar: strona główna na futureweb.com.pl, pierwsze wejście z pustą pamięcią podręczną, Lighthouse 13.5.0 w Chrome 154 (symulowane dławienie, preset mobilny i komputerowy, po jednym biegu), z komputera, nie z telefonu; „przesłane” to bajty z sieci po kompresji brotli, 6.10.2026. Pliki: zawartość obrazu Dockera, czyli repozytorium bez wykluczeń z .dockerignore (bez Dockerfile, plików gita, pełnej paczki three.js i prototypu znaku); obrazy to WebP, PNG, JPG, SVG i ICO; inne to dane JSON, .htaccess, robots.txt, manifest, koder WASM, licencje i strona błędu 500, 1.11.2026.

Narzędzia i sprzęt

języki
PHP, JavaScript i TypeScript, CSS, Python
frameworki
React i inne; ta strona nie używa żadnego
CMS
WordPress, motyw pisany od zera
serwery
Docker; własny hosting na Hetznerze z Coolify (tu stoi ta strona) i SEOhost dla stron klientów
3D
Blender
komputer
Ryzen 5 5600, Radeon RX 6600 XT, 16 GB RAM, płyta MSI, chłodzenie powietrzem
na biurku
monitor Acer, klawiatura Krux

// Chłodzenie powietrzem. Woda zostaje w szklance.

Dlaczego ta strona nie ma 90 w PageSpeed

W cenniku obiecuję klientom 90+. Ta strona tego wyniku nie osiąga i to jest świadomy wybór.

Strony, które robię dla klientów, nie mają sceny 3D, symulacji pyłu na karcie graficznej ani preloadu z przejściami, tam 90+ jest realne i sprawdzalne. Ta strona jest moją wizytówką, więc ma pokazać, co da się zrobić w przeglądarce. Motto projektu: jakość ponad optymalizację.

Wynik z tabeli wyżej (67 / 71) to Lighthouse na produkcji, nie moje szacunki. LCP to nie wolny serwer: za największy element Lighthouse bierze logo w nakładce preloadu i liczy intro jak ładowanie strony.

Najwięcej punktów kosztuje: wykonanie JavaScriptu sceny przy pierwszym wejściu, Three.js w paczce i praca karty graficznej, której Lighthouse nie odróżnia od zablokowanego wątku. Co zrobiłem, żeby kosztowało mniej: treść w HTML od pierwszej sekundy, preload jako nakładka, bryła liczona w tle i trzymana w IndexedDB, poziomy jakości dobrane pomiarem na urządzeniu, scena rysuje tylko to, co widać.

Zmierz sam w PageSpeed Insights (otwiera się w nowej karcie)

// Wolałem to napisać sam, niż czekać, aż ktoś zmierzy i zapyta.

Wróć do cennika