NovaCraft Balance Engine — Developer Reference
A full-stack game data management and balance tooling suite for NovaCraft — a sci-fi survival crafting game where players scavenge resources, build infrastructure, and craft components to repair a crashed spaceship. This workbench is the single source of truth for all item data, recipes, and progression balance before it reaches Unity.
CraftFlow is a Node.js / Express web app that acts as a live design and balancing dashboard sitting on top of the novacraft_db MariaDB database.
Instead of editing raw SQL or spreadsheets, designers and engineers use this UI to create and tune every game entity — items, crafting recipes, crafting stations, smelter recipes, and fuel types — and then export the resulting dataset directly to Unity as a structured JSON file.
All CRUD operations write directly to novacraft_db via a MariaDB connection pool.
Static analysis flags broken recipes, pacing regressions, inverted cost hierarchies, and missing unlock triggers.
GitHub Models (GPT-4o) reads your registry and proposes new items. Approve them with one click to inject them into the live DB.
| Layer | Technology | Location | Role |
|---|---|---|---|
| Server | Node.js + Express | server.js | HTTP server, mounts all API routers, serves static frontend |
| Database | MariaDB + mariadb npm | config/database.js | Connection pool; call pool.getConnection() in every route |
| API Routes | Express Router | routes/ | One file per domain — items, recipes, stations, smelter, analysis, suggestions, export, migration |
| Services | Plain JS modules | services/ | Pure logic decoupled from Express — e.g., smelterAnalysisService.js |
| Frontend | Vanilla JS + Tailwind v2 | public/ | Single-page tab layout. Modules loaded via <script> tags in dependency order |
| AI Layer | @azure-rest/ai-inference | routes/suggestions.js | Calls GitHub Models endpoint with designer constraints; returns structured JSON |
git clone https://<your-gitea-host>/jicwah60826/NovacraftDB.git cd NovacraftDB
npm install
Key packages: express, mariadb, body-parser, @azure-rest/ai-inference, @azure/core-auth.
The app expects the following variables at runtime — set them in your Docker / Unraid container environment or a .env file (add dotenv if needed):
| Variable | Required | Description |
|---|---|---|
| DB_HOST | Yes | MariaDB host (e.g. 192.168.1.x or mariadb) |
| DB_USER | Yes | MariaDB username |
| DB_PASSWORD | Yes | MariaDB password |
| DB_NAME | Yes | Should be novacraft_db |
| GITHUB_TOKEN | AI only | GitHub Personal Access Token — required only for the AI Design Assistant |
On first run, click ⚙️ Run DB Migration in the top-right header. This is safe to re-run at any time — it only adds missing tables and columns, it never destroys data.
node server.js # → CraftFlow Balancing engine running on port 3000
Then open http://localhost:3000 in your browser. For development, consider using nodemon server.js for auto-restart on file changes.
All tables live in novacraft_db. The migration endpoint (POST /api/db/migrate) keeps the schema up to date automatically.
item_id (PK) · display_name · tier · is_craftable · calculated_value · base_tta · requires_unlock · unlocked_by_default · unlock_trigger · unlock_trigger_ref · crafting_time
The core entity. Every craftable item, raw resource, consumable, and equipment piece lives here. calculated_value is derived from the item's recipe tree labor cost and is used by the Balance Advisor.
recipe_id (PK) · output_item_id (FK → items) · smelt_duration_seconds
One row per craftable item's recipe. Linked to its ingredients via recipe_ingredients.
recipe_id (FK → recipes) · ingredient_item_id (FK → items) · quantity
Many-to-many junction table. Each row is one ingredient line in a recipe.
fuel_types defines burn duration; smelter_recipes maps input → output items with a smelt duration.
The primary data entry tab. Use the form on the left to add new items or edit existing ones. The table on the right lists every item in the database.
SCREAMING_SNAKE_CASE (auto-formatted) and globally unique — this is the primary key used in Unity.Register and manage crafting recipes independently of items. Each recipe has a unique Recipe ID, an output item, and one or more ingredient rows.
is_craftable = 1 but has no recipe, the Balance Advisor will flag it as an Error.Crafting stations are the in-world structures the player builds to unlock recipe categories (e.g., a Fabricator, a Med Bay, an Engineering Bench). Register stations here and assign them to recipe categories.
Manages the smelting sub-system separately from the crafting system. Two forms are available:
The most important tab for maintaining a healthy game economy. Contains two panels:
Click ▶ Run Analysis to scan the full database. Flags are colour-coded:
Each flag has an ✏️ Edit Item shortcut that loads the offending item directly into the Items form.
Uses GitHub Models (GPT-4o) to generate new item suggestions contextualised to your existing registry. Configure all 8 constraint controls before generating:
Review each card and click ✅ Approve & Inject to write the item directly to novacraft_db. Then return to the Items tab to assign a recipe if needed.
⚠️ Requires a valid GITHUB_TOKEN environment variable.
A read-only master spreadsheet of every item in the database. Use the search box to filter by name or ID. Useful for a quick audit before running a balance pass or exporting to Unity.
Sends a POST /api/db/migrate request that applies any pending schema changes (new columns, new tables). Always run this after pulling changes from the repository that include schema updates. It is fully idempotent — safe to run multiple times.
Downloads the entire item registry as novacraft_items_export.json via GET /api/export/unity. Drop this file into the Unity project's StreamingAssets/ folder to update the game's data at runtime.
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/data | Fetches full workspace state (all items, recipes, stations, etc.) in one call |
| GET | /api/items | List all items |
| POST | /api/items | Create a new item |
| PUT | /api/items/:id | Update an existing item |
| DELETE | /api/items/:id | Delete item and any recipes that output it |
| GET | /api/recipes | List all recipes with their ingredients |
| POST | /api/recipes | Create a new recipe |
| DELETE | /api/recipes/:id | Delete a recipe |
| GET | /api/stations | List all crafting stations |
| GET | /api/fuel-types | List all fuel types |
| GET | /api/smelter-recipes | List all smelter recipes |
| GET | /api/balance/analysis | Run full balance static analysis — returns flags array + summary |
| GET | /api/smelter/analysis | Run smelter economy analysis |
| GET | /api/suggest | AI item suggestions — accepts query params: tier, acquisition, purpose, theme, rarity, complexity, requiresUnlock, count |
| GET | /api/export/unity | Download full item registry as Unity-ready JSON file |
| POST | /api/db/migrate | Run idempotent DB schema migration |
routes/myFeature.js using express.Router().pool.getConnection() inside a try/catch and release it with conn.end() in the finally block.server.js with app.use('/api', require('./routes/myFeature')).services/myFeatureService.js pure function and import it into the route.public/js/ in the appropriate subdirectory (renders/, editors/, forms/, analysis/).<script src="..."> tag at the bottom of public/index.html. Load order matters — the comment block documents the required order: state → utils → renders → editors → forms → analysis → api → app.runSmelterAnalysis not just run).All item IDs must be SCREAMING_SNAKE_CASE — e.g., HULL_PATCH_KIT, ENGINE_MANIFOLD_MK2. The form field auto-uppercases input. This ID is the stable reference used in Unity ScriptableObjects and must never change once an item is in production.
The JSON structure exported by GET /api/export/unity is consumed directly by ItemData.cs in Unity. If you add a new column to the items table, you must also update the export route and the Unity ScriptableObject to match.