VOID Repo Docs
Guide

Configuration

Environment variables, config files, feature flags


Overview

This page documents every environment variable, build-time setting, and runtime configuration option that controls VOID Repo Docs. Getting configuration right matters because the Express API Server will silently fall back to error states—or refuse to start meaningful work—if required provider keys are absent or if origins are mismatched. Whether you are running a local development server, splitting the front-end and API across separate hosts, or shipping an Android APK, this page tells you exactly which values to set and why.


Prerequisites

Before configuring VOID Repo Docs, ensure the following are available in your environment:

  • Node.js ≥ 18 — required by the Express API Server and build tooling
  • npm ≥ 9 — used for dependency installation and script execution
  • Git — needed to clone the repository
  • At least one AI provider API key — Gemini, Mistral, Groq, or OpenRouter; the application cannot generate documents without one
  • Android Studio + a compatible JDK — only required if you intend to build or deploy the Capacitor Android Bridge
  • A Google Cloud account with Cloud Run enabled — only required for production Cloud Run deployments

Installation

These steps bring the project from source to a running state. Configuration of environment variables happens after the build succeeds.

  1. Clone the repository and install dependencies:
git clone <your-repo-url>
cd <repo-directory>
npm ci
  1. Create your environment file. Copy the recommended block below into a .env file at the project root. Fill in at least one provider key:
NODE_ENV=production
APP_URL=https://app.example.com
GITHUB_TOKEN=
GEMINI_API_KEY=
MISTRAL_API_KEY=
GROQ_API_KEY=
OPENROUTER_API_KEY=
  1. Lint the TypeScript source to catch type errors before building:
npm run lint
  1. Build the production artifact. This compiles the Vite client and bundles the Express API Server with esbuild:
npm run build

The build pipeline runs:

vite build
esbuild server.ts --bundle --platform=node --format=cjs --packages=external

Successful output creates:

dist/
|-- assets/
|-- index.html
|-- server.cjs
`-- server.cjs.map
  1. Start the production server:
$env:NODE_ENV = "production"
npm start

On Linux/macOS:

NODE_ENV=production npm start
  1. (Android only) Sync the Capacitor Android Bridge and build the APK:
npm run android:apk

This command runs the full build, syncs Capacitor, and invokes Gradle's assembleDebug target in one step.


Configuration

Server-Side Environment Variables

These variables are injected at runtime into the Express API Server process. They are never embedded in the client bundle.

VariableRequiredDefaultEffect
NODE_ENVRecommendedundefinedSet to production to enable static serving of dist/ and single-page-app fallback routing. Any other value leaves the server in development mode.
APP_URLRecommendedundefinedThe exact public origin of your frontend (e.g., https://app.example.com). Must include scheme and port if non-standard. Not a wildcard or comma-separated list. Added to the CORS allowed-origins list. Omit only when the frontend and API share the same origin.
GEMINI_API_KEYConditionalundefinedAPI key for the Gemini provider (gemini-3.5-flash). Also the only key used for document refinement. Required if Gemini is your chosen or auto-selected provider.
MISTRAL_API_KEYConditionalundefinedAPI key for the Mistral provider (mistral-large-latest). Auto mode checks Mistral first; omitting all other keys while omitting this one causes Auto to select Mistral and immediately return a missing-key error.
GROQ_API_KEYConditionalundefinedAPI key for the Groq provider (llama-3.3-70b-versatile).
OPENROUTER_API_KEYConditionalundefinedAPI key for OpenRouter. OpenRouter is the only provider that performs model-level fallback across a candidate list; see the AI Providers reference for the fallback order.
GITHUB_TOKENOptionalundefinedPersonal access token used to fetch repository metadata for prompt construction. Without it, GitHub API rate limits apply to unauthenticated requests.

At least one provider key (GEMINI_API_KEY, MISTRAL_API_KEY, GROQ_API_KEY, or OPENROUTER_API_KEY) must be present for the application to generate any document.


Build-Time Client Variables (Vite)

These variables are read by Vite during npm run build and embedded into the compiled JavaScript bundle. Changing them after the build has no effect; you must rebuild.

VariableScopeEffect
GEMINI_API_KEYBuild-time onlyExposed to the React Web UI via process.env.GEMINI_API_KEY so the browser can call Gemini directly without routing through the Express API Server. This is the only key embedded in the bundle; treat it accordingly.
VITE_API_BASE_URLBuild-time onlyWhen running the frontend and API on separate hosts, set this to the Express API Server's public origin before building. Omit it for the default single-process deployment where both are served from the same Express process.

CORS Configuration

The Express API Server allows requests from the following origins by default:

  • http://localhost
  • https://localhost
  • capacitor://localhost — required for the Capacitor Android Bridge
  • The value of APP_URL, when set

Allowed HTTP methods: GET, POST, OPTIONS. Allowed headers: Content-Type, Authorization. Requests from any other origin receive no Access-Control-Allow-Origin header and are effectively blocked.


Port

The Express API Server listens on port 3000. It does not read a PORT environment variable. If your host requires a dynamic port, a code change is necessary before deployment. Configure your load balancer or reverse proxy to forward traffic to port 3000.


Capacitor Android Bridge

The Capacitor configuration lives in capacitor.config.ts:

const config: CapacitorConfig = {
  appId: 'com.c728.voidrepodocs',
  appName: 'VOID Repo Docs',
  webDir: 'dist'
};
FieldValueNotes
appIdcom.c728.voidrepodocsAndroid application identifier. Do not change without updating Play Store or sideload metadata.
appNameVOID Repo DocsDisplay name shown on the Android device.
webDirdistMust point to the Vite build output directory. Run npm run build before any Capacitor sync.

If VITE_API_BASE_URL or other frontend settings change, rebuild and re-sync before generating a new APK or AAB:

npm run build
npx cap sync android

Auto Provider Selection Order

When the provider field in a GenRequest is set to auto, the Express API Server checks available keys in this order:

  1. Mistral
  2. Gemini
  3. Groq
  4. OpenRouter

The first provider for which a key is found (either in customKeys on the request or in the server environment) is selected. Auto mode does not retry a different provider if the selected provider fails.


Usage

Running in Development

During development, the Express API Server and Vite dev server run together via tsx:

npm run dev

Hot module replacement (HMR) is enabled by default. To disable it (useful during automated edits), set DISABLE_HMR=true in your environment before running npm run dev. This also disables file watching to reduce CPU usage.


Supplying Provider Keys

You have two ways to provide AI provider credentials:

Option A — Server-side environment variables (recommended for shared or production deployments):

Set the relevant keys in your .env file or host secret manager. All users of the deployed instance share that quota.

GEMINI_API_KEY=your-gemini-key-here
MISTRAL_API_KEY=your-mistral-key-here

Option B — Custom API Keys per request (BYOK):

Pass a customKeys object in your GenRequest payload. The Express API Server prefers a key found in customKeys over the matching server environment variable. Keys submitted this way are stored in the browser's local storage in plain text by the React Web UI; use server-side keys for anything sensitive.

{
  "customKeys": {
    "gemini": "your-gemini-key",
    "mistral": "your-mistral-key"
  }
}

Splitting Frontend and API Across Hosts

By default, the Express API Server serves both the compiled React Web UI and the API from a single process on port 3000. To host them separately:

  1. Deploy the Express API Server to your backend host.

  2. Set VITE_API_BASE_URL to the backend's public origin.

  3. Set APP_URL on the server to the frontend's public origin.

  4. Rebuild the client so VITE_API_BASE_URL is embedded:

    VITE_API_BASE_URL=https://api.example.com npm run build
    
  5. Deploy the contents of dist/ (excluding server.cjs) to your static host.

Remember: VITE_API_BASE_URL is baked in at build time. Any change requires a full rebuild and redeployment of the frontend assets.


Building for Android

For a debug APK:

npm run android:apk

For a release APK:

npm run android:apk:release

For a release AAB (for Play Store submission):

npm run android:aab

Every Android build runs npm run build and npx cap sync android as part of the script. If your API endpoint or frontend configuration has changed, the Android build will pick up the latest values automatically.


Examples

Example 1 — Minimal .env for local development

A single provider key is sufficient to start generating documents locally.

NODE_ENV=development
GEMINI_API_KEY=AIza...

Start the dev server:

npm run dev

Expected console output (approximate):

Server listening on port 3000

Example 2 — Full production .env

This configuration enables all four providers, a GitHub token for richer repository metadata, and the correct APP_URL for CORS.

NODE_ENV=production
APP_URL=https://app.example.com
GITHUB_TOKEN=ghp_...
GEMINI_API_KEY=AIza...
MISTRAL_API_KEY=...
GROQ_API_KEY=gsk_...
OPENROUTER_API_KEY=sk-or-...

Start the production bundle:

$env:NODE_ENV = "production"
npm start

Expected behavior: The Express API Server serves the React Web UI from dist/ and accepts API requests at port 3000. CORS allows requests from https://app.example.com.


Example 3 — Sending a GenRequest with custom keys (BYOK)

This example uses curl to call the Express API Server directly, supplying a Gemini key per-request rather than relying on the server environment.

curl -X POST http://localhost:3000/api/generate \
  -H "Content-Type: application/json" \
  -d '{
    "documentType": "PRIVACY_POLICY",
    "targetPlatform": "ANDROID",
    "tone": "Formal",
    "length": "medium",
    "provider": "gemini",
    "customKeys": {
      "gemini": "AIza..."
    },
    "repoUrl": "https://github.com/example/my-app",
    "appDetails": {
      "name": "My App"
    }
  }'

Expected response shape (GenResponse):

{
  "document": "# Privacy Policy\n\n...",
  "documentType": "PRIVACY_POLICY",
  "targetPlatform": "ANDROID",
  "tone": "Formal",
  "length": "medium",
  "provider": "gemini"
}

Example 4 — Split-host build embedding VITE_API_BASE_URL

VITE_API_BASE_URL=https://api.example.com npm run build

After the build, dist/assets/*.js contains the hardcoded API origin. Deploy dist/ to your CDN or static host. The Express API Server at https://api.example.com must have APP_URL=https://frontend.example.com set to allow CORS from the frontend origin.


Example 5 — Android debug APK build

npm run android:apk

This command internally runs:

npm run build
npx cap sync android
powershell -NoProfile -ExecutionPolicy Bypass -File ./scripts/android-gradle.ps1 assembleDebug

Expected output: a debug APK file in the Android Gradle build output directory (android/app/build/outputs/apk/debug/), ready for sideloading onto a device.


Troubleshooting

Issue: Server starts but every generation request returns 400 Missing key

Symptom: The Express API Server is running, but all POST requests to the generate endpoint return HTTP 400 with a message about a missing provider key.

Likely cause: No provider key is set in the server environment, and no customKeys object was included in the GenRequest. When provider is auto and no key is found, Auto selects Mistral and immediately returns a missing-key error.

Fix: Add at least one key to your .env file and restart the server:

GEMINI_API_KEY=AIza...

Issue: CORS errors in the browser (No 'Access-Control-Allow-Origin' header)

Symptom: The React Web UI loads, but API calls fail in the browser console with a CORS error.

Likely cause: The APP_URL environment variable is not set, is set to the wrong value, or does not exactly match the browser's origin (including scheme and port).

Fix: Set APP_URL to the exact origin the browser is using, then restart the server. For example:

APP_URL=https://app.example.com

Do not use a trailing slash, a wildcard, or a comma-separated list. A single exact origin is required.


Issue: VITE_API_BASE_URL changes are not reflected in the running app

Symptom: After updating VITE_API_BASE_URL, the React Web UI still sends requests to the old API origin.

Likely cause: VITE_API_BASE_URL is embedded at build time. Changing it in .env after the build has no effect on an already-compiled bundle.

Fix: Rebuild the client after updating the variable:

npm run build

For Android, rebuild and re-sync:

npm run android:apk

Issue: Android APK build fails after changing the API URL

Symptom: The APK launches but cannot reach the Express API Server, or the Gradle build references a stale endpoint.

Likely cause: The Vite build was not re-run before cap sync, so the Capacitor Android Bridge copied an outdated dist/ into the Android project.

Fix: Always use the composite npm scripts, which run the full build and sync automatically:

npm run android:apk

Do not run npx cap sync android in isolation if you have changed any frontend configuration.


Issue: Provider returns HTTP 429

Symptom: Generation requests fail with HTTP 429 and a rate-limit message.

Likely cause: The provider key (server-side or custom) has exceeded its request quota. On a shared deployment, all users share a single server-side key's quota.

Fix:

  • Switch to a different provider by setting provider in your GenRequest.
  • Use per-user Custom API Keys (customKeys in the GenRequest) so each user consumes their own quota.
  • Configure billing alerts and rate limits with your provider before exposing the service publicly.
  • For OpenRouter specifically, note that free-tier model availability is volatile; check the candidate fallback list in the AI Providers reference.

Issue: npm run build succeeds but npm start cannot find dist/server.cjs

Symptom: Running npm start after a clean checkout throws a module-not-found error for dist/server.cjs.

Likely cause: The build step was skipped, or npm run clean removed the dist/ directory without a subsequent build.

Fix: Run the full build pipeline before starting:

npm ci
npm run lint
npm run build
npm start

Issue: HMR causes flickering or unexpected reloads during development

Symptom: The Vite dev server triggers excessive hot-module reloads, causing the React Web UI to flicker.

Likely cause: File watching is active and picking up changes from an automated process or editor.

Fix: Disable HMR and file watching by setting DISABLE_HMR=true before starting the dev server:

DISABLE_HMR=true npm run dev

This is intentional behavior documented in vite.config.ts to prevent flickering during agent-driven edits.

VOID Repo Docs | VOID Repo Docs Docs | Git2Docs