{"slug": "nutral-s-homelab-blog", "title": "Nutral's HomeLab blog", "summary": "Nutral's HomeLab blog reports that an AI coding agent successfully implemented a feature in a FastAPI and Svelte application, consuming about 6 million input tokens and 250,000 output tokens, and correctly created and executed a plan despite prior reactivity issues with Svelte and Claude Sonnet 4.6. The agent also proposed a unit-switching system for pressure inputs (MPa/bar) with a clickable unit label, a settings cog icon, and a loop-safe data flow design, asking the user to choose between global or per-calculation unit persistence.", "body_md": "To give a little example of working with this.\n\nI work on my software that has a backend in fastapi and front-end in svelte. (svelte can be an issue with models!)\n\nThe feature has been correctly implemented in one go! about 6M input tokens and 250k output tokens running somewhere this morning. I’ve had a lot of reactivity issues with svelte and claude sonnet 4.6 and while I did warn the agent this time, it correctly created a plan and executed it.\n\nNow this isn’t perfect, it is very much based on a lot of groundwork in the software, how things are done and how data is structured that is kept in the same way. Being more intentional also makes it easier for LLM’s to program further.\n\nToday i wanted to fix a bug and implement different units in the front-end, with my own philosophy.\n\n`prompt I want you to create a plan, where we can switch between bar and mpa as input for presure. that can be switched between in the front-end. I would prefer it would be something like clicking the Mpa text on the input field. This should be part of a more generalized \"unit\" system where the front-end operates in a certain unit and then convertes that back to MPa. The philosophy of this whole software is that everything uses the same basic unit system MPa, mm etc and conversions are done in the front-end or in the backend class. `\n\nAnswer\n\n```\nI've written out the plan and set up the task list. To recap the key decisions so you can approve or adjust:\n 1.  Base unit = MPa in formData (unchanged single source of truth; backend keeps its MPa→bar conversion in the class).\n 2.  Display unit is a separate, switchable setting, converted only at the input boundary (display→MPa on input, MPa→display for showing).\n 3.  Clickable unit label (UnitCell) to cycle MPa ↔ bar — matches your \"click the MPa text\" request.\n 4.  New: src/lib/units.js (registry), src/store/displayUnits.js (persisted setting), UnitCell.svelte (clickable label). Touched: Numberinput.svelte, Caseinput.svelte, Caseinput_single.svelte.\n 5.  Phase 1 = pressure only; the registry is built so temperature (°C ↔ °F) and other quantities slot in without new plumbing.\nOne thing I'd like your call on before I start:\n•  Where should the unit choice be remembered? My default is a single global setting per quantity (e.g. \"pressure is in bar\"), persisted to localStorage, applied to all routes at once. Alternatively you could want it per-calulation (stored in the calculation record / URL) so each saved calc remembers its own units. Global is simpler and matches \"the frontend operates in a certain unit\"; per-calc is more granular. Which do you prefer?\nOnce you confirm (and pick global vs per-calc), I'll start with the unit registry and store.\n```\n\n`prompt I want to save it to localstorage in the same similar way that dark/light mode is stored. I would like to also have a small cog icon next to the question mark and keyboard sign where you can also switch units (based on a standard \"settings\"js or something like that?) What i do wonder is. We have a single source of truth that is formdata. how is the connection done between the caseinput and the formdata? I thas to go 2 ways without causing a reactivity loop `\n\n```\nThe plan is now complete and grounded in your existing code. Here's the final shape:\nArchitecture (loop-safe, your philosophy preserved)\nData flow — the key to no reactivity loop:\n•  formData = base units (MPa), single source of truth, what's sent to the backend. Never stores display units.\n•  Each input shows a local display string in the selected unit.\n•  Type → base: oninput converts display→MPa and writes formData (one-way, no read of formData).\n•  External change → display: an $effect re-syncs display from formData (MPa→display) only when the input isn't focused (unit toggle, load, reset, blur). While focused, the user's text is never overwritten → no cycle.\nComponents (new):\n 1.  src/lib/units.js — unit registry. Linear factors now (MPa↔bar), structured to add offset units (°C↔°F) later. toBase/fromBase(quantity, value, unit).\n 2.  src/store/settings.js — mirrors theme.js exactly (writable, hydrate from localStorage, subscribe to persist), but a general settings object holding { units: { pressure: 'MPa', temperature: '°C' } } with a toggleUnit action.\n 3.  src/components/forms/UnitCell.svelte — clickable unit label (reuses the ig-cell preset-tonal styling, adds a small cycle icon), cycles the unit for its quantity.\n 4.  src/components/SettingsModal.svelte — mirrors KeyboardShortcutsHelp (same Modal), with Pressure (MPa/bar) and Temperature (°C/°F) toggles.\nWiring (touched):\n•  Numberinput.svelte — MPa fields (design_pressure, stress_design_override, …) use UnitCell + the loop-safe conversion.\n•  Caseinput.svelte + Caseinput_single.svelte — the pressure cell becomes a UnitCell; same focused-guard conversion for every value in pressureArray.\n•  Both CalculationLayout.svelte and FreeCalculationLayout.svelte — gear button added next to the keyboard icon, opening SettingsModal.\nWhy this is clean for your single-source-of-truth rule: formData is never touched except directly (as you already do), the conversion lives entirely at the input boundary, and the only reactive sync is event-driven and focus-gated — so no loops, no intermediate state variables.\nOne deliberate choice to confirm: I'm keeping the temperature switch (°C↔°F) in the settings modal from day one (it's cheap now the registry supports it), but the temperature input conversion can ship in the same pass or as a quick follow-up — either way it won't affect pressure.\nShall I go ahead and implement it? I'll start with src/lib/units.js + src/store/settings.js, then the UnitCell + SettingsModal, then wire the inputs and gear buttons, and finish with svelte-check + a browser smoke test.\n```\n\n`prompt Implement this but not for numberinput because I don't want bar for stress_design and design pressure is not used with numberinput. `\n\n```\nThe frontend unit system (your in-progress work) — now complete\nThe whole chain is consistent: Caseinput → UnitInput stores pressure in MPa (the base unit), the API sends it raw, and the backend does the ×10. I found and fixed one bug that was blocking it:\n•  Fixed a Svelte syntax error in Caseinput.svelte and Caseinput_single.svelte: {error: pressureError(index)} is object-spread (invalid for a single prop); changed to error={pressureError(index)}. svelte-check went from 4 errors → 0 errors (the remaining 8 warnings are all pre-existing, none in your files).\nConfirmed working:\n•  Generalized: src/lib/units.js registry (pressure MPa/bar, temperature °C/°F, length mm) with toBase/fromBase; UnitInput cycles the unit on label-click and always stores the base value.\n•  Persisted: src/store/settings.js writes units to localStorage, merged over defaults; SettingsModal (gear icon in both layouts) can set units too.\n•  Loop-safe: UnitInput binds a local display string and only re-derives from base when not focused, so typing is never clobbered.\n•  No regression: design_pressure is now sent as numbers/null instead of strings — matches the backend's list[Annotated[float, gt=0]] schema. I verified every Caseinput route (branch/head/bend/straightinternal/external/flange) expects MPa; test-pressure is the one bar-based route and it uses Numberinput directly, so it's untouched.\n•  Cleanup: the intermediate CaseField.svelte/UnitCell.svelte are gone with no lingering references.\nI also added a note to AGENTS.md recording the MPa-input / ×10-to-bar convention so nobody mistakes it for a bug again.\n```\n\n", "url": "https://wpnews.pro/news/nutral-s-homelab-blog", "canonical_source": "https://forum.level1techs.com/t/nutrals-homelab-blog/201528?page=5#post_82", "published_at": "2026-08-31 09:05:19+00:00", "updated_at": "2026-08-31 09:22:23.846581+00:00", "lang": "en", "topics": ["artificial-intelligence", "ai-agents", "ai-tools", "developer-tools"], "entities": ["Nutral", "FastAPI", "Svelte", "Claude Sonnet 4.6"], "alternates": {"html": "https://wpnews.pro/news/nutral-s-homelab-blog", "markdown": "https://wpnews.pro/news/nutral-s-homelab-blog.md", "text": "https://wpnews.pro/news/nutral-s-homelab-blog.txt", "jsonld": "https://wpnews.pro/news/nutral-s-homelab-blog.jsonld"}}