Skip to main content
Case study · Web and ecommerce development

Case study: eclipseando.com, a website and ecommerce backend built from scratch in 19 days

Our own site with 8,132 municipality pages in seven languages, a Stripe-powered shop and four different logistics providers connected by API, by webhook or by email. How it was built, and what of it applies to your shop.

Interactive map on eclipseando.com with the totality band over Spain, the municipality search box and the switchable layers

On 12 August 2026 there was a total solar eclipse over Spain. On 24 July, eclipseando.com did not exist: no domain, no design, not a line of code. Nineteen days later the site was live with a page for every municipality in Spain, a shop charging through Stripe and a logistics chain placing orders with four different providers. We tell it here because it is the project that best shows how we work when the brief is “a website and a backend from scratch”, and because every piece is in production and can be visited.

Key idea: an ecommerce site is not a template with a pay button. It is the front end, the checkout, the data store and the interfaces with whoever manufactures and whoever ships. On eclipseando.com we wrote those four layers ourselves, and each one is covered by tests that run before every publish.

The brief: a website with an expiry date

The project was ours, not a client's, which makes it a more honest example: there was no budget to stretch and no negotiable deadline. The sky set the date. The requirements came from prior research and were concrete: answer “what time and how much will I see from my town?” for any municipality in Spain, sell certified glasses and municipality-personalised souvenirs, and do it in Catalan, English, German, French, Italian and Portuguese too, because part of the audience came from abroad.

We ruled out Shopify and WooCommerce before starting. Not on price, but because the hard part of the project was not the shop: it was the 8,132 computed pages, the map, the cloud forecast and logistics integrations no platform ships out of the box. When the value lies in what does not come out of the box, the platform gets in the way more than it helps. We apply the same criterion when a client asks whether to build their site on Odoo Website or separately.

What was built, piece by piece

PieceWhat it doesWhat it is built with
Front end8,132 municipality pages, map, search, shop and blog, in seven languages with a URL per language.Static site generated with Astro; served by nginx on our own server.
APIBasket, checkout, digital kit delivery, supplier orders, tracking, newsletter, cloud forecast per municipality, cookieless analytics and back-office panel.FastAPI in Python, state in SQLite, 1,370 automated tests.
PaymentStripe Checkout with a signed webhook; the price is always computed on the server, never in the browser.Stripe API; checkout language follows the shop the buyer came from.
LogisticsFour providers: two with an API, one with a dropshipping API and one without an API that receives the order by email and CSV.Own integrations, carrier mailbox reading and buyer notifications.
Scheduled jobsSeven timers: mailbox, queues, retries, clouds, printer lead times and the sky report.systemd units on the same server.

The front end: 8,132 pages that are computed, not written

Every municipality in Spain has its own page with the start time, the maximum, the end, the obscuration percentage and, inside the totality band, the seconds of darkness. Nobody typed that data: it is computed when the site is generated, from the eclipse elements and each municipality's coordinates, and a test checks a sample of results against those published by Spain's National Geographic Institute. If the computation drifts, the site does not get published. Besides Spain there are indexes for Portugal, France, Italy, Germany, Ireland, Iceland, Greenland, Morocco, the Netherlands and the United Kingdom.

The multilingual setup is real, not machine translation layered on top: each language has its own route (/ca/, /en/, /de/…), its own copy and its own shop pages, and tests check that all seven versions of every template exist and link to each other. It is the same rule we apply on flexigotech.com and on pernocta.eu.

The backend: a small API that acts as till, warehouse and counter

Everything static is served by nginx. Everything dynamic hangs off /api/* and is a FastAPI application with its state in SQLite. It sounds modest, and it is on purpose: one person maintains it, it runs on a server that costs a few euros and it took the eclipse-day peak without changing anything. The decisions that matter are inside:

  • The basket is priced on the server. The browser keeps the lines, but every price is recomputed against the current catalogue when the payment session is created. Otherwise anyone opens the console and buys a hoodie for one euro.
  • The Stripe webhook is the source of truth. A payment counts as collected when Stripe confirms it with a verified signature, not when the browser lands on the thank-you page. If the supplier order fails on payment, the API returns an error so Stripe retries, and a table keyed by session id prevents producing twice.
  • The digital product is delivered with a signed link (HMAC, expires after 72 hours, five downloads at most) and the withdrawal-waiver checkbox is required before charging: the API rejects the kit checkout if it is not ticked.
  • Emails are never lost. Every confirmation goes out through Brevo; if Brevo does not respond, it sits in a SQLite queue that a timer drains every fifteen minutes. A buyer without a confirmation email is a complaint, so that rule has no exceptions.

The logistics interfaces: four providers, four ways of talking

This is the part that most resembles what clients ask us for. The shop sold things that shipped from different places, and each place communicated in its own way:

  • A print shop with an API and a webhook. On payment, the API generates the print file (an SVG template with the municipality name, time and duration, rasterised at 300 dpi), creates the order and waits for the “shipped” webhook to send the buyer their tracking.
  • A second print shop with a plant in Barcelona for apparel, because the first did not produce garments in Spain and the lead time did not fit. Both APIs were measured with real orders before deciding; the mug stayed with the first because that one was produced here.
  • A glasses manufacturer with a dropshipping API shipping to Spain, France, Germany, the UK and Portugal. The order is created only on payment, and before charging its real per-country availability is checked.
  • A distributor with no API. It ships the glasses within 24-48 hours across mainland Spain and the Balearics, but the order has to be sent by email. The panel produces in one click exactly what it needs: recipient, address, phone, item and quantity, as text and as an attached CSV. And since its parcels go out with GLS, the API reads the mailbox every ten minutes, classifies the carrier's emails (on its way, at a pickup point with a deadline, recipient absent) and notifies the buyer of each one.

One consequence that looks small and is not: an order with glasses and a T-shirt means two parcels from two providers. That is why tracking lives per shipment and not per order, with one row per order-provider pair. A single “tracking number” field would have worked until the first customer who bought both.

Lead times are measured, not promised

The print shop's quote API answered “standard delivery, 5-10 days” for everything, including products it later rejected when actually ordered. We found out through a sale that could not be delivered. Since then a timer creates a draft order every night for every product-country combination, reads the carrier and the real days the printer returns, and deletes it. Those numbers, not the documentation's, are what the buyer sees on the product page before paying. It is the same lesson we apply to Odoo connectors: a green test against a mock proves nothing; you have to measure against the real system.

What runs on its own

Seven systemd units do what in a small shop is usually done by hand: read the carrier's mailbox every ten minutes, drain the email queues and retry paid-but-unproduced orders every fifteen, refresh AEMET's cloud forecast every three hours for the most-visited municipalities and measure the printer's lead times daily. None of them calls an external service in the path of a web request: pages read from cache, and a test guarantees it.

What of this applies to your shop

Almost all of it, swapping the eclipse for your catalogue. What a client asks for when they say “I want an ecommerce site from scratch” is exactly this list: a fast, multilingual front end, a checkout that cannot be tricked, integrations with whoever manufactures and whoever ships, tracking that reaches the customer without anyone copying it by hand, and jobs that run on their own. When the client already has Odoo, that API is replaced by the ERP itself and the integrations become carrier connectors inside Odoo; when they do not, or their business does not fit an ERP, it is built like this.

Frequently asked questions

Why was it not built on Shopify or WooCommerce?

Because the hard part was not the shop but what surrounded it: 8,132 computed pages, an own map, weather forecasts and four different logistics integrations. When the value lies in what the platform does not ship, the platform is a fixed cost that also constrains. The shop itself, with Stripe Checkout, was a small part of the work.

How do you integrate a provider that has no API?

By reducing the human work to one click and automating whatever does arrive through a readable channel. On eclipseando.com the order to the glasses distributor leaves the panel as text and CSV ready to paste into an email, and the carrier's notices are read from the mailbox every ten minutes and turned into statuses and emails to the buyer.

Can the same be done on Odoo?

Yes, and it is the usual choice when the client already has the ERP: the front end connects to Odoo, the basket and order live in Sales, and carriers come in through connectors published on the App Store. It is built separately when there is no Odoo or when the core of the business, as here, is not a catalogue but a computation.

Useful links inside FlexigoTech

Custom developmentWebsites, backends and Odoo modules programmed from scratchWeb development: our projects in productioneclipseando.com, pernocta.eu and clentic.comLogistics integration in OdooCarriers, labels and tracking inside the ERPBuilding an ecommerce site from scratch with logistics integrationThe five layers and the order they are built in

Need a website or a shop built from scratch, with its logistics connected?

Tell us what you sell, who makes it and who ships it. We will tell you what gets built, what is integrated by API and what does not need programming at all. Email comercial@flexigobe.com or call +34 616 809 504.

Talk to an engineer