Skip to content

Contributing

delabrcd edited this page Jun 6, 2026 · 2 revisions

Contributing

Workflow

  1. Fork (or branch, if you have access) off main.
  2. Make your change. Keep number logic pure + tested (Data Accuracy, Testing).
  3. Build and run it: docker compose -f docker-compose.yml -f docker-compose.build.yml up -d --build.
  4. Run the tests and (for numeric changes) the cross-validation.
  5. Open a PR against main with a clear description and the checklist below.

PR checklist

  • docker run --rm ngrid-dashboard-test passes.
  • For anything touching numbers: GET /api/verify is green on a real account — summary pasted in the PR.
  • New pure logic (parsing/math/prediction) has a hand-calculated unit test.
  • No secrets or personal data committed (.env, data/, session, PDFs, account numbers, addresses). They're gitignored — keep it that way.
  • New numeric/parse logic lives in parsePdf.ts / series.ts / prediction.ts, not in a component or route.
  • Code matches the surrounding style (TypeScript, existing naming/idioms); no new dependency without a reason.
  • If the portal interaction changed, you verified a real scrape end-to-end.

Coding conventions

  • TypeScript throughout. Keep the strict-mode build clean.
  • Pure where it counts. Anything you'd want to unit-test (math, parsing, prediction) is a pure function with no DB/browser/React dependency.
  • Charts are declarative. Add or change a chart by editing lib/chartSpec.ts (series, axes, colors); the generic ConfigurableChart renders it and derives its config menu. Don't fork a bespoke chart component.
  • Display prefs go through lib/prefs.tsx (localStorage); runtime app settings (like the scheduler toggle) go through the AppSetting table + /api/settings.
  • Match the repo. Comment density, naming, and structure should look like the file you're in.

Security & secrets

  • Credentials are either read from env at runtime (NGRID_USER/NGRID_PASS, the bootstrap/fallback) or saved AES-256-GCM-encrypted in the DB (NgLogin) — never hardcode or commit them, and never log or return a decrypted password to the client. The encryption key comes from NGRID_SECRET_KEY (or an auto-generated file in the session volume) and is never stored in the DB (Accounts and Login). The saved Playwright session lives in a root-only Docker volume (0600); don't relocate it to a bind mount or log its contents.
  • .gitignore excludes .env and data/. Before committing, double-check nothing under those (PDFs, session, DB) and no account number/address/domain slipped into source.
  • No app-level auth by design. The dashboard exposes financial data and is meant to be LAN-only or behind a reverse proxy/SSO. Don't add a public login or instructions to expose it. The in-app NG-login management UI (enter/verify National Grid credentials) is allowed but inherits the existing gate — it is not a public application-login layer (Accounts and Login).

Etiquette & Terms of Service

This scraper accesses a third-party site with a real account. Automated access may be against National Grid's ToS — it's personal-use, at-your-own-risk. Contributions must keep it gentle: reuse the session, keep the rate-limit/jitter, and never add tight polling or parallel logins. If you touch the scheduler, preserve the "tighten near the predicted bill, back off otherwise" behavior — don't make it poll aggressively.

Commits

  • Write clear, imperative commit messages.
  • Author commits as yourself. The maintainer keeps AI/co-author trailers off this repo — don't add Co-Authored-By trailers.

How to add common things

  • A chart: add an entry to CHART_SPECS in lib/chartSpec.ts. Add the underlying fields to MonthRow + deriveMonthlySeries if needed (with a test).
  • A data source: capture it in collect.ts (intercept-and-widen), normalize it, add a model
    • upsert in persist.ts, surface it via queries.ts/series.ts. If it's a number, add a verify.ts cross-check.
  • An API route: add under app/src/app/api/<name>/route.ts with runtime = 'nodejs' and dynamic = 'force-dynamic'.
  • A setting: display pref → prefs.tsx; server setting → AppSetting + /api/settings.

Clone this wiki locally