# Contributing to InfraNet Pro Welcome. This project is intentionally **low-tooling**: vanilla JS, Node-only, with a *lightweight* esbuild bundle for the frontend (introduced by the ESM migration). You can be productive in minutes. Read `ARCHITECTURE.md` first for the mental model. ## Setup & run ```bash npm install # runtime (Express, net-snmp, pdfkit, esbuild…) + dev (eslint, typescript, playwright-core) npm start # build the frontend bundle + serve → http://localhost:8421 ``` On first launch a default **`admin` / `admin`** account is created — change the password immediately. The login page is required to reach the app (and the preview tooling). ## The commands you'll use ```bash npm run check # syntax-check every source .js (tools/check-syntax.js) npm run lint # ESLint gate — no-undef as a safety net (eslint.config.js) npm test # run all tests (node --test, zero dependencies) npm start # serve the app ``` `check`, `lint` and `test` must all be green before you commit (the same three run in CI). `npm run lint:fix` applies the auto-fixable subset. The lint gate is deliberately scoped: `no-undef` is enforced where the module system is explicit (Node/CommonJS + the UMD `lib/`), and **off on `src/`** for now (the bundle's `window` bridge resolves bare names at runtime — it re-enables once that bridge is retired). Stylistic findings are warnings, not errors, so the gate stays green. ## Conventions (non-negotiable) 1. **Logic in `lib/`, presentation in glue.** Put decision logic in a pure UMD-lite module under `lib/` (works in Node + browser) and unit-test it. Keep the glue (ESM modules in `src/app-*.js`, bundled by esbuild) thin — it turns pure results into DOM. See `ARCHITECTURE.md` §3. 2. **No new runtime dependency** without a strong, discussed reason. The frontend build is esbuild-only (a dev dep); keep the pure `lib/*.js` modules UMD-lite so the Node tests import them unchanged. 3. **Tests are zero-dependency** — `node --test` only. New pure logic ships with a `test/.test.js`. 4. **Manual-first**: never make discovery/SNMP overwrite a user-entered value. 5. **i18n**: any new UI string gets a key in both `it` and `en` in `lib/i18n.js`. Use `data-i18n` for static HTML, `t('key')` for JS templates. Never machine- translate; leave technical terms and vendor names alone. The key-parity test fails if a translation is missing on one side. 6. **Every value interpolated into HTML goes through `escapeHTML()`.** There is no framework doing it for you, and the input is not only your keyboard: `sysName`, `sysDescr`, DHCP hostnames and LLDP neighbour names come from the devices, i.e. from anyone on the network being documented. A static guard (`tools/html-escape-scan.js`) proves what it can and ratchets the rest per file, so a new raw `${d.sysName}` fails the build. Run `node tools/html-escape-scan.js --list` to see where a file's residue is. 7. **Use the design tokens, including for text size.** Sizes come from `--fs-2xs…--fs-2xl` in `styles/01-tokens.css` — writing `0.82rem` by hand is the same pixel today and a different one the day the token moves, and `test/type-scale-ratchet.test.js` fails on it, naming the line and the token to use. Same for colour: a badge's ink is derived from its background, never fixed. See `styles/README.md`. ## Your first change (worked example) Add a field to a device, the right way: 1. **Pure logic (if any)** → a function in a `lib/` module + a test in `test/`. 2. **Glue** → render the field in the relevant block of `src/app-properties.js` (or the matching `src/app-properties-*.js`). 3. **i18n** → add the label keys to `it` and `en` in `lib/i18n.js`; tag with `t('...')` / `data-i18n`. 4. `npm run check && npm run lint && npm test` → all green. 5. **Verify in the browser** (`npm start`, log in): the smoke tests catch crashes but **not** visual issues — open the page and look. Switching the language is a good way to surface JS-rewritten text that bypassed i18n. ## Commit & PR - **Commit messages**: conventional style (`feat(...)`, `fix(...)`, `refactor(...)`, `docs(...)`). - **Never commit** secrets or user data — `users.json`, `.session-secret`, `projects/`, `.env` are git-ignored; keep it that way. - Keep PRs focused; a green `check` + `lint` + `test` is the bar. ## Where things live (quick map) | You want to… | Look in | |---|---| | Add/adjust device types | `src/app-types.js`, `src/app-properties.js`, `netmapper.html` (palette) | | Change rendering of the rack/floor/cables | `src/app-render-core.js`, `src/app-topology-overlay.js` | | Touch SNMP polling/discovery | `drivers/snmp.js`, `server/routes/discovery.js`, `src/app-snmp.js` | | Classification (sysObjectID / OUI) | `engine/`, `plugins/` | | Translations | `lib/i18n.js` | | CSS, design tokens, the type scale | `styles/` (start from `styles/README.md`) | | Backend routes / storage | `server/` | Thanks for keeping it simple. The lack of tooling is a feature — please preserve it.