12 sierpnia 2026 roku nad Hiszpanią nastąpiło całkowite zaćmienie Słońca. 24 lipca eclipseando.com nie istniało: ani domeny, ani projektu, ani linijki kodu. Dziewiętnaście dni później strona była opublikowana, z osobną stroną dla każdej gminy w Hiszpanii, sklepem przyjmującym płatności przez Stripe i łańcuchem logistycznym składającym zamówienia u czterech różnych dostawców. Opisujemy to tutaj, bo ten projekt najlepiej pokazuje, jak pracujemy, gdy zlecenie brzmi „strona i backend od zera”, a każdy element działa produkcyjnie i można go odwiedzić.
Kluczowa myśl: strona e-commerce to nie szablon z przyciskiem płatności. To front, kasa, magazyn danych i interfejsy z tym, kto produkuje, i z tym, kto wysyła. W eclipseando.com te cztery warstwy napisaliśmy sami, a każda jest sprawdzona testami uruchamianymi przed publikacją.
Zlecenie: strona z datą ważności
Projekt był nasz, nie klienta, co czyni go uczciwszym przykładem: nie było budżetu do rozciągania ani negocjowalnego terminu. Datę wyznaczało niebo. Wymagania wynikły z wcześniejszego researchu i były konkretne: odpowiedzieć na pytanie „o której godzinie i ile zobaczę z mojej miejscowości?” dla dowolnej gminy w Hiszpanii, sprzedawać certyfikowane okulary i pamiątki personalizowane dla gmin, a to wszystko także po katalońsku, angielsku, niemiecku, francusku, włosku i portugalsku, bo część odbiorców przyjeżdżała z zagranicy.
Shopify i WooCommerce odrzuciliśmy jeszcze przed startem. Nie ze względu na cenę, tylko dlatego, że trudna część projektu nie leżała w sklepie: to były 8 132 obliczane strony, mapa, prognoza zachmurzenia i integracje logistyczne, których żadna platforma nie ma w standardzie. Gdy wartość tkwi w tym, czego nie ma w standardzie, platforma przeszkadza bardziej, niż pomaga. To samo kryterium stosujemy, gdy klient pyta, czy zrobić stronę na Odoo Website, czy osobno.
Co zbudowano, element po elemencie
| Element | Co robi | Z czego jest zrobiony |
|---|---|---|
| Front | 8 132 strony gmin, mapa, wyszukiwarka, sklep i blog, w siedmiu językach z osobnym adresem URL dla każdego języka. | Statyczna strona generowana w Astro; serwowana przez nginx na własnym serwerze. |
| API | Koszyk, checkout, dostarczanie zestawu cyfrowego, zamówienia u dostawców, śledzenie przesyłek, newsletter, zachmurzenie dla gmin, analityka bez cookies i panel zarządzania. | FastAPI w Pythonie, stan w SQLite, 1 370 testów automatycznych. |
| Płatności | Stripe Checkout z podpisanym webhookiem; cena jest zawsze liczona na serwerze, nigdy w przeglądarce. | API Stripe; język bramki płatniczej zależy od sklepu, z którego kupuje klient. |
| Logistyka | Czterej dostawcy: dwóch z API, jeden z API dropshippingowym i jeden bez API, któremu zamówienie przekazuje się e-mailem i plikiem CSV. | Własne integracje, odczyt skrzynki przewoźnika i powiadomienia dla kupującego. |
| Zadania zaplanowane | Siedem timerów: skrzynka, kolejki, ponowienia, zachmurzenie, terminy drukarni i raport o niebie. | Jednostki systemd na tym samym serwerze. |
Front: 8 132 strony, które się oblicza, a nie pisze
Każda gmina w Hiszpanii ma swoją stronę z godziną początku, maksimum i końca, procentem przesłonięcia oraz, w pasie całkowitego zaćmienia, liczbą sekund ciemności. Tych danych nikt nie wpisywał: są obliczane w momencie generowania strony na podstawie elementów zaćmienia i współrzędnych każdej gminy, a test porównuje próbkę wyników z danymi publikowanymi przez Hiszpański Instytut Geograficzny. Jeśli obliczenia się rozjadą, strona nie zostanie opublikowana. Poza Hiszpanią są indeksy dla Portugalii, Francji, Włoch, Niemiec, Irlandii, Islandii, Grenlandii, Maroka, Holandii i Wielkiej Brytanii.
Wielojęzyczność jest prawdziwa, a nie nałożonym automatycznym tłumaczeniem: każdy język ma własną ścieżkę (/ca/, /en/, /de/…), własne teksty i własne strony sklepu, a testy sprawdzają, że siedem wersji każdego szablonu istnieje i linkuje do siebie nawzajem. To ta sama zasada, którą stosujemy w flexigotech.com i pernocta.eu.
Backend: małe API, które pełni rolę kasy, magazynu i lady
Całą statykę serwuje nginx. Dynamika podpina się pod /api/* i jest aplikacją FastAPI ze stanem w SQLite. Brzmi skromnie i tak ma być: utrzymuje to jedna osoba, działa na serwerze za kilka euro i wytrzymało szczyt w dniu zaćmienia bez żadnych zmian. Ważne decyzje są w środku:
- Koszyk jest wyceniany na serwerze. Przeglądarka przechowuje pozycje, ale każda cena jest przeliczana na nowo względem aktualnego katalogu przy tworzeniu sesji płatności. Inaczej każdy otworzy konsolę i kupi bluzę za jedno euro.
- Webhook Stripe rozstrzyga. Płatność uznaje się za pobraną, gdy Stripe potwierdzi ją z zweryfikowanym podpisem, a nie wtedy, gdy przeglądarka wróci na stronę z podziękowaniem. Jeśli po pobraniu płatności zamówienie u dostawcy się nie powiedzie, API zwraca błąd, żeby Stripe ponowił próbę, a tabela z identyfikatorem sesji zapobiega wyprodukowaniu zamówienia dwa razy.
- Produkt cyfrowy jest dostarczany podpisanym linkiem (HMAC, wygasa po 72 godzinach, najwyżej pięć pobrań), a pole rezygnacji z prawa odstąpienia od umowy jest wymagane przed pobraniem płatności: API odrzuca checkout zestawu, jeśli nie jest zaznaczone.
- E-maile się nie gubią. Każde potwierdzenie wychodzi przez Brevo; jeśli Brevo nie odpowiada, trafia do kolejki w SQLite, którą timer opróżnia co piętnaście minut. Kupujący bez e-maila z potwierdzeniem to reklamacja, więc ta reguła nie ma wyjątków.
Interfejsy logistyczne: czterej dostawcy, cztery sposoby komunikacji
To część, która najbardziej przypomina to, o co proszą nas klienci. Sklep sprzedawał rzeczy wysyłane z różnych miejsc, a każde miejsce komunikowało się po swojemu:
- Drukarnia z API i webhookiem. Po pobraniu płatności API generuje plik do druku (szablon SVG z nazwą gminy, godziną i czasem trwania, rasteryzowany w 300 dpi), tworzy zamówienie i czeka na webhook „wysłano”, by przekazać kupującemu numer śledzenia.
- Druga drukarnia z zakładem w Barcelonie do odzieży, bo pierwsza nie produkowała ubrań w Hiszpanii i termin się nie mieścił. Przed decyzją zmierzono obie API na prawdziwych zamówieniach; kubek został u pierwszej, bo ten produkt powstawał na miejscu.
- Producent okularów z API dropshippingowym, który wysyła do Hiszpanii, Francji, Niemiec, Wielkiej Brytanii i Portugalii. Zamówienie tworzy się samo po pobraniu płatności, a przed pobraniem sprawdza się jego rzeczywistą dostępność w danym kraju.
- Dystrybutor bez API. Wysyła okulary w 24-48 godzin na Półwyspie i Balearach, ale zamówienie przekazuje się mu e-mailem. Panel jednym kliknięciem generuje dokładnie to, czego potrzebuje: odbiorcę, adres, telefon, artykuł i ilość, jako tekst i jako załączony plik CSV. A ponieważ jego przesyłki jadą z GLS, API co dziesięć minut czyta skrzynkę, klasyfikuje e-maile przewoźnika (w drodze, w punkcie odbioru z terminem, nieobecny odbiorca) i powiadamia kupującego o każdym z nich.
Konsekwencja, która wygląda na drobną, a taka nie jest: zamówienie z okularami i koszulką to dwie paczki od dwóch dostawców. Dlatego śledzenie działa na poziomie przesyłki, a nie zamówienia, z jednym wierszem dla każdej pary zamówienie-dostawca. Jedno pole „numer śledzenia” działałoby do pierwszego klienta, który kupiłby obie rzeczy.
Terminy się mierzy, a nie obiecuje
API wyceny drukarni odpowiadało „dostawa standardowa, 5-10 dni” na wszystko, także na produkty, które potem odrzucało przy prawdziwym zamówieniu. Odkryliśmy to przy sprzedaży, której nie dało się zrealizować. Od tamtej pory timer co noc tworzy zamówienie robocze dla każdej kombinacji produktu i kraju, odczytuje przewoźnika i rzeczywistą liczbę dni zwracaną przez drukarnię, a następnie je usuwa. To te liczby, a nie te z dokumentacji, widzi kupujący na karcie produktu przed zapłatą. To ta sama lekcja, którą stosujemy w konektorach Odoo: zielony test na mocku niczego nie dowodzi; trzeba mierzyć na prawdziwym systemie.
Co działa samo
Siedem jednostek systemd robi to, co w małym sklepie zwykle robi ktoś ręcznie: czyta skrzynkę przewoźnika co dziesięć minut, opróżnia kolejki e-maili i ponawia opłacone zamówienia, które nie trafiły do produkcji, co piętnaście minut, co trzy godziny odświeża prognozę zachmurzenia z AEMET dla najczęściej odwiedzanych gmin i codziennie mierzy terminy drukarni. Żadna z nich nie wywołuje zewnętrznej usługi w ścieżce żądania webowego: strony czytają z cache, a test to gwarantuje.
Co z tego przyda się w Twoim sklepie
Prawie wszystko, po zamianie zaćmienia na Twój katalog. Kiedy klient mówi „chcę stronę e-commerce od zera”, prosi dokładnie o tę listę: szybki, wielojęzyczny front, kasę, której nie da się oszukać, integracje z tym, kto produkuje, i z tym, kto wysyła, śledzenie, które dociera do klienta bez ręcznego przepisywania, oraz zadania działające same. Gdy klient ma już Odoo, to API zastępuje sam ERP, a integracje stają się konektorami przewoźników w Odoo; gdy nie ma, albo jego biznes nie mieści się w ERP, buduje się to tak jak tutaj.
Najczęstsze pytania
Dlaczego nie zrobiono tego na Shopify lub WooCommerce?
Bo trudne nie było samo sklep, tylko to, co go otaczało: 8 132 obliczane strony, własna mapa, prognoza pogody i cztery różne integracje logistyczne. Gdy wartość tkwi w tym, czego platforma nie dostarcza, platforma jest kosztem stałym, który na dodatek ogranicza. Sam sklep, ze Stripe Checkout, był niewielką częścią pracy.
Jak zintegrować dostawcę, który nie ma API?
Sprowadzając pracę człowieka do jednego kliknięcia i automatyzując to, co dociera kanałem możliwym do odczytu. W eclipseando.com zamówienie dla dystrybutora okularów wychodzi z panelu jako tekst i CSV gotowe do wklejenia do e-maila, a powiadomienia przewoźnika są odczytywane ze skrzynki co dziesięć minut i zamieniane na statusy oraz e-maile do kupującego.
Czy to samo da się zrobić na Odoo?
Tak, i jest to normalne, gdy klient ma już ERP: front łączy się z Odoo, koszyk i zamówienie żyją w sprzedaży, a przewoźnicy wchodzą przez konektory opublikowane w App Store. Buduje się osobno, gdy nie ma Odoo albo gdy sednem biznesu, jak tutaj, nie jest katalog, tylko obliczenie.
Przydatne linki w FlexigoTech
Co robimy w tym zakresie
Potrzebujesz strony lub sklepu zbudowanego od zera, z podłączoną logistyką?
Napisz, co sprzedajesz, kto to produkuje i kto wysyła. Powiemy Ci, co się buduje, co integruje się przez API, a czego programować w ogóle nie trzeba. Napisz na comercial@flexigobe.com lub zadzwoń pod numer +34 616 809 504.

