diff --git a/README.md b/README.md index fbc4381c..ae4b0903 100644 --- a/README.md +++ b/README.md @@ -1,141 +1,235 @@ # Hydro Builder -An interactive, browser-based 3D builder for hydroponic / water-flow systems. -Design lattice towers, grow walls, pipe networks, pumps, reservoirs and custom -water paths — with live, approximate flow simulation. +Hydro Builder is a browser-based 3D builder for laying out pumps, reservoirs, pipe runs, fittings, towers, trays, and return lines with live water-flow feedback. -Built with **React + TypeScript + Vite**, **React Three Fiber / Drei**, -**Zustand**, and **TailwindCSS**. +It is built for fast iteration: -![Hydro Builder](docs/screenshot.png) +- click-to-place parts +- drag to reshape runs +- snap connectors pipe-to-pipe +- switch between builder, x-ray, water, and 3D views +- inspect pump output, head, open ends, and system health while you build -## Quick start +![Hydro Builder UI](docs/hydro-builder-ui.png) + +## What this repo contains + +- `frontend`: React + TypeScript + Vite app in the repo root +- `backend`: lightweight Express API in `server/index.js` with SQLite persistence +- `simulation`: in-browser flow and diagnostics for pumps, restrictions, head, loops, and open drains + +## Linux quick start + +These instructions assume Ubuntu or Debian first. Equivalent packages work on Arch, Fedora, or other distros. + +### 1. Install system dependencies + +```bash +sudo apt update +sudo apt install -y git curl build-essential python3 make g++ +``` + +### 2. Install Node.js 20 + +Use Node 20 LTS. The app is Vite-based and that is the sane floor here. + +```bash +curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - +sudo apt install -y nodejs +node -v +npm -v +``` + +You want Node `20.x` or newer. + +### 3. Clone and enter the project + +```bash +git clone https://gitea.thetempleofdoom.com/drjones/hydro-builder-app.git +cd hydro-builder-app +``` + +### 4. Install JavaScript dependencies ```bash npm install -npm run dev # → http://localhost:5173 ``` +### 5. Create your local env file + ```bash -npm run build # typecheck + production build (dist/) -npm run preview # serve the production build -npm run typecheck # tsc only +cp .env.example .env ``` -On first launch the app loads a working demo: reservoir → pump → riser → -overhead return → emitter spraying back into the tank, plus a grow tower, -tray and lattice to play with. Your work autosaves to the browser and is -restored on the next visit. +Minimum local env: -## Using the builder - -| Action | How | -|---|---| -| Place a part | Click it in the left library, then click the ground (Shift-click stamps copies). Or drag it from the library onto the canvas. | -| Move a part | Drag it in the scene. In Front/Side views, dragging moves vertically too. | -| Raise / lower | `E` / `Q` (or edit Y in the inspector) | -| Rotate | `R` (90° around Y), Shift-`R` reverse, or inspector fields/buttons | -| Duplicate / delete | `D` / `Delete`, or inspector buttons | -| Undo / redo | `⌘Z` / `⇧⌘Z` (or toolbar) | -| Measure | Toolbar 📏, then click two points | -| Snap to grid | Toolbar ⌗ (0.25 ft grid) | -| Connect pipes | Drop a part near another part's connector — it snaps. Green dot = joined, amber = open. | -| Views | Toolbar: 3D orbit / Top / Front / Side (2D orthographic) | -| Water animation | Toolbar 💧 Flow | -| Save / Load | Toolbar — named projects in browser storage | -| Export / Import | Toolbar — design JSON file | - -## How the simulation works - -The system is treated as a **graph**: - -- **Nodes** — connection points; connectors that touch are merged (union-find). - Every flow-carrying part also gets an internal node so 3-way tees, tanks, - towers etc. work uniformly. -- **Edges** — part bodies (pipes, elbows, valves, …), each with a hydraulic - resistance. -- **Pump** — pressure source. It checks its inlet reaches a reservoir, then - traverses downstream collecting resistance, static head (highest point above - the pump), open ends, dead ends and loops. - -Approximate delivered flow: - -``` -Q = rated_GPH × headFactor × resistanceFactor -headFactor = clamp(1 − head / maxHead, 0, 1) -resistanceFactor = 1 / (1 + R / 30) - -R(pipe) ≈ length / diameter⁴ -R(elbow) ≈ 1.2 × (angle/90) / diameter² -R(valve) ≈ 0.3 + restriction(% open); closed = blocks flow +```dotenv +PORT=3000 +JWT_SECRET=change-this-for-real-use +STRIPE_SECRET_KEY=sk_test_replace_me ``` -Diagnostics surfaced in the bottom panel: missing source, disconnected pump, -pump too weak for the elevation (head ≥ max head), bottlenecks, open pipe -ends (leaks), dead ends, closed valves, loops. Click a diagnostic to select -the offending part. Flow direction is rendered as animated arrows; flowing -pipes tint blue and the rate scales arrow speed. +Notes: -This is deliberately simple steady-state math — not CFD — and is designed to -be swapped out later (see below). +- `PORT` is for the backend API server. +- `JWT_SECRET` should be changed for any non-throwaway environment. +- `STRIPE_SECRET_KEY` is only needed if you are testing billing or checkout flows. + +## How to run it + +You have three useful ways to start the app. + +### Frontend only + +Use this when you are working on the builder UI, 3D scene, layout, snapping, or water visualization. + +```bash +npm run dev +``` + +Open: + +- [http://localhost:5173](http://localhost:5173) + +### Backend only + +Use this when you are debugging auth, saved projects, payments, or SQLite behavior. + +```bash +npm run server +``` + +API runs on: + +- [http://localhost:3000](http://localhost:3000) + +SQLite database file: + +- `server/database.sqlite` + +### Frontend and backend together + +This is the normal local setup. + +```bash +npm run dev:all +``` + +That starts: + +- Vite frontend on `5173` +- Express backend on `3000` + +## Build commands + +```bash +npm run typecheck +npm run build +npm run preview +``` + +What they do: + +- `typecheck`: TypeScript validation only +- `build`: production build into `dist/` +- `preview`: serve the production build locally + +## Builder workflow + +This app is only useful if the editing loop is fast. The current interaction model is: + +### Place and connect + +- click a part in the left library, then place it in the scene +- drag a part near another connector to snap +- green connectors mean joined +- amber connectors mean open + +### Manipulate runs + +- drag a body or gizmo to move a selected part +- double-click plumbing to grab the full run +- selected pipes expose stretch handles +- drag connector dots to snap endpoints +- use front or side views for vertical edits + +### Tune flow + +- select a pump +- adjust rated flow and max head in the inspector +- switch to `Water` mode to isolate active flow behavior +- use `Flow` to animate movement through the system + +### Diagnose problems + +The bottom diagnostics area will surface issues like: + +- disconnected pump inlet +- open drain / leaking end +- dead-end branch +- head too high for the selected pump +- closed or restrictive path +- loop or return behavior ## Project structure -``` -src/ -├── types.ts # Shared domain types (parts, sim, project file) -├── parts/ -│ └── catalog.ts # ★ Part catalog: defaults, params, connectors -├── store/ -│ └── builderStore.ts # Zustand store + undo/redo (BuilderState) -├── simulation/ -│ └── flowSimulator.ts # Graph build + pump physics + warnings -├── utils/ -│ ├── connectors.ts # World-space connector math, snap logic -│ ├── serializer.ts # Save/load/export/import (ProjectSerializer) -│ ├── demoProject.ts # Starter scene -│ └── dragState.ts # Transient drag context -├── components/ -│ ├── SceneCanvas.tsx # R3F canvas, cameras, grid, drag plane, measure -│ ├── PartMesh.tsx # Geometry for every part type + selection/drag -│ ├── FlowArrows.tsx # Animated flow-direction arrows -│ ├── Toolbar.tsx # Project actions, tools, view presets -│ ├── PartLibrary.tsx # Left sidebar -│ ├── PropertiesPanel.tsx # Right sidebar inspector -│ └── StatusPanel.tsx # Bottom simulation status -├── App.tsx # Layout, shortcuts, autosave, drag-drop -└── main.tsx +```text +. +├── src/ # React app, store, simulation, 3D scene, UI +├── server/ # Express API + SQLite bootstrap +├── docs/ # screenshots and design notes +├── dist/ # production build output +├── package.json +└── README.md ``` -Conventions: world units are **feet** (1 grid cell = 0.5 ft), pipe diameters -in **inches**, flow in **GPH** (shown with L/h). Rotations are radians (XYZ -euler) in state, degrees in the UI. +Important files: -## How to extend +- `src/App.tsx`: top-level app shell +- `src/components/SceneCanvas.tsx`: 3D scene and camera behavior +- `src/components/PartMesh.tsx`: part rendering and direct manipulation +- `src/store/builderStore.ts`: state, selection, undo/redo +- `src/simulation/flowSimulator.ts`: flow graph and pump logic +- `src/parts/catalog.ts`: part definitions and connector metadata -**Add a new part type** (e.g. a UV filter): -1. Add `'uvFilter'` to `PartType` in `src/types.ts`. -2. Add a catalog entry in `src/parts/catalog.ts` — defaults, inspector params - and `getConnectors()`. Add it to a category in `CATEGORIES` and (if it - carries water) to `FLOW_PARTS`. -3. Add a mesh case in `src/components/PartMesh.tsx`. -4. Give it a resistance in `partResistance()` in - `src/simulation/flowSimulator.ts`. +## Troubleshooting on Linux -That's it — placement, snapping, drag, save/load, inspector and simulation -pick it up automatically. +### `npm install` fails building native modules -**Improve the physics**: everything lives in `flowSimulator.ts`. The graph -build is separate from the flow estimate, so you can replace the single-pass -estimate with e.g. Hardy-Cross iteration or a linear solver over the same -graph without touching the UI. +Make sure these exist: -**Planned extension points** (the architecture already supports them): -- *Nutrient dosing* — add a `doser` part + per-edge concentration tracking in - the simulator (it already knows flow per part). -- *Plant growth zones / lighting / timers* — new part categories; timers can - gate `partResistance()` (a valve already shows how blocking works). -- *Bill of materials* — iterate `useBuilder.getState().parts` and group by - type/params; the catalog has labels and units. -- *Parts marketplace / AI assistant* — the project JSON (`ProjectFile`) is a - complete, validated serialization format for sharing and generation. +```bash +sudo apt install -y build-essential python3 make g++ +``` + +### Port 5173 or 3000 is already in use + +Find and kill the process: + +```bash +lsof -i :5173 +lsof -i :3000 +kill -9 +``` + +### Backend starts but auth or save features fail + +Check: + +- `.env` exists +- `JWT_SECRET` is set +- `server/database.sqlite` is writable + +### Water or 3D rendering looks broken + +Check: + +- browser console errors +- WebGL is enabled in the browser +- you are on a current Chrome, Chromium, or Firefox build + +## Current reality + +This is not CFD and it is not a full hydraulic solver. It is a fast builder with approximate flow behavior intended to make pipe-to-pipe editing, pump sizing, and obvious routing mistakes easy to see. + +That is the right tradeoff for this app right now. diff --git a/docs/hydro-builder-ui.png b/docs/hydro-builder-ui.png new file mode 100644 index 00000000..4bf36932 Binary files /dev/null and b/docs/hydro-builder-ui.png differ