All posts

Building a Digital Twin of Val d'Aran

Published Aug 7, 20266 min read
  • Engineering
  • Mountain
  • GIS

Key takeaways

  • aran-twin pulls together several of the studio's other projects — Guidaran, a self-hosted Open-Meteo instance — as live data sources for a single geospatial model of Val d'Aran.
  • Every external data source (ICGC, INE, Catastro, OSM, Lauegi) is at a different stage of readiness, and the project's own rules forbid inventing placeholder data to paper over the gaps.
  • The Gaussian-splat drone pipeline — ephemeral GPU, COLMAP, splat training, CDN delivery — is fully built but has no real captures to render yet.

Val d'Aran is the reason Maladeta Studio exists where it exists. Most of what we build for other people lives somewhere else — a booking flow for a resort, a translation layer for a museum, a communications engine quietly routing messages behind the scenes. aran-twin is the first project where we're building a model of the place itself: a geospatial digital twin of the valley, combining 3D terrain, municipal and environmental data, avalanche exposure zones, trail intelligence, live weather, and — the part I'm most excited about — Gaussian-splat 3D reconstructions from our own drone captures.

I'm writing about it now, about six weeks into its git history, instead of waiting for a polished launch. Partly because the architecture is worth documenting while it's fresh, and partly because I think there's more value in showing what a young, ambitious data project actually looks like than in pretending it arrived finished. A lot of aran-twin today is real, working infrastructure pointed at data sources that aren't fully connected yet. That's not a failure state — that's just what week six looks like.

1. A valley made of many other projects

aran-twin's job is to answer one question well: what is happening, right now, in this specific place? "This place" is defined precisely — a bounding box around Val d'Aran, centered near Vielha, covering the valley's nine municipalities: Arres, Bausen, Bossòst, Canejan, Es Bòrdes, Les, Naut Aran, Vielha e Mijaran, and Vilamòs.

What makes it satisfying to build is that it's a convergence point for things the studio was already doing. Guidaran, the tourism app I built before Maladeta Studio existed (I wrote about its origin in the "Founding Maladeta Studio" post), is now just another data source feeding the twin — trail and point-of-interest data flowing in through its own API instead of living in its own silo. The self-hosted Open-Meteo instance we run for weather is another. Neither integration required inventing anything new; they required treating a live app as infrastructure for a bigger one.

The rest of the pipeline is more conventional but no less real: a Python ETL layer pulls from ICGC (Catalunya's cartographic institute), INE (Spain's statistics institute), Catastro (the land registry), OpenStreetMap, and Lauegi (the region's avalanche bulletin service), and lands it all in PostGIS. From there it's served two ways — vector map tiles through Martin, and a Go API for anything that needs structured queries rather than tiles — both consumed by a React and MapLibre frontend. Drone footage runs through an entirely separate pipeline, ending up as Gaussian splats on a CDN:

ICGC ─────┐
INE ──────┤
Catastro ─┤      ┌─────────────┐      ┌───────────┐
OSM ──────┼─────▶│ Python ETL  │─────▶│  PostGIS  │
Lauegi ───┤      └─────────────┘      └─────┬─────┘
Guidaran ─┤                                  │
Weather ──┘                       ┌──────────┴──────────┐
                                   ▼                     ▼
                                Martin                Go API
                          (vector tiles)      (structured queries)
                                   └──────────┬──────────┘
                                              ▼
                                 React + MapLibre frontend

Drone footage ─▶ ephemeral GPU instance ─▶ COLMAP (SfM / camera pose)
                                                │
                                                ▼
                                  Gaussian-splat training
                                                │
                                                ▼
                                .spz / .ksplat model file
                                                │
                                                ▼
                        DigitalOcean Spaces (CDN) ─▶ frontend streams & renders

2. Uneven data, on purpose, not by accident

If you looked at aran-twin's source today expecting a clean, uniformly working system, you'd be disappointed — and that's worth saying plainly rather than dressing it up. Every external data source the twin depends on is at a different stage of being real:

  • ICGC municipal boundaries — live, working, with source attribution. The one piece you can point at right now.
  • INE population data — the adapter is written, but stays dormant until we have an approved export URL from INE itself.
  • Catastro parcel and building data — same shape of problem: the integration exists, but only activates once a validated municipality data package is in hand.
  • OpenStreetMap trails, roads, and POIs — OSM quality varies wildly by who last mapped a given trail, so this only turns on after a Geofabrik-based data-quality validation step passes.
  • Lauegi's avalanche data — the bulletin and zone information has real, working adapters today. The more granular accident and observation API is built but sits behind a service token we don't have yet.
  • Guidaran and the weather instance — both work today, via public API adapters, with attribution, because both are ours and were already live before aran-twin existed.

The project's contributor rules are explicit about this, and it might be the single best engineering decision baked into aran-twin so far: you're not allowed to invent placeholder values for real-world facts — credentials, official statistical codes, GPU instance identifiers, prices, data schemas. Unknowns get an explicit TODO convention instead of a plausible-looking fake. Where a real contract does exist — Guidaran's API, the weather instance's API — it's pinned and documented, not just assumed to keep working because it did last time we checked.

It would be easy to fake this. Population numbers in particular are the kind of thing you could plausibly hallucinate and nobody outside INE would immediately notice. The discipline is refusing to, even under the quiet pressure to make a demo look more finished than it is.

3. What a Gaussian splat actually is, and why we're waiting on drone footage

Gaussian splatting is the part of this project that made me want to write about it before it was ready. It's a relatively recent 3D reconstruction technique — the practical successor to photogrammetry — that represents a scene not as a textured mesh but as millions of tiny 3D "splats": soft blobs, each with its own position, color, opacity, and orientation. Rendered together, from any viewpoint, they produce something closer to a photograph than a 3D model, without the seams and geometry errors that used to give photogrammetry away.

For aran-twin, the intended pipeline is: drone footage of a specific area of the valley goes through ffmpeg for processing, then COLMAP for camera-pose estimation and structure-from-motion, then splat training itself, all running on an ephemeral GPU cloud instance — spun up on demand, billed only while running, torn down when it's done. The output is a splat model, in .spz or .ksplat format, uploaded to a CDN on DigitalOcean Spaces, where the frontend streams and renders it directly.

That pipeline exists today. What doesn't exist yet is a drone capture to feed it — as of this post, drone footage is listed internally as "unavailable pending licensed capture manifest," which is a precise way of saying we haven't done the actual, legally-covered flight yet. So there's no splat of the valley to show you. There's real infrastructure, tested and ready, aimed at footage that doesn't exist. I'd rather tell you that plainly than let a diagram imply otherwise.

4. Keeping the valley's own language on the map

Val d'Aran's nine municipalities — Arres, Bausen, Bossòst, Canejan, Es Bòrdes, Les, Naut Aran, Vielha e Mijaran, and Vilamòs — appear in the twin exactly like that: in Aranese, the valley's own Occitan variety, not translated into Spanish or Catalan for convenience. That's a deliberate rule, not an oversight, consistent with something the studio has cared about elsewhere, including tools we've built specifically around the Aranese language. A digital twin of the valley that renamed the valley's own places in someone else's language would be a strange kind of betrayal for a studio based here. It's a small detail in a codebase full of bigger unresolved problems, but it's one we got right on day one rather than promising to fix later.

aran-twin is, by its own git history, about six weeks old as I write this. Most of the visually exciting part — the splats — doesn't exist yet in any public form, and half the data layers are wired up to sources that haven't said yes yet. What does exist is a real pipeline, a real discipline about not faking what we don't have, and a real reason to keep going: this is the valley we work in, rendered honestly, one confirmed data source at a time.