Inspiration
Ireland has about 49,600 importers, and 98% of them are small or medium-sized (CSO, 2022). When a port is disrupted or the euro moves, a large company has a logistics team to deal with it. A small importer has an owner or an accountant, and they find out when the stock is already gone.
All the signals are public: trade statistics, ECB exchange rates, port news and weather. But nobody has put them together into a single answer a busy person can act on. We wanted one question answered in plain English: "Will my imports be late or dearer this month?"
What it does
In Time takes three inputs: a shipment route, the invoice currency, and how long your stock lasts. It returns:
- a one-line headline next to a route map
- three answers (stock, route, cost in euro), each with a status word, how sure we are, and a link to the source row
- one next step, such as "Check your forwarder's ETA today"
Accountants can keep several shipments on one page and re-check them all together. A container number links to the carrier's tracking page.
How we built it
It's a Python 3.12 standard-library server with a plain HTML/JS front end, so there is nothing to install.
- Sources: CSO and Eurostat Comext trade data, ECB reference rates, GDELT news per port, Met Éireann warnings, Open-Meteo port forecasts and public holidays. Every loader returns the same
SourceResult, with the licence, period,checked_atand a live/fallback mode. - Decision logic:
filter_eventskeeps only news that names a port on the user's route and a disruption.exposurethen compares stock with lead time:
$$\text{shortfall} = \max(0,\; L - S)$$
where $S$ is the days of stock and $L$ is the supplier lead time. Stock of 21 days against a 35-day lead time gives "You're 14 days short."
- FX: this is a separate card and never feeds the delay answer. For the share $u$ of the invoice not yet fixed, the euro cost change is roughly
$$\Delta \approx u\left(\frac{r_{\text{then}}}{r_{\text{now}}} - 1\right)$$
where $r$ is the ECB rate in foreign currency per euro.
- Fallbacks: if a live source fails, we use the stale cache and then the newest saved snapshot. The answer says which one it used, so a demo doesn't break.
- Tests: 100 offline tests run against saved real responses, and CI runs them plus osv-scanner on every pull request.
Challenges
- Saying "I don't know." News is a signal, not proof. A headline is only "reported" unless an official carrier or port notice confirms it. When we can't tell, the app says "We can't determine whether your shipment is affected", still shows any stock shortfall, and never says "No action needed". Tests enforce that wording.
- Rate limits. GDELT limits how often you can call it. We added a shared gate that allows one call every 5.5 seconds, a 30-minute background refresher for the main lanes, and cache or snapshot fallbacks.
- Licensing. We couldn't confirm the reuse terms for official carrier and port pages or for AISHub ship counts, so both features are built but switched off by default.
- Privacy. Nothing a user types is written to disk or logged, and cache keys hold only public source ids or a single port name. This is why "check every 30 minutes" only works while the tab is open.
- Fixed assumptions. Weather never changes the answer state, and holiday buffers are rules of thumb that we label as assumptions.
What we learned
- Showing where every number came from and how fresh it is builds more trust than a confident answer does.
- The most useful features were often the ones that limit the answer, such as route filtering and the "may" wording.
- Public open data is rich, but each source has its own licence, delay and failure mode, and the product has to handle all of them.
What's next
- Confirm the reuse terms for carrier and port pages and for AISHub, then turn those features on.
- Add more confirming sources and ports (we know 31 today).
- Send alerts that don't need the page open and don't store anyone's shipment.
- Test it with real importers and accountants.
In Time is a non-commercial showcase built on real public data. It is not financial advice.
Built With
- cso-pxstat
- css
- ecb-data-api
- eurostat-comext
- gdelt
- github-actions
- html
- javascript
- json
- make
- met-eireann
- open-data
- open-meteo
- osv-scanner
- python
- render
- rest-api
- unittest