doneintelligentlyStart a build

Civic compliance software

SmartComply

We designed and built SmartComply — the system of record that runs a town’s entire stormwater permit program from day one.

Year
2026
What we did
Platform, product, brand & site
smartcomply.app/idde
SmartComply illicit-discharge investigation map with outfalls and tracked cases

The problem

Towns are legally accountable for their stormwater programs, yet most run them on spreadsheets, shared drives, and email — so when an auditor or a lawsuit asks who changed what and when, no one can answer.

Every U.S. town with an MS4 permit owes the same work: tracking outfalls, chasing illicit discharges, testing backflow, inspecting construction sites and BMPs, managing industrial pretreatment, issuing enforcement, billing fees, and signing off an annual report that has to hold up under scrutiny. The obligations are federal. The tooling, almost everywhere, is improvised.

SmartComply brought us that gap. A program scattered across files and inboxes isn’t just inefficient — it’s indefensible. The moment an inspection record can’t be tied to a person, a date, and a reason, the town’s legal position erodes. We were asked to turn an ad hoc routine into a system of record that could stand up to an audit.

So we designed and built it: an isolated workspace for each town, every permit obligation modeled as a tracked workflow, every record pinned to an interactive map, and every field carrying its own tamper-evident change history. Enforcement notices generate, get e-signed, and go out by physical mail. Residents report spills through a public intake that lands as a tracked case. A town signs up and is running its full program the same day.

1
Isolated workspace per town
Day 1
Running, no implementation project
Every field
Its own change history
Full permit
Program in one platform

What makes it different

What we built in, on purpose.

The decisions that separated a real system of record from another database with a map.

01

A workspace per town

Each town gets a fully isolated tenant — its own data, its own program, no bleed. Compliance records can’t share a table with anyone else’s.

02

Obligations as workflows

We didn’t store records and hope. Every permit requirement is modeled as a tracked workflow, so the work that’s owed and the work that’s done are the same object.

03

Change history on every field

Each field carries its own tamper-evident history of who changed it and when. The audit answer is built into the data, not reconstructed after the fact.

04

The map is the index

Outfalls, inspections, investigations and BMPs live on an interactive map. The town’s geography is how you find and reason about its records.

05

Enforcement that closes the loop

Notices are generated, e-signed and physically mailed from inside the platform — no exporting to Word, no trip to the post office to make it official.

06

A public front door

Residents report spills and illicit discharge through a public intake that becomes a tracked case the moment it’s filed — citizen reports enter the same system, not a separate inbox.

When the auditor asks who changed this and when, the answer is already in the record.

Under the hood

A multi-tenant compliance platform, specified.

A turbo monorepo on Next.js 16 and React 19, deployed on Vercel, with the data and document machinery a regulator-facing system demands.

Core platform

Framework
Next.js 16 (App Router) · React 19 · TypeScript, in a Turborepo with shared db / rules-engine / ui / types / validators packages.
Data layer
Drizzle ORM over Nile — Postgres purpose-built for multi-tenant SaaS, giving each municipality a hard-isolated tenant.
Auth & access
Clerk for identity, with a custom RBAC layer and tenant-slug routing so roles and data scope per town.
Background work
Inngest for durable jobs — notice generation, report snapshots, import pipelines and scheduled compliance checks.

The compliance machinery

Geospatial
MapLibre GL renders outfalls, facilities and IDDE cases as interactive map layers — the primary way users navigate.
Rules engine
A dedicated package encodes MS4, pretreatment and backflow rules, so deadlines and violations are computed, not hand-tracked.
Documents
TipTap for rich editing; pdf-lib + fontkit to generate notices and the annual MCM report; e-signature capture on enforcement.
Physical mail
Lob delivers enforcement notices as certified letters, with tracking written back to the case.
Audit integrity
Per-record hashing plus field-level change history — the tamper-evident backbone behind every list and detail view.

Money, intake & intelligence

Payments
Stripe for subscriptions and fees, Plaid for bank-linked payment, modeled inside the same tenant as the obligations.
Public intake
A public, rate-limited spill/illicit-discharge report (Upstash) that creates structured investigation cases.
AI assist
The AI SDK (Anthropic · Google · OpenAI) powers import triage and document drafting — intelligence inside the workflow, not a chat bubble.
Comms
Transactional email and SMS for notices, reminders and status changes across the lifecycle of a case.

Operations & quality

Observability
Sentry + OpenTelemetry (Vercel OTel) for traces and errors across the request and job paths.
Storage
Vercel Blob for evidence photos, lab results and generated documents.
Testing
Playwright end-to-end, plus Autonoma and Kernel-driven automated QA against seeded demo tenants.
Delivery
Vercel with a route-smoke + auth-smoke gate; an automated code-audit step blocks high-severity findings from shipping.

The build, on screen

Inside the platform.

SmartComply program dashboard
Program dashboard — the whole permit at a glance.
Outfall inventory on the map
Outfall inventory — every discharge point, mapped.
Illicit discharge case workflow
IDDE — illicit discharge, detection to resolution.
Field-level change history popover
Hover a field — its full change history is right there.
Activity timeline for a record
Every record keeps a complete activity timeline.
Enforcement notice detail
Enforcement notice — generated, signed, mailed.
Billing list
Fees and pretreatment billing, inside the record.
BMP inspections
BMP & construction-site inspections, scheduled and logged.
New illicit discharge investigation form
Opening a new illicit-discharge investigation.
Backflow test form
Backflow-prevention testing, captured to standard.

Technology

What it’s built on.

Language
  • TypeScript
Framework
  • Next.js 16
  • React 19
  • Turborepo
Data
  • Nile (Postgres)
  • Drizzle ORM
Auth & access
  • Clerk
  • Custom RBAC
AI
  • Anthropic
  • OpenAI
  • Google
Async & realtime
  • Inngest
  • Upstash Redis
Payments
  • Stripe
  • Plaid
Storage
  • Vercel Blob
Specialty
  • MapLibre
  • Lob
  • TipTap
  • pdf-lib
Infra & hosting
  • Vercel
  • Sentry
  • OpenTelemetry

Our approach

How we approached the build.

We built backward from the hardest question a town can be asked.

  1. 01

    Started from the audit.

    We designed for the moment of scrutiny first — an auditor or a lawsuit asking for proof. Everything else followed from making that answer trivial.

  2. 02

    Modeled the permit, not the paperwork.

    We mapped the actual MS4 obligations into workflows so the software mirrors what the permit requires, instead of digitizing whatever spreadsheet a town happened to have.

  3. 03

    Made history non-negotiable.

    Change tracking isn’t a feature you turn on — it’s wired into every field. There’s no path to editing a record without leaving a tamper-evident trail.

  4. 04

    Removed the onboarding wall.

    We built it so a town self-serves into a working program. No implementation project, no consultants — sign up and the system runs from day one.

Next case study

FASTMAX

How we helped FASTMAX turn a wall of tax forms into a finished return.