Documentation

How Charging works

Two layers, in a deliberate order. Six engines compute a result from published code tables with no model involved. Twelve instruments then interpret, critique and write up what the engine produced.

That order is the product. A model that guesses a conductor size is a liability. A model that explains a computed one, names the code section it comes from, and tells you which field condition would change it, is genuinely useful. Everything here follows from keeping those two jobs separate.

Run the tests yourself

The engines ship with a test suite that checks every result against hand-worked examples. From the repository root: npm test. It asserts 55 values — load calculations, breaker and conductor selection, voltage drop, charge times, depot peaks, site payback and tariff totals — and exits non-zero on any failure.

Code edition
NFPA 70, National Electrical Code, 2023
Terminations
75 °C
Conductors
Not more than three current-carrying in a raceway; no ambient derating applied
Model
claude-sonnet-5 via the Anthropic Messages API
Runtime
Static front end, two edge functions, managed Postgres
Engine execution
Entirely client-side — inputs never leave the browser

The six engines

Each engine is a pure function: same inputs, same output, no network, no randomness. They live in assets/engines.js and can be imported and used on their own.

Load calculator

Answers whether an existing service can carry a new EVSE. Implements NEC 220.83 (standard method — 100% of the first 8 kVA of other load, 40% of the remainder, plus the larger of heating and cooling) and NEC 220.87 (measured method — recorded peak demand at 125% plus the new load at 125%). The EVSE is counted as a continuous load at 125% per 625.41. Also solves for the largest EVSE the service will carry.

Circuit sizer

Overcurrent device at not less than 125% of continuous load (210.19(A)(1), 210.20(A)), rounded up to a standard rating (240.6(A)). Conductor from Table 310.16 at 75 °C, constrained by the small-conductor limits in 240.4(D). Equipment grounding conductor from Table 250.122. Voltage drop computed from circular mils in Chapter 9, Table 8, and the conductor is upsized until it meets the target.

Charge session

AC power is the lesser of the EVSE output and the vehicle's onboard charger. DC follows a taper: full power to the knee, then linearly down to 15% of peak at 100% state of charge, integrated over 1% steps. Reports time, energy into the pack, energy at the meter after efficiency losses, cost, range added and cost per 100 miles.

Depot planner

Fleet energy against a dwell window. Computes the arithmetic minimum charger count, the uncontrolled peak if everything plugs in at once, and the managed peak under automatic load management (NEC 625.42). Converts the difference into monthly demand charges and into a service size at 208 V or 480 V three-phase.

Site economics

Public DC fast charging. Annual energy from stalls, power, uptime and utilisation; revenue against wholesale energy, demand charges at a stated coincidence factor, and fixed opex. Solves break-even utilisation directly rather than searching for it, and reports simple payback on capex.

Tariff compare

Flat, time-of-use and utility EV rate on the same charging profile, including any fixed monthly charge, with the annual cost of choosing wrong stated in dollars and a second pass showing what shifting 90% of load off-peak would be worth.

Method and tables

The reference data compiled into the engines, so you can check it against your own copy of the code book.

Ampacity — Table 310.16, 75 °C

AWG / kcmilCopper (A)Aluminium (A) Circular mils

Small-conductor limits — 240.4(D)

Regardless of ampacity, overcurrent protection is limited to 15 A for 14 AWG copper, 20 A for 12 AWG copper, 30 A for 10 AWG copper, 15 A for 12 AWG aluminium and 25 A for 10 AWG aluminium.

Voltage drop

Estimated with the circular-mil method, using K = 12.9 for copper and K = 21.2 for aluminium:

single phase   Vd = 2 · K · I · L / cmil
three phase    Vd = 1.732 · K · I · L / cmil

3% on a branch circuit is the figure in the informational note to 210.19(A). It is a recommendation, not a requirement, which is why it is an adjustable target rather than a hard constraint.

What the engines do not do

No ambient temperature correction (310.15(B)(1)), no adjustment for more than three current-carrying conductors (310.15(C)(1)), no conduit fill, no 60 °C termination limitation, no derating for continuous duty beyond the 125% rule, no service-entrance or feeder tap rules, no arc-flash or short-circuit analysis. Local amendments are not modelled. These are planning calculations, and a licensed electrician makes the design.

The twelve instruments

Six teach, six research. Each has a fixed role and a specified output shape — a comparison declares its criteria and weights before it scores; a scenario model tables every assumption and names the one whose failure breaks the result; a steelman argues both sides at equal length. The shapes are what make output checkable rather than merely fluent.

Any completed response can be handed to any other instrument, carrying the text as context. Engine results can be handed in the same way, so a computed load calculation becomes the starting point for a scenario model rather than something the model has to guess at.

Instrument prompts live in the TOOLS array in assets/app.js. Renaming an instrument or rewriting its brief is a one-line data edit.

API

Two endpoints ship with the deployment. Both are edge functions and both run on Vercel and Netlify unchanged.

POST /api/chat

Proxies to the Anthropic Messages API with server-sent-event streaming. Your API key is read from the ANTHROPIC_API_KEY environment variable and never reaches the browser.

curl -N https://DOMAIN/api/chat \
  -H 'content-type: application/json' \
  -d '{
    "system": "You are a charging expert.",
    "messages": [{"role":"user","content":"Why does DC charging taper?"}],
    "max_tokens": 800
  }'

Responds text/event-stream. Accumulate delta.text from content_block_delta events. Context is truncated to the last 24 messages and max_tokens is capped at 4096 server-side.

GET /api/config

Returns the two public Supabase values so the front end can authenticate without them being hardcoded. Never returns anything secret.

{ "supabaseUrl": "https://xxxx.supabase.co", "supabaseAnonKey": "eyJ..." }

Engines as a module

The engines have no dependencies and run in Node or the browser.

const { ENGINES } = require('./assets/engines.js');

const r = ENGINES.circuit({
  amps: 48, volts: 240, material: 'cu', length: 60, vdLimit: 3
});

r.breaker   // 60
r.size      // '6'
r.egc       // '10'
r.dropPct   // 0.0118
r.notes     // the code references behind each choice

Fleet and Enterprise plans expose these as a hosted HTTP API with keys and per-key rate limits. Until then, vendoring the file is the supported path and it will keep working whatever we do to the hosted product.

Self-hosting

  1. Push the repository to GitHub. Do not upload the zip — the web uploader will not unpack it.
  2. On Vercel: Add New → Project → import the repo. Framework preset Other. No build command, no output directory.
  3. Settings → Environment Variables → add ANTHROPIC_API_KEY, then redeploy. This is what makes the instruments work for visitors instead of asking each of them for a key. The engines work without it.
  4. Optional but recommended: create a Supabase project, run supabase/schema.sql in the SQL editor, and add SUPABASE_URL and SUPABASE_ANON_KEY. This turns on sign-in, saved projects and share links.
  5. Add your domain, then replace every DOMAIN in the head block of index.html, app.html and docs.html. og:image must be an absolute https URL or link previews render blank in every messenger.
  6. Regenerate brand assets after any change to brand/*.svg with python3 build-icons.py, and keep assets/ committed.

Netlify works identically; netlify.toml is included and the functions use the standard export default async (req) => Response signature both platforms accept.

Security

Attack surface

A static front end, two stateless edge functions and a managed Postgres. No server we operate holds customer data outside that database. No build step, no dependency tree, no third-party script on any page.

Secrets

The Anthropic key exists only as a server environment variable read inside api/chat.js. It is never sent to a browser, never logged, and never written to the database. The Supabase service-role key is not used anywhere in this application.

Authentication

Passwordless email links. There is no password to leak, reuse or phish out of a support ticket. Sessions are bearer tokens held in browser storage and revocable by signing out.

Authorisation

Row-level security is enabled on every table. Projects and sessions carry a user_id and the policy is auth.uid() = user_id for select, insert, update and delete. Enforcement is in Postgres, not in application code, so a front-end bug cannot expose another account's rows. Share records are deliberately readable by anyone holding the link — that is what a share link is, and the product says so before you create one.

Data minimisation

Engines run client-side. Signed out, no engine input is ever transmitted. Signed in, we store the project you asked us to save and nothing else. There is no analytics tracker and no advertising cookie on any page.

Deletion

Signing out clears local session state. Clearing local data removes browser-stored projects. Account deletion cascades every project, session and share row through foreign keys.

Reporting an issue

Send security reports to the address published on the deployed domain. We will acknowledge within two business days and will not pursue researchers acting in good faith.

What we do not claim

We have no SOC 2 report, no ISO 27001 certificate and no penetration test to show you. Saying otherwise would be the easiest thing on this page to fake, so we are saying it plainly instead. What we can offer an enterprise buyer today is a deployment in your own cloud account, against your own keys and your own database, where our controls are not the question.

Enterprise

For utilities running make-ready programmes, charge point operators who need a customer education surface, and OEMs who want the calculation inside their own experience.

  • Your cloud. Deployed in your account, against your Anthropic key and your Postgres. Nothing calls home.
  • Your brand. Full theming of the design system, your logotype, your domain, your legal terms.
  • Your code edition. Pin a different NEC edition or add jurisdiction amendments as engine overrides, including local derating rules and permit fee schedules.
  • Your data model. Tenant isolation, SSO through your identity provider, and webhooks into the systems that already hold your customer records.
  • Qualification hooks. A completed load calculation is the most qualified make-ready lead in the category. Route it wherever your programme needs it.

Engagements start with a two-week pilot on a single programme and a fixed scope.

Changelog

1.4.0current
  • Six deterministic engines with 55 hand-checked assertions and npm test
  • Project workspace: named projects, per-engine inputs, per-instrument sessions
  • Claude review of any engine result, with hand-off into any instrument
  • Printable project reports assembling captured engine results
  • Company site, documentation, method tables and API reference
1.2.0
  • Supabase projects table with row-level security
  • Plan entitlements and account sheet
  • Share links with rasterised Open Graph cards
1.0.0
  • Twelve instruments with fixed roles and specified output shapes
  • Streaming through a single edge-function proxy
  • Passwordless sign-in and session persistence

Status

Engines — client-side computeOperational
Instruments — inference proxyOperational
Accounts and project syncOperational
Share linksOperational

Engines run in your browser, so they keep working even when everything else here does not. The live link state for your own session is shown in the panel's telemetry strip.

Contact

Charging is built by Humble Superintelligence. Sales, support, security reports and enterprise enquiries all go to the address published on the deployed domain.

If you found a wrong number in an engine, that is the message we most want to receive. Include the inputs and the result and we will fix it, add an assertion for it, and note it in the changelog.