Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ storybook-static

# local state
.env
.env.local
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,8 @@ Docs live separately in `humanode-network/vortex-simulator-docs`.
- `dist/` is generated build output.
- UI expects the API at `/api/*`. During local dev, Rsbuild proxies `/api/*` to `http://127.0.0.1:8788` by default (override with `API_PROXY_TARGET`).
- To point the UI at a different API host, set `RSBUILD_PUBLIC_API_BASE_URL` at build time or serve `public/vortex-config.json` with `{"apiBaseUrl":"https://api.example.com"}`.

## Local env file

- `.env.local` is the local runtime config.
- Start with one command: `yarn dev:local`.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"packageManager": "yarn@4.11.0",
"scripts": {
"dev": "rsbuild dev --open",
"dev:local": "node scripts/dev-local.mjs",
"build": "rsbuild build",
"preview": "rsbuild preview",
"test": "RSTEST=1 rstest",
Expand Down
55 changes: 55 additions & 0 deletions scripts/dev-local.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { spawn } from "node:child_process";
import { existsSync, readFileSync } from "node:fs";
import { resolve } from "node:path";
import { fileURLToPath } from "node:url";

const __dirname = fileURLToPath(new URL(".", import.meta.url));
const rootDir = resolve(__dirname, "..");

function parseEnvFile(filepath) {
const content = readFileSync(filepath, "utf8");
const out = {};
for (const line of content.split(/\r?\n/)) {
const trimmed = line.trim();
if (!trimmed || trimmed.startsWith("#")) continue;
const equalIndex = trimmed.indexOf("=");
if (equalIndex <= 0) continue;
const key = trimmed.slice(0, equalIndex).trim();
const rawValue = trimmed.slice(equalIndex + 1).trim();
const unquoted =
(rawValue.startsWith('"') && rawValue.endsWith('"')) ||
(rawValue.startsWith("'") && rawValue.endsWith("'"))
? rawValue.slice(1, -1)
: rawValue;
out[key] = unquoted;
}
return out;
}

function loadLocalEnv(filepath) {
if (!existsSync(filepath)) return;
const values = parseEnvFile(filepath);
for (const [key, value] of Object.entries(values)) {
process.env[key] = value;
}
}

const envPathArg = process.argv.find((arg) => arg.startsWith("--env="));
const envPath = envPathArg
? envPathArg.slice("--env=".length)
: resolve(rootDir, ".env.local");
loadLocalEnv(envPath);

process.env.API_PROXY_TARGET ??= "http://127.0.0.1:8788";

const child = spawn("yarn", ["dev"], {
cwd: rootDir,
stdio: "inherit",
env: process.env,
});

child.on("exit", (code) => process.exit(code ?? 1));
child.on("error", (error) => {
console.error(error instanceof Error ? error.message : String(error));
process.exit(1);
});
2 changes: 2 additions & 0 deletions src/app/AppRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Invision from "../pages/invision/Invision";
import Vortexopedia from "../pages/Vortexopedia";
import Factions from "../pages/factions/Factions";
import Faction from "../pages/factions/Faction";
import FactionCreate from "../pages/factions/FactionCreate";
import ProposalPP from "../pages/proposals/ProposalPP";
import ProposalChamber from "../pages/proposals/ProposalChamber";
import ProposalFormation from "../pages/proposals/ProposalFormation";
Expand Down Expand Up @@ -46,6 +47,7 @@ const AppRoutes: React.FC = () => {
<Route path="feed" element={<Feed />} />
<Route path="profile" element={<Profile />} />
<Route path="factions" element={<Factions />} />
<Route path="factions/new" element={<FactionCreate />} />
<Route path="factions/:id" element={<Faction />} />
<Route path="human-nodes" element={<HumanNodes />} />
<Route path="human-nodes/:id" element={<HumanNode />} />
Expand Down
Loading