Alpha. This is an experiment, and installing a node makes you part of it. Things will break; some will surprise you. Tell us what happened, what helped and what did not: info@fab.city

PLANETAI · how the node works

Observe here.
Decide here.
Act here.

PLANETAI is hyperlocal awareness for climate and local challenges, built on distributed design and production and on open-source principles. A node connects everything that measures one place, from a particle sensor to a satellite, into a picture sharp enough to act on at the scale of a house, a street, a city, and passes upward what the models of a bioregion and a planet cannot see from above. This page is the reasoning behind that, and what has been built so far.

$ curl -fsSL planetai.fab.city/install | bash
Never run a server? Start here

The first instrument

Bali first, because the sensor was already there

Node #1 runs in Kuta Selatan and measures particulates. Air is not the mission. A Smart Citizen kit was already on the wall, the public reference network already published, and people there face the same question every morning: is the room better than the street. That made it the cheapest way to test what we actually wanted to know. Can an observation become an action at one address, and can we measure whether it did. Barcelona, Boston and Santiago are the other pilot sites, each with its own sensors, its own portals and its own numbers.

Nothing about air lives in the node’s code. It is a pack: three rules, three index cells, no Python, and a README that says where each threshold came from. The next domain is a folder. The next scale is an adapter.

bayu-22 Sep 2026
PLANETAI · 05:19

Indoor PM2.5 at Bayu 2 (indoor) is 42 µg/m³. Outside is worse right now (~68 from 4 nearby public sensors). Keep the windows shut and run the purifier if you have one.

#2
closed them · acted

English and Bahasa Indonesia sit in the same rules file. The reply matters more than the alert, because it is how the network finds out whether anything happened.

One number nobody had

ρ, and how long an observation takes to become an action

The Fab City Index measures a place as DIDO × (1 − PITO) × ρ. Two generations of it had no way to measure ρ, so they assumed it was 1: observation always becomes action. Node #1’s first hour says 0.33. Three alerts worth acting on, one acted on, median three minutes.

The Index’s registry lists 32 datasets across its twenty cells. Governance at the community scale has none, because no dataset anywhere records whether people act on what they know about their own street. A node produces that number, in any domain, at any site. You cannot buy it from a sensor company or download it from a portal.

Community · City · Region · Bioregion · Planet. One shape at every scale.

The claims

Four claims about how a place should be measured.

Each one is checkable in the repository. Air is the first domain, not the subject.

01 · Distributed computation

The computer already exists

Every fab lab has a machine idle in a corner. Every household with a sensor already owns a computer. A node is about two thousand lines and two containers, and it runs on a Mac mini or an old laptop. Nobody has to buy infrastructure to join, which is why a network of hundreds is arithmetic rather than ambition. Compute attaches at both ends through the same three contracts: a phone posting readings and actions below, a lab cluster or a partner’s HPC above. Where the thinking happens is a deployment choice.

02 · Local intelligence

The decision is made where it lands

A node runs its own rules against its own data on its own machine. No round trip, no account, no dependency on someone else’s uptime. When the internet drops, a sensor on the LAN keeps reporting and the rules keep firing. Intelligence here is small and situated: SQL that knows this building, and one day a model that knows this valley. It is not a general mind in a data centre renting attention back to you.

03 · Observation to action

A reading that changes nothing is decoration

Most civic sensing stops at the dashboard, and a dashboard is where a good measurement goes to be admired. What a node produces is a message to someone who can act on it, in their language, with a cooldown so it stays worth reading. Then it records whether they did. That record is both the product and the instrument.

04 · Sovereign data

Sovereignty is a data path, not a policy

Raw readings never leave the machine that recorded them. What moves up is hourly means, index cells carrying their own provenance, and, when a model is worth training, weight updates rather than rows. Peer observatories are read as sources and credited, not absorbed. Nothing here needs a cloud provider to work, so owning your data is something you can check in the code instead of a line in a policy.

The building

Three layers, none of which knows what a metric means.

Three layers closing on the Fab City Index, and none of them knows what a metric means. The same shape works at a house, a district, a province, a bioregion. The core moves numbers and evaluates SQL. A pack decides what a number means.

01

Sense

Anything that emits a number with a time and a place: your hardware, other people’s networks, open data portals, Earth models, people. A reading is (ts, sensor_id, metric, value) and the core never asks what the metric means. A new source is one function.

02

Observe

Postgres on the node. Hourly means. Every node exposes the same read API, so the observatory is a client rather than a master. Indoor flagged, stale dropped, raw kept beside corrected, gaps left as gaps.

03

Act

Rules are SQL over the node’s own data. When one is true, one message goes to the people at the address in their language. Agents draft, humans dispatch. Detect, decide, act, measure, and every step carries a timestamp.

04

Index

Packs declare which cell their SQL feeds. The core evaluates it and polices the provenance: live, partial or mock, never upgraded on the way up, and no live claim before the data supports it. Governance is filled at every node whatever it measures, because ρ comes from the ledger.

sensor ──▶ node ──▶ rules ──▶ a message ──▶ a person ──▶ an action ──┐ │ │ └── hourly means ──▶ district ──▶ region ──▶ Fab City Index ◀──┘ ρ ▲ │ phone, DIY pod, lab cluster ────────────────────┘ raw never leaves the node

Node #1 · bayu-2

Live.

This is the proof, not the product. It runs at Fab Lab Bali on a Mac that was already in the room, reading a kit that was already on the wall. Nothing was bought. Two containers, about two thousand lines, two minutes from the install line to a running node, and a first message on a phone within the hour.

StatusPolling every 5 minutes
PlaceKuta Selatan, Badung, Bali · −8.827, 115.157 · Community scale
DomainsAir, heat, coast, land, place (the neighbourhood from OpenStreetMap and Open Buildings, in PostGIS), open-data health, and a daily insight digest: nine packs. The core is domain-blind.
SensorThree Smart Citizen kits indoors and one on the wall outside; a Meshtastic gateway with a BME680; PM, temperature, humidity, pressure, gas. From the map and from orbit: 2,904 buildings on OpenStreetMap, 7,219 in Google Open Buildings, 37 mapped uses within a kilometre
ReferenceBali Air Dispatch public API: the three nearest outdoor stations, stale and indoor rows excluded; above them Copernicus CAMS, Open-Meteo weather and marine, Earth Engine land cover
HardwareApple Silicon Mac · Postgres + one Python service
First alert05:19 UTC, 2 Sep 2026
IndexEnvironmental|Community for Bali, the first non-mock reading that cell has had
OperatorMeaningful Design Group with Fab Lab Bali

Why this case first

A domain earns the first slot by being cheap to test and worth getting right. Air in Bali is both. The public reference network already exists, the sensor was already installed, and the decision people face every morning, whether to open the windows or keep them shut, was one nobody was answering.

It also surfaced the constraint that matters, and it is not technical. Every AirGradient deployed in Bali in 2025 went silent within the year. Sensing networks die of neglect. What is worth building is not the reading but the person whose job is keeping the instrument alive and the message right. A fab lab network is the only kind of organisation shaped to do that at a thousand addresses, because it can print the enclosure locally, install locally, maintain locally, and teach it in Fab Academy.

Smart CitizenAirGradientPurpleAirDIY sensor over MQTT · nextOpenAQ · next
2

Containers

Postgres and one Python service. Nothing else.

~700

Lines of code

Cut from 1,479 and twelve containers on the day it was written.

4 of 20

Index cells a node fills

Two Environmental, two Governance. Nine more have a registered source and need an adapter; seven have no source at all.

0

Clouds required

Runs on hardware you control. The chat app is the one outside dependency, and it's a function.

Four pillars × five scales = twenty cells

Twenty cells, from an address to the planet.

The Fab City Index measures a place from the address up to the planet. A node is not a Community-scale sensor box that reports upward. It ingests at whichever scale the question lives, using three classes of source. Same core, same contracts, a different kind of number.

sensor

Community

A device on your LAN, or a public one nearby. Minutes. Smart Citizen, AirGradient, PurpleAir ship. This is the only class that involves hardware.

portal

City & Region

Open data and statistical APIs. Days to months. One CKAN adapter reads Barcelona’s, Boston’s, Santiago’s and Bali’s portals, which is four of the Index’s own sources from one function.

model

Bioregion & Planet

A global model sampled at your coordinates. Open-Meteo ships: free, key-free, anywhere on earth. Boundary conditions, published downward, never rolled up into a cell.

survey

The missing class

People answering. Four of the five Social cells are empty across the whole registry and no sensor fills them. This is the adapter nobody has written.

What that looks like across the four pilot sites. Different sensors, different portals, the same node:

Barcelona Smart Citizen kits · Open Data BCN (CKAN) · Generalitat dades obertes · Metroverse · TED procurement Boston a lab's own machines · Analyze Boston (CKAN) · MassGIS · Metroverse · Flood Hub Santiago low-cost PM · datos.gob.cl (CKAN) · LAKLEMS · ChileCompra · Caravan hydrology Bali Smart Citizen 19880 · Bali Satu Data (CKAN) · Asian KLEMS · LKPP procurement · Open-Meteo │ │ │ sensor portal model

And the state of the matrix, counted from the Index’s own registry rather than from ambition:

filled by a node today

4 cells

Environmental|Community live from your sensors · Environmental|City partial from public reference · Governance|City from portal maintenance · Governance|Community from ρ.

have a source, need an adapter

9 cells

Procurement feeds, statistical APIs, hydrology and biodiversity datasets, economic complexity. Registered, documented, unwired. Socrata and ArcGIS adapters are the cheapest next gain.

no source at all

7 cells

Four of them are Social. One is Economic|City, arguably the Fab City question, and a lab’s own machine log is the closest thing anyone has to it. One is Governance|Community, which is why ρ matters.

A node at one address fills two cells well and contributes to two more. Nobody should call that a planetary observatory. It is the smallest working piece of one, with the ingestion classes for the other scales already present and one adapter each to prove they run. The full matrix →

What a node can measure

The core knows about readings, not about air.

A reading is a time, a source, a metric name and a number, whether it came from a sensor on your wall, a city’s API or a global model. Everything that depends on the domain lives in a pack: what counts as bad, what someone should do about it, which index cell it feeds. Nine ship: air, heat, insight, cold-start, open-data health, coast, earth-engine, place and a worked example. The rest are sketches with the metric names already proposed, waiting for whoever has the problem.

Live · packs/air-quality

Air

pm25 pm10 temp humidity

Is this room better or worse than the street? Ventilate, or keep it shut. Feeds Environmental|Community and |City. Running at node #1.

Live · packs/open-data-health

Open data

datasets_total datasets_fresh_90d

How much of a city's published data was touched in 90 days. A portal nobody updates is an archive, not open data. Feeds Governance|City for any CKAN portal.

Designed

Water

turbidity tds ph water_level rainfall

Is the spring safe this week? Will the tank run dry before the rain? Should the subak divert? A $30 probe on an ESP32 and a rule.

Designed

Energy

power_w energy_kwh grid_up solar_w

Run the kiln now or in two hours? Is the lab about to trip its supply? Did last night's outage reach the fridge? Feeds Economic.

Designed

Fabrication

machine_hours jobs_completed material_kg

Which machine is the bottleneck? Is this lab producing more than it imports? The one domain that speaks directly to PITO → DIDO.

Designed

Noise & mobility

noise_db vehicle_count occupancy

Is the school street too loud to teach in at 8am? Did anything change after the intervention? The Smart Citizen kit already emits noise.

Designed

Comfort & soil

co2 tvoc_index soil_moisture ec

Ventilate the classroom before the CO₂ makes them sleepy. Irrigate or wait. AirGradient already emits the first two.

Designed means the schema takes it and the names are proposed. It does not mean anyone has built it. The first person to ship one gets to fix the names. DOMAINS.md has the full table and what each would need.

Open source · Apache 2.0

Two minutes, plus downloads.

If you can open a terminal and paste a line, you can run a node. The walkthrough was written against the first real install and fixed for every failure it hit: lost exec bits, a port clash with another container, a Docker builder quirk.

# Mac · Linux (x86) · Windows (WSL2)
curl -fsSL planetai.fab.city/install | bash

# it asks four things:
1. A short name for this node        bayu-2
2. Where is it?                       Kuta Selatan  →  -8.80, 115.18 · Asia/Makassar
3. What is this node for?           a home · a business · a lab · a district
4. Do you have a sensor?             Smart Citizen kit 19880, or your username for every kit on the account

# then, two minutes each
planetai telegram          # alerts on your phone; finds your chat id itself
planetai test-alert        # one fires now, so you see the whole path
/act 3  (on Telegram)      # you did the thing. that is the first rho. Or the button on the dashboard.
Ubuntu 22.04+ / Debian 11+Arch · OmarchymacOS 13.0+ · Apple SiliconmacOS 13.5+ · IntelWindows 10 22H2+ · WSL2older Mac → Linux, on the same laptop

Step 1 · the check

Nothing starts until it can

One table before any question: system, architecture, memory, disk, container runtime, network, ports. Every cross carries the one line that fixes it on that machine. A machine no runtime can be installed on is told so in a sentence, and nothing is downloaded. Run it on its own first: curl -fsSL planetai.fab.city/preflight | bash

Step 2 · four questions

Detected, not configured

A name. A place, typed as words: coordinates, time zone, city and which outdoor reference applies are looked up. What the node is for. A sensor, or none. The answers are written down before anything heavy runs, so a second run offers them back instead of asking again. Safe to run twice.

Step 3 · the loop

See it fire, then close the loop

planetai test-alert makes one fire now. planetai act records that you did something about it. That is your first ρ.

Core, official, community

Everything local lives in a folder.

A pack is a folder that adds a rule, an index cell, or a sensor. It is how a domain arrives, and how a place tunes one. What counts as bad in Kerobokan is not what counts as bad in Poblenou, and the sentence that gets someone to act is different in every language and every building. The air pack is official and shipped. It is also just a folder you can copy. Most useful packs contain no code at all.

Core

fabcity/planetai-node

maintainers · tagged releases

The runtime, the adapters, two domain-blind rules, the three contracts. Knows nothing about any domain. Full review; must not add a container or a cloud dependency.

  • semver, additive schema only
  • a node updates in place
  • deferred pieces carry a written trigger

Official packs

fabcity/planetai-packs

maintainers · optional at install

Whole domains, reviewed like core but optional at install. air-quality is the first and the template. Water and energy are the obvious next two.

  • same review bar as core
  • versioned independently
  • declares the node version it needs

Community packs

your repo, listed in the marketplace

you · listed, not audited

A PR to the marketplace repo with a manifest and a link. We check the manifest parses, the licence is open, and the README says where the rule was learned. Verified means a maintainer read the code and ran it. Unverified is a normal state, not a warning.

  • data packs: rules and cells, no code
  • code packs: off until you set a flag
  • your version, your repo, your name

A pack is a folder

packs/air-quality/          # official: how node #1 works at all
  pack.yaml     # id, author, version, domain, requires
  rules.yml     # SQL + message. ids namespaced monsoon-bali/…
  cells.yml     # SQL → an fci-cells-v0 row for the Index
  adapter.py    # optional. code. off unless you opt in.

$ git clone …/planetai-pack-water packs/water
$ docker compose restart app
$ curl -s localhost:8080/packs

Data before code

Rules and cells are YAML and SQL. They can't reach the network, they run against the node's own database, and anyone who knows their neighbourhood can write one. That is the contribution we want most, and it needs no trust in a stranger's Python.

A pack that ships adapter.py is code, and code runs with the node’s privileges. Those do not load until the operator reads the file and sets PACKS_ALLOW_CODE=1. The node says so, by name, in the log. That bluntness is the security model at this scale. Dressing it up would be worse.

Write a pack

Zero community packs exist today. One worked example ships in the repo. The marketplace opens when there are three real packs to put in it, because an empty marketplace is worse than none.

Limits

What it isn't.

Notan air quality product. The core is domain-blind; air is a pack, and it happens to be the one that runs today.
Nota dashboard. If a message doesn't change a decision at the address, the node is decoration.
Nota cloud. Readings never leave the machine that recorded them. Hourly means, index cells and, later, model updates go up. Nothing else.
Notreference-grade. Low-cost sensors drift and disagree; the node stores raw beside corrected and says which it's showing.
Nota planetary observatory. Four of twenty cells, at one site. The architecture reaches further than the deployment does, and the gap is written down rather than smoothed over.
Notfinished. One node, one night. The next brick is the second address, or the second domain.

Node #2 is someone else's machine, or someone else's question

Run one.

If you have a sensor and a computer that stays on, you have a node, whatever you measure. If you have a lab, you have ten. Bring a domain nobody has written yet and you bring the more interesting half. Adding a node to the registry is a pull request.

$ curl -fsSL planetai.fab.city/install | bash
Read the walkthrough