# dev

Rzeczy techniczne. Bez slopu.

Przemysław Zalewski #
Kocham issues na GitHubie w starych bibliotekach. 6 lat dyskusji, 140 komentarzy "+1", zero PR-ów. Open source jako sport widowiskowy
Przemysław Zalewski #
Idempotency key przy płatnościach: klient wysyła ten sam klucz przy ponowieniu, serwer wie, że to ta sama operacja. Bez tego user klika "Zapłać" dwa razy i płaci dwa razy. A potem pisze do supportu trzy razy
Przemysław Zalewski #
Ciekawostka: crypto.randomUUID() działa natywnie w przeglądarce i w Node. Paczka uuid ma 100 mln pobrań tygodniowo. Ludzkość pobiera bibliotekę do czegoś, co ma za darmo, 100 mln razy w tygodniu 📦
Przemysław Zalewski #
Zasada: logi strukturalne (JSON) zamiast console.log("tu jestem 2"). Za pół roku, o 3 w nocy, będziesz szukał po polach, a nie po "tu jestem 2" w 400 tysiącach linii
Przemysław Zalewski #
Tip: Cache-Control: stale-while-revalidate=60. User dostaje starą wersję od razu, a w tle leci odświeżenie. Szybkość jak z cache, świeżość prawie jak bez. Najlepszy kompromis od czasu pizzy hawajskiej
Przemysław Zalewski #
Ciekawostka: fbclid i utm_* w linkach to śledzenie. Usuwaj przed wysłaniem dalej. Albo nie, niech Zuckerberg wie, że oglądasz przepisy na pierogi o 3 w nocy
Przemysław Zalewski #
Ktoś zbudował własną wyszukiwarkę od zera: crawler, indeks, embeddingi, 3 miliardy stron, na własnym sprzęcie. A ja się cieszę, jak grep -r znajdzie mi plik w repo. Szacunek i lekka depresja
Przemysław Zalewski #
Repo email-bugs na GitHubie to moja ulubiona lektura do poduszki. Każdy klient pocztowy psuje HTML inaczej. Outlook renderuje maile silnikiem Worda. Słownie: Worda. W 2025. Maile to frontend na poziomie hard
Przemysław Zalewski #
Najlepsza ochrona przed scraperami AI, jaką widziałem: zamiast captchy pytanie "ile r jest w strawberry?". Ludzie odpowiadają, boty się mylą. Captcha z tokenizera 🍓
Przemysław Zalewski #
Klasyk o testowaniu: testy wyczerpujące są niemożliwe. Funkcja z dwoma intami 32-bitowymi to 2^64 kombinacji. Przy milionie testów na sekundę skończysz za 580 tysięcy lat. Dlatego testujemy granice, nie wszystko
Przemysław Zalewski #
Hobby: zbieram payloady, które crashują WebKita. Jedna linijka HTML-a i Safari na iOS się wywala. Testuję na nich klienty pocztowe. Apple Mail, pozdrawiam serdecznie 🍎
Przemysław Zalewski #
"Game design is simple, actually". Polecam każdemu, kto robi produkt: pętla, nagroda, trudność, która rośnie. Każda dobra apka to gra, tylko nikt nie przyznaje
Przemysław Zalewski #
Prawo Goodharta: kiedy miara staje się celem, przestaje być dobrą miarą. Leaderboard tokenów AI w firmie? Za tydzień ludzie będą generować slop, żeby być na górze. Liczba linii kodu, story pointy, tokeny, to wszystko ten sam film 📈
Przemysław Zalewski #
Fajne spojrzenie na wątki: software i przemysł lniany. Wątki, nici, przędzenie, splatanie. Nasze "thready" to dosłownie nici. A deadlock to po prostu supeł, którego nikt nie umie rozsupłać 🧵
Przemysław Zalewski #
CSS: gap działa w flexboxie od 2021. Jeśli dalej robisz margin-right na wszystkich dzieciach poza ostatnim, to masz kod starszy niż TikTok
Przemysław Zalewski #
Tip: git bisect znajdzie commit, który zepsuł buga, w log2(n) krokach. 1000 commitów to 10 sprawdzeń. Najlepsze narzędzie, którego nikt nie używa
Przemysław Zalewski #
Ciekawostka: structuredClone kopiuje Mapy, Sety, Daty i cykliczne referencje. JSON.parse(JSON.stringify()) zgubi Datę, wywali się na cyklu i zje undefined. Czas pożegnać hacki z 2015
Przemysław Zalewski #
Slate.js działa, dopóki nie przestaje. Prędzej czy później trafisz na kosmiczne bugi, zwłaszcza na telefonach. Rada: nie dotykaj inputów na mobile, pozwól natywnej edycji robić swoje. contenteditable to las, a Ty jesteś w nim bez mapy 🌲
Przemysław Zalewski #
Klasyk z xkcd: "My code's compiling". Dziś: "My agent's thinking". Ta sama wymówka, tylko droższa w tokenach. Credit where it's due 🫡
Przemysław Zalewski #
Zasada nr 1: danych produkcyjnych nie trzymamy na devie. Zasada nr 2: patrz zasada nr 1. Sekurak co tydzień ma nowy przykład, czemu
Przemysław Zalewski #
Tailwindowcy, mam coś dla was: TailwindSQL. select-from-users where-id-eq-1. Klasy w SQL-u. Brakowało tylko dark: dla zapytań po 22:00
Przemysław Zalewski #
O Panie, duży temat. Każda nowa rola to eksplozja kombinatoryczna: 2×2×2×2×2×2 = 64 kombinacje do przetestowania. Moja sugestia: wywalić role i zredukować do konceptu "A udostępnia B".

64 vs 8 💪
Przemysław Zalewski #
Mój blog ciunkos.com miał zostać koszerny: zero AI, wszystko ręcznie. Trudno się zmotywować, jak AI robi to samo jednym promptem. Czuję się jak kowal, który patrzy na fabrykę gwoździ
Przemysław Zalewski #
Ciekawostka na dziś: structuredClone(obj) robi deep copy z datami, mapami i cyklami. JSON.parse(JSON.stringify(x)) możecie pochować obok Reduxa 🪦
Przemysław Zalewski #
AbortSignal.timeout(5000) zamiast ręcznego setTimeout + controller.abort(). Jedna linijka, zero wycieków. Kto dalej pisze własny fetchWithTimeout, ten pierwszy rzuca kamieniem 🪨
Przemysław Zalewski #
Pluralizacja po polsku: 1 plik, 2 pliki, 5 plików, 22 pliki. Intl.PluralRules('pl') zwraca one / few / many. Nie róbcie count === 1 ? 'plik' : 'pliki', bo potem "5 pliki" i wstyd na pół internetu.
Przemysław Zalewski #
Intl.Segmenter liczy znaki tak, jak widzi je człowiek. '👨‍👩‍👧'.length === 8, a segmenter mówi 1. Walidacja "max 280 znaków" na .length to bug, który czeka na rodzinę z emoji 👪
Przemysław Zalewski #
Any order is better than no order. Sortujcie alfabetycznie - schemat nie musi się podobać, ale zmniejsza entropię. Można powiedzieć, że to był craft, teraz szybko i YOLO 😛
Przemysław Zalewski #
Po POST z formularza oddawajcie 303 See Other, nie 302. Przeglądarka zrobi GET na nowy adres i F5 nie wyśle formularza drugi raz. HTTP to rozwiązał w 1999, a my dalej wynajdujemy koło w server actions 🙃
Przemysław Zalewski #
Sec-Fetch-Site: same-origin - darmowa ochrona przed CSRF w każdej nowoczesnej przeglądarce. Sprawdzacie jeden nagłówek i połowa tokenów CSRF idzie do kosza.
Przemysław Zalewski #
bez-produkcji.png
Przemysław Zalewski #
Idempotency key przy płatnościach i webhookach. Klient wysyła UUID, serwer pamięta wynik. Retry po timeoutcie nie zrobi drugiego przelewu. Stripe tak robi od lat, a my "przecież nikt nie kliknie dwa razy" 😅
Przemysław Zalewski #
SQLite: PRAGMA journal_mode=WAL; i nagle czytanie nie blokuje pisania. SQLite to nie zabawka, to najczęściej wdrożona baza danych na świecie. Jest w Twoim telefonie, w Twoim samochodzie i pewnie w Twojej lodówce.
Przemysław Zalewski #
WAF Cloudflare na botach od scrapingu AI
you-shall-not-pass-lotr.gif
Przemysław Zalewski #
Feature flaga = dwa razy więcej testów (włączona i wyłączona). A nie mówiłem, testy to 🏆 - kod nie jest nic warty, tylko test case'y.
mala-zmiana.png
Przemysław Zalewski #
Cloudflare Workers: ctx.waitUntil() na rzeczy po odpowiedzi (logi, analityka, cache). User dostaje odpowiedź od razu, a Ty dalej robisz swoje. Jak kelner, który najpierw podaje, a potem liczy napiwki
Przemysław Zalewski #
Debugowałem 2 godziny. Problem: spacja niełamiąca w kluczu JSON-a. Wygląda jak spacja, zachowuje się jak spacja, nie jest spacją. Jak niektórzy ludzie
Przemysław Zalewski #
EXPLAIN ANALYZE przed każdą dyskusją "baza jest wolna". Pomiar przed opinią. W 9 na 10 przypadków brakuje indeksu, w 1 na 10 ktoś robi N+1 w pętli w ORM-ie 🤦
Przemysław Zalewski #
CSS :has() działa wszędzie. form:has(:invalid) button { opacity: .5 } - zero JS-a. Natywny nesting też jest. Sass, dziękujemy za współpracę 👋
Przemysław Zalewski #
HTTP 418 I'm a teapot to prawdziwy kod statusu. Mamy w standardzie kod dla czajnika, a dalej nie umiemy się dogadać co do 401 vs 403 🫖
Przemysław Zalewski #
content-visibility: auto na długich listach i przeglądarka nie renderuje tego, czego nie widać. Darmowe 60 FPS bez wirtualizacji i bez paczki z npm 🚀
Przemysław Zalewski #
Ktoś mi napisał funkcję, która zamienia 4 linijki ifów na jedną linijkę ternary po 240 znaków. Piękne. Nieczytelne. Piękne
chefs-kiss-french-chef.gif
Przemysław Zalewski #
Historia gita to fakty. Rebase dla odważnych, nie by default. Co dzieje się na PR, zostaje w PR.
Przemysław Zalewski #
Fix produkcyjny w 4 minuty od zgłoszenia, łącznie z testem. Gol w doliczonym czasie
robert-lewandowski.gif
Przemysław Zalewski #
Ciekawostka: Date w JS liczy miesiące od 0, a dni od 1. Ktoś to zaprojektował, zatwierdził i poszedł do domu spokojnie spać 📅
Przemysław Zalewski #
Dark mode bez flickera: <meta name="color-scheme" content="dark light"> + klasa na <html> z SSR-a. Paski przewijania i pola formularzy same się dopasują. Bez czekania na Reacta.
Przemysław Zalewski #
AbortController do fetchy w useEffect. Bez tego szybki user klika 5 razy i dostajesz odpowiedzi w losowej kolejności. Race condition jak w Monaco
Przemysław Zalewski #
Pliki z hashem w nazwie → Cache-Control: public, max-age=31536000, immutable. HTML → no-cache. Dwie linijki konfiguracji i CDN robi resztę. Kto cache'uje HTML na rok, ten deployuje dwa razy 😄
Przemysław Zalewski #
Prod leży, ale backup jest. Ostatni test odtwarzania: nigdy
panik.png
Przemysław Zalewski #
SPF, DKIM, DMARC. Trzy rekordy DNS, które decydują, czy Twój mail ląduje w inboxie, czy w spamie obok księcia z Nigerii. Sprawdź dig TXT _dmarc.twojadomena.pl zanim zapytasz, czemu newsletter nie dochodzi 📧
Przemysław Zalewski #
Promise.withResolvers() - koniec z let resolve; new Promise(r => resolve = r). Mała rzecz, a cieszy jak zielone CI.
Przemysław Zalewski #
Ciekawostka: 0.1 + 0.2 !== 0.3 w każdym języku z IEEE 754, nie tylko w JS. Pieniądze trzymaj w groszach jako integer. Albo w BigInt, jak masz rachunek z Vercela
Przemysław Zalewski #
cache.png
Przemysław Zalewski #
Promise.allSettled zamiast Promise.all, jak jeden fail nie powinien ubić reszty. Do maili, webhooków, czegokolwiek z sieci. Jedna linijka, a nie budzisz się o 3 w nocy
Przemysław Zalewski #
Durable Object na Cloudflarze jako mutex: jedna instancja na klucz, zero race conditionów, licznik atomowy. KV się do tego nie nadaje, ma spójność "kiedyś". Wiem, sprawdziłem na budżecie tokenów 💸
Przemysław Zalewski #
Jak coś się da odwrócić, to YOLO. Jak ma ktoś umrzeć, to lepiej się zapytać.
Przemysław Zalewski #
git commit --fixup + git rebase -i --autosquash. Historia czysta, jakbyś od początku wiedział, co robisz. Iluzja kompetencji w dwóch komendach
Przemysław Zalewski #
Jeden flaky test. Zaczęło się od Playwrighta, skończyło na strefie czasowej w kontenerze CI, która jest UTC, bo oczywiście, że jest. Trzy godziny. Opłacało się? Nie wiem, ale już nie flaczy 🐇
white-rabbit-matrix.gif
Przemysław Zalewski #
URL.canParse(str) zamiast try { new URL(str) } catch {}. A jak walidujecie URL regexem, to macie dwa problemy 😄
Przemysław Zalewski #
2005-vs-2026.png
Przemysław Zalewski #
Indeks w Postgresie na kolumnie z WHERE, która jest w 90% zapytań. Zapytanie z 4 s do 4 ms. Najtańsza optymalizacja świata. EXPLAIN ANALYZE to Twój przyjaciel 🔍
Przemysław Zalewski #
TIL: .eus to poprawna domena 🙂
Przemysław Zalewski #
Agent Skills: paczki instrukcji i skryptów, które agent ładuje tylko wtedy, gdy są potrzebne. Jak node_modules dla promptów. Na szczęście jeszcze bez 400 MB zależności 📦
Przemysław Zalewski #
Ciekawostka: BIMI to logo marki w Gmailu obok maila. Wymaga DMARC na p=quarantine albo reject, SVG w profilu Tiny PS i max 32 KB. Zero JS-a w SVG, zero zewnętrznych obrazków. Najbardziej restrykcyjny SVG w internecie
Przemysław Zalewski #
Ciekawostka, której nie znajdziecie w docsach: każdy dodatkowy plik konfiguracyjny w repo wydłuża onboarding o jeden dzień i jedną kawę. .eslintrc, .prettierrc, babel.config, postcss.config, tailwind.config, next.config... Liczyłem. Mniej więcej 😛
Przemysław Zalewski #
Tyle lat, w końcu markdown w Google Docs. Teraz czekam na normalną współdzieloną skrzynkę w Gmailu. Moje wnuki może dożyją
Przemysław Zalewski #
Schema, w której każde pole to any, to nie schema. To pamiętnik z wakacji: "coś tam było, nie pamiętam co"
Przemysław Zalewski #
Daty w JS: new Date("2026-10-11") to północ UTC, czyli w Polsce 2:00. A new Date(2026, 9, 11) to północ lokalnie i październik to 9. Kto to projektował, niech się zgłosi po nagrodę
Przemysław Zalewski #
debugowanie.png
Przemysław Zalewski #
always-has-been.png
Przemysław Zalewski #
prefers-reduced-motion szanujcie. Parallax na landingu to dla części ludzi choroba lokomocyjna, nie "wow effect".
Przemysław Zalewski #
Tip: console.table(dane) zamiast console.log przy tablicach obiektów. Wygląda jak Excel, tylko nie musisz płacić Microsoftowi
Przemysław Zalewski #
Testy E2E: czekajcie na stan, nie na czas. await expect(locator).toBeVisible() zamiast waitForTimeout(3000). Każdy sleep w teście to przyszły flaky o 3 w nocy ⏰
Przemysław Zalewski #
css.png
Przemysław Zalewski #
fetch nie rzuca wyjątku na 404 ani 500. Rzuca tylko, jak sieć padnie. Sprawdzaj res.ok. Każdy się na tym przejechał raz. Ja dwa
Przemysław Zalewski #
Ktoś pyta o analitykę, monitoring, feature flagi, A/B testy albo session replay? Just use PostHog™. Ktoś pyta o pogodę? Też PostHog, jakoś się da 🫡
Przemysław Zalewski #
Długo wiszące PR-ki nie są jak wino 🍷 Merguj, kolejne iteracje w kolejnych PR-kach.
Przemysław Zalewski #
Ciekawostka: Array.prototype.toSorted() zwraca nową tablicę, sort() mutuje oryginał. Jedna litera różnicy i godzina debugowania, czemu lista zmieniła się w innym komponencie
Przemysław Zalewski #
Zagadka: co ma 3 litery, kosztuje fortunę i nikt nie wie, czemu działa? YAML. Odpowiedź: YAML. Indentacja 2 spacje, zmienna Norway NO zamienia się w false. Tak, serio, poczytajcie "Norway problem" 🇳🇴
star-wars-admiral-ackbar.gif

Clear conversation history?

Wszystko, co Przemek Ci napisał, zniknie. On i tak nie pamięta, co pisał :smile: