Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

791 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Pango

Pango

Know what happened in every unit — and be able to prove it.

Raise a job against a door, cost it as the work happens, close it. Then settle move-out damage with an ingoing/outgoing inspection comparison instead of an argument.

For managing agents, landlords with a portfolio, body corporates and facilities teams. One static binary, one SQLite file. No cloud account, no subscription, no external service — and it keeps accepting work with no connection at all.

Version License: MIT OR Apache-2.0 Self-hostable Offline-first Go React

Quick start · Screenshots · How it works · Status · Docs

Pango — Swahili for the lease, and for the den it is held on.
Part of Vulos — rooted in vula, the Zulu and Xhosa word for open.


Pango — maintenance jobs, per-unit costing and condition inspections, self-hosted

What is Pango?

Maintenance and inspection software for people who look after property — managing agents, landlords with a portfolio, body corporates, facilities teams.

It runs as one binary and one SQLite file. A tablet, a laptop, an office NAS or a Raspberry Pi is a complete deployment. Copy the file, run it, done.

Two things it does that general ticketing tools do not:

Costs are per door, not per ticket. Every job belongs to a unit, and spend and labour aggregate per building and per unit. Units are real records with a normalised key, so Flat 3A, 3A and flat 3a are one door rather than three rows quietly fragmenting your reporting.

Inspections compare. Run an ingoing condition report at move-in and an outgoing one at move-out, and Pango diffs them item by item — what changed, in which direction, and what degraded. Damage liability becomes evidence rather than a disagreement.

Screenshots

Jobs board
Jobs board — triage across every building, filtered by unit, priority or assignee.
Job detail
Job detail — append-only costs and hours, and an event thread with a tenant-visible toggle per entry.
Move-out walkthrough
Move-out walkthrough — a condition scale per item, not a checkbox, with the ingoing record alongside.
Reports
Reports — created vs. closed over the month, then spend and hours per building and per unit.
Append-only cost and time ledgers
The ledger — materials, contractors and hours as separate entries. Nothing is edited; a correction is a new line.
Raise a job
Raise a job — against a building and a door. A unit that does not exist yet is created, normalised.
Inspections
Inspections — ingoing and outgoing pairs per unit, scheduled and tracked.
Building detail
Building detail — units on record with their normalised keys, and every job raised against them.
Buildings
Buildings — every property the organisation manages.
Settings
Settings — organisation, people, node identity and sync.

Eleven surfaces, each in light and dark — the full set is in docs/SCREENSHOTS.md. All captured from the compiled binary in demo mode by npm run screenshots; nothing is mocked up, and the script refuses to write a placeholder if the binary does not serve the app.

Quick start

git clone https://github.com/vul-os/pango && cd pango
npm install && npm run build          # build the app
bash scripts/build-embedded.sh        # compile it into the binary
./backend/pango --demo              # http://localhost:8099

Demo mode runs entirely in memory with a seeded portfolio — no database, no configuration, nothing written to disk. Sign in as demo@pango.local / demopassword.

For a real deployment:

./backend/pango --db /var/lib/pango/pango.db --addr 0.0.0.0:8099

The first account you register becomes the owner; registration then closes, and further accounts are created by an authenticated operator. See SELFHOST.md.

How it works

flowchart LR
  subgraph "One binary"
    API["Go API<br/><i>chi</i>"]
    DB[("SQLite<br/><i>+ oplog</i>")]
    UI["React app"]
    SITE["Docs &amp; landing"]
  end
  P2["Another site<br/><i>office · contractor</i>"]
  USB["Shared folder<br/><i>NAS · USB stick</i>"]
  UI --> API --> DB
  API <-->|"signed ops<br/>Ed25519"| P2
  API <-->|"ops-<node>.jsonl"| USB
Loading

The building is the authority. Whoever manages a building owns its jobs, its job numbering and its inspections. Because the only contended decision — who does the work — has exactly one legitimate writer, there is no consensus protocol, no leader election and no distributed lock anywhere in the system.

Money and hours are append-only. A job's cost is SUM over its ledger at read time, never a stored column. Two people costing the same job while offline therefore add rather than overwrite, and a correction is a negative entry, so the audit trail is complete by construction.

Peers are enrolled by hand. No discovery, no rendezvous, no hub. An operator enters another node's URL; requests are mutually signed with Ed25519. For sites with no connectivity, each node appends only its own ops-<node>.jsonl to a shared folder — so a NAS or a USB stick is a valid transport with no possibility of a write conflict.

Status

Honest per-area accounting. A feature that silently does nothing is worse than one that says it is not built.

Area State
Jobs — raise, triage, assign, cost, close Built
Buildings and units, unit normalisation Built
Append-only cost and time ledgers Built
Reports — per building, per unit Built
Inspections — condition capture, completion Built
Ingoing/outgoing comparison Built
Auth, org scoping, first-run registration Built
Peer sync — HTTP transport, Ed25519 envelopes, folder/USB Built, not yet exercised beyond its test suite
WRAP trades/v0 binding In progress — cross-organisation work orders
Tenant portal Designed, not built. The data model carries public vs internal event visibility; there is no tenant-facing surface yet
Photo attachments Partial — references exist; content-addressed blob storage and replication are not built
Template versioning Open question. Comparison tolerates template drift by pairing on item text; there is no formal versioning
Recurring / planned maintenance Not built
Compliance certificates Not built

Configuration

Flag Default Description
--db pango.db SQLite file path
--addr 127.0.0.1:8099 Listen address
--demo off In-memory demo data; forces :memory: so it can never touch a real database
--sync-listen off Accept sync from enrolled peers
--sync-peer Peer URL to sync with
--sync-folder Shared directory for file transport

Every networked feature is off by default. A fresh install makes no outbound connections.

Documentation

Doc
Architecture The binding contract — read before changing anything structural
Getting started Install and first run
Configuration Flags and settings
Sync The replication protocol in depth
WRAP Cross-organisation work orders
Inspections Condition capture and comparison
Self-hosting Deployment
Cloud & tunnelled nodes Running on a public address — a different threat model
Threat model Including what is not protected
FAQ

Development

npm run dev              # frontend on :5173
npm run build            # production bundle
npm test                 # vitest
npm run test:e2e         # playwright, against the real binary
npm run screenshots      # regenerate docs/screenshots from demo mode
make check               # the full gate
cd backend && go test ./...

Contributing

Issues and pull requests welcome. Read ARCHITECTURE.md first — several of its rules (append-only money, building-as-authority, author-key tie-breaks) look like style preferences and are not.

Brand

The mark in brand/ is the source of truth. Every icon this repo ships — favicon, PWA and app icons, the mark in the README and on the site — is rendered from brand/logo.svg rather than redrawn, so there is one approved drawing and no second copy to drift.

Copy it outward, never edit a derived copy, and never edit brand/ to match something downstream.

License

MIT OR Apache-2.0 — © VulOS. Pango is a VulOS project; source and issues at github.com/vul-os/pango.


vulos
vulos — open by design

About

Pango — self-hostable building maintenance & inspections you own: jobs costed per building and per unit, ingoing/outgoing condition comparison that settles move-out damage. Offline-first, single binary, your data.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages