The Open Source AI Platform for Funding & Business Consultants
OpenBcon helps consultants, advisors, incubators, and funding teams run the full workflow in one place:
- discover funding programs
- assess business readiness
- manage company and client records
- generate funding-ready business plans
- organize applications, templates, resources, and reports
Community edition:
AGPL-3.0-or-laterCommercial licensing available for private deployments, closed-source modifications, white-label/OEM distribution, implementation services, and ongoing support.
See COMMERCIAL-LICENSE.md and CLA.md.
Version 3.0.1 makes administrator-triggered updates deterministic and clears stale browser state after a successful installation:
- Install update backs up the production environment file, force-replaces the
checkout with
origin/main, and preserves database volumes. - Admin Console clears Cache Storage, service workers,
localStorage, andsessionStorageafter the new services are healthy, then reloads with a cache-busting URL. - The update status reports the installed release label and explains that a locally stored browser session must sign in again after the refresh.
Version 3.0 expands the funding catalog experience and makes the workspace Grants & Loans page independent from the interface language:
- Grants & Loans now loads every active program language from the shared catalog. English and Chinese program records remain associated with their own data sources instead of being filtered by the user's workspace language.
- The Grants & Loans directory displays at most 12 programs per page, with pagination that resets when search or filters change.
- Data-source names shown on funding cards use the latest Admin Console configuration, so renamed sources are reflected without re-importing records.
- Existing language-specific API consumers continue to receive their requested language; the all-language catalog query is used only by Grants & Loans.
Version 2.5.6 improves local build visibility and Admin Console update feedback:
- Local Vite development and builds automatically read the current Git tag and
commit when deployment environment variables are not provided, so the
Updates page does not incorrectly show
Unreleasedfor a tagged checkout. Install updatenow explains when updates have not been checked, no newer build is available, the update service is not configured, or no target build was returned.- The install action remains available until an update is actually running, so administrators receive feedback instead of silently clicking a disabled button.
Version 2.5.5 completes first-admin provisioning during VPS bootstrap:
- Setup Wizard validates and stores the initial admin email and password for one-time server-side provisioning.
- The deployment creates the administrator with the
adminrole in the Shared, Test, and Live PostgreSQL databases, so the same credentials work after switching between Test Mode and Live Mode. - The initial password is stored only as a bcrypt hash in each database and
the one-time bootstrap values are removed from
deploy/.env.productionafter successful provisioning. - Setup status explicitly reports administrator creation and continues to the public HTTPS and API health checks.
Version 2.5.4 fixes funding data-source synchronization in the workspace:
- Google Sheets and Airtable funding records are now persisted to the shared PostgreSQL catalog instead of only being kept in browser cache.
- External catalog records are upserted by source and record identity, and records omitted from a completed sync are archived.
- JSON catalog field mappings are used consistently for duplicate detection.
- A local API proxy failure now explains that the API on port
8787must be running instead of presenting an opaque502import error.
Version 2.5.3 makes the installed release visible immediately after an administrator-triggered update:
- Deployment metadata is always regenerated from the current Git checkout, so stale commit or release values cannot be inherited from an older container.
- Application services are force-recreated after an update to ensure the new frontend bundle is running.
- Admin Console reloads after a successful update so the current build shows
the installed release tag, such as
2.5.3.
Version 2.5.2 fixes production updates when the private update agent runs Docker Compose from inside its updater container:
- Caddy configuration mounts now resolve through the VPS checkout path instead
of the updater container's
/workspacepath. - Existing Traefik proxy overrides are normalized automatically before Compose validates them, so deployments created by older releases can update safely.
- Database and Caddy data volumes are preserved; the fix does not delete application data.
Version 2.5.1 makes release status easier to understand:
- Admin Console Updates displays the current and latest release tags, such as
2.5.1, instead of exposing an internal commit hash as the primary build label. - Tagged deployments receive their release version automatically during the
Docker build; untagged development builds are labeled
Unreleased. - Commit hashes remain available to the update service for safe comparison and fast-forward installation.
Version 2.5 improves production operations and large catalog synchronization:
- Admin Console can check for and install fast-forward updates through a private, administrator-only update agent.
- JSON funding catalogs sync in bounded batches, so large U.S. Grants and similar sources do not exceed the API request limit; old records are archived only after the final batch completes successfully.
- Deployment health checks now report actionable service and HTTPS failures, while the bootstrap wizard shows generated database credentials and next steps.
After updating a deployment, rebuild the API service so the new synchronization logic is active:
docker compose \
--env-file deploy/.env.production \
-f deploy/docker-compose.production.yml \
up -d --build apiOpenBcon 2.0.0 adds a guided deployment experience for arbitrary customer domains. It includes the Admin Console Deployment Setup wizard and the secure Bootstrap Setup flow that runs before the application is configured. Operators can choose the public domain, HTTPS/proxy plan, and initial Test or Live Mode; the VPS generates database credentials and the application encryption key, then continues into the normal Docker deployment.
The release also includes account registration, login, password reset, multilingual workspace support, real funding-program discovery, company records, Quick Build, and configurable Strategic Report generation with business, technology, and financial sections.
The release has been verified locally with an end-to-end Test Mode walkthrough: register a user, sign in, reset the password, select a real funding program, create a company, launch Quick Build, and open the generated Strategic Report. Test Mode uses the deterministic mock gateway and test data stores; it does not send requests to an external LLM or payment provider. Configure Live Mode and server-side provider credentials before using real generation or payments.
Release validation commands:
npm run check
npm audit --omit=dev --audit-level=moderate
git diff --checkLatest local smoke validation also starts the Node API and checks the workspace
routes with real catalog data. The API health check returned 200, Grants &
Loans loaded 2,545 active programs (2,326 grants and 219 loans), Programs
loaded the same catalog, the Dashboard showed a dynamic date and greeting, and
the Guide and Templates Preview dialogs opened and closed successfully.
The shared catalog migration safely consolidates older workspace-scoped
duplicates before enforcing the global (source_id, source_record_id) unique
index. Existing application and package references are retargeted to the
canonical program record during the migration.
The final local check passed with 14 test files and 77 tests, followed by a successful TypeScript and Vite production build. Lint reports only the existing React Fast Refresh and hook-dependency warnings.
Funding consultants and business advisors still spend too much time on repetitive work:
- searching and comparing grant or loan programs
- collecting company information from clients
- rewriting business plans and funding narratives
- tracking applications, deadlines, and next actions
- building reports and export packages manually
OpenBcon turns that fragmented process into one AI-assisted workspace.
OpenBcon is designed for teams that help businesses secure funding:
- funding consultants and grant writers
- business advisors and coaches
- incubators and accelerators
- economic development organizations
- partner networks, internal advisory teams, and multi-client workspaces
- AI business plan generation: turn company and funding-program context into a structured funding-ready package
- Configurable Strategic Report: run section-by-section generation with admin-managed sections, document types, agents, roles, prompts, and ordering
- Reusable report layouts: configure cover-page and main-content CSS declarations in Admin Console with a live preview, then assign those layouts to Strategic Report sections
- Funding readiness workflows: assess strengths, risks, and missing inputs before submission
- Discovery scouting reports: compare each funding program against a selected company with fit scoring, positive signals, reviewer concerns, and a recommended next move
- Configurable program matching: score opportunities with a shared weighting model for eligibility fit (50%), company profile completeness (20%), policy match (20%), and document readiness (10%)
- Client and company management: organize founder profiles, business details, and working records
- Funding program database: manage grants, loans, and opportunity sources in one directory
- Partner and admin workspace: configure modules, branding, landing-page content, legal links, data sources, models, payment settings, and workspace behavior
- Resource and template libraries: centralize templates, social resources, tools, and reusable content
- Google Sheets and Airtable integrations: connect external resource sources with admin-managed sync
- Open-source customization: self-host, extend, rebrand, or commercialize under the project's dual-license model
- Multilingual workspace UI: English (Canada), French (Canada), and Simplified Chinese locale support
The original English catalogs remain unchanged in public/funding_programs_complete.json and
public/loan_programs_complete.json. Simplified Chinese catalogs are provided separately as
public/funding_programs_complete.zh-CN.json and public/loan_programs_complete.zh-CN.json.
Enable and sync the two Chinese JSON data sources in Admin Console > Data Sources. The records
are stored in funding_programs with language = 'zh-CN', and the Grants & Loans and Funding
Shortlist pages request only the catalog matching the active workspace language. Test and Live
mode continue to use their respective databases.
The repository currently includes three product surfaces:
/- public landing page/dashboard- user workspace/admin- platform configuration console, including Strategic Report setup
Every workspace module uses a flat route such as /discovery, /quick-build, /strategic-reports, /my-applications, and /grants-loans.
Built-in auth entry flows are also included for /login, /signup, /forgot-password, and /reset-password.
Live demo and short product walkthroughs are planned. Until then, the repository includes a visual snapshot of the current product experience.
![]() Landing Page | ![]() Landing Page 2 | ![]() Dashboard Overview |
The current repository snapshot includes the landing experience, dashboard workspace, directories, and Quick Build flow.
![]() Discovery | ![]() Quick Build | ![]() Quick Build - Result Preview |
![]() My Companies | ![]() Funding Shortlist | ![]() My Applications |
![]() Grants & Loans | ![]() Templates | ![]() Social Resources |
![]() Tools | ![]() Settings | ![]() Admin Console |
- Responsive landing page and dashboard shell
- Mobile drawer navigation and collapsible sidebar groups
- Consistent Dashboard-style topbars across workspace pages, with clear page names and supporting descriptions
- Configurable branding, logo, and public messaging
- Admin-managed landing page header, content, footer navigation, and legal-link configuration
- Admin-managed pricing catalog with free, monthly, annual, and one-time offers
- Billing settings surface with current subscription, pricing options, and transaction history
- Module and Partner Portal feature flags
- Searchable and filterable listing views with record details
- Three-step Quick Build workflow with validation, company import, application restore, and generated previews
- Discovery presents one program-matching scouting report card at a time, with company switching, program profiles, match indicators, and non-circular Previous/Next navigation
- Discovery displays the match score as a dynamic progress ring with the score rendered inside the circle
- Discovery cards expose the company profile used for matching, including legal structure, sector, industry, stage, products or services, funding usage, seasonal periods, mission, vision, values, and team information
- Discovery, Dashboard, and Funding Shortlist use the same unified matching calculator and the active company context
- Dedicated Strategic Reports route (
/strategic-reports) for reopening the latest generated package outside the form flow - Funding Shortlist route (
/funding-shortlist) for reviewing shortlisted grants, loans, and other funding opportunities - Strategic Report generation driven by configurable sections, document types, agents, roles, prompts, and workflow ordering
- Admin-managed Strategic Report layouts with editable names, descriptions, CSS declarations, and live previews
- Funding Shortlist opportunities materialized as applications with funding-program step data prefilled
- My Applications and Quick Build use the unique external
app_idin links and API requests - Google Sheets and Airtable funding data-source integrations
- Admin data-source search, create, edit, delete, enable, and manual sync controls
- Admin Console Matching settings for top-level score weights and eligibility/policy sub-weights, persisted with the shared platform configuration
- Dynamic Grants & Loans directory with source attribution and Quick Build import
- Grants & Loans catalog with all active data-source languages and 12-program pagination
- PostgreSQL domain data plus MongoDB-backed dynamic configuration and workspace state
- One Strategic Report per application, persisted in
strategic_reportswith LangGraph trace and final result data - Three-year, 36-month financial forecasts with monthly revenue and expense rows, annual summaries, and Strategic Report visualizations
- Financial forecast line-item tables open on Year 1 and switch between Year 1, Year 2, and Year 3 twelve-month views from the annual summary cards
- Database migrations, demo seed data, audit logs, and Docker Compose setup
- Admin Console update checks compare the stamped build commit with the latest GitHub
maincommit - Route-specific titles, metadata, and a dedicated 404 page
- Vitest checks and a GitHub Actions verification workflow
- Dual-license foundation for open-source and commercial distribution
This is a directional roadmap rather than a release commitment. Priorities may change as contributors, advisors, and self-hosting teams provide feedback.
- Add release metadata and changelog links to the Admin Console update check
- Improve production operations with backup verification, migration checks, and expanded health monitoring
- Add Strategic Report version history, retry controls, and clearer generation diagnostics
- Improve collaborative workspace permissions, invitations, and activity history
- Expand automated tests for generation, persistence, authentication, and responsive layouts
- Add more funding-catalog connectors and scheduled sync observability
- Extend financial planning with editable assumptions, scenario comparisons, and export-ready forecast formats
- Add structured Strategic Report cover-page rendering with report metadata, centered layout, and brand accent
- Add richer document editing, review comments, and package export workflows
- Render matching cover pages and page breaks in the web preview, DOCX, and PDF exports
- Add administrator controls for cover logos, backgrounds, themes, and alignment options
- Expand localization beyond English (Canada), French (Canada), and Simplified Chinese
- Publish stable integration APIs and webhooks for partner workflows
- Create a database-backed Consulting Templates catalog with template keys, descriptions, categories, enablement, required company fields, and report type
- Connect each template to the existing Admin Console configuration for document types, sections, prompts, agents, priorities, and layouts
- Add template versioning so new reports always use the latest configuration, while generated reports retain the configuration snapshot used for audit and reproducibility
- Generalize
strategic_reportsfor consulting reports withreport_type,template_id,template_version, andcompany_id; allowapplication_idto be optional when a report is not funding-specific - Add a Consulting Templates page where users choose a template, select a company, review missing information, and start a report
- Add a generic consulting-report API and LangGraph workflow for loading the latest template, validating company data, analyzing the company, generating sections by priority, running review, compiling the report, and saving token usage
- Add Admin Console controls to create, edit, delete, enable, disable, and preview consulting templates without hardcoding report structures in the UI
- Reuse Strategic Report editing, regeneration, layout preview, PDF/DOCX/XLSX export, report history, and report navigation for consulting reports
- Add the first consulting template set: Digital Transformation, AI Readiness, Market Entry, Manufacturing Assessment, Retail Growth, Restaurant Expansion, Healthcare Clinic Review, SaaS Go-to-Market, ESG Assessment, and Due Diligence
- Add template validation and clear errors for deleted or missing agents, sections, document types, prompts, and layouts; do not silently fall back to stale configuration
- React 19
- TypeScript
- Vite
- React Router
- Oxlint
- Express
- PostgreSQL 17
- MongoDB 8
- i18next and react-i18next
- Zod
npm install
npm run db:setup
npm run devOpen http://localhost:5173.
Copy .env.example to .env before changing database credentials or ports.
Start both database services before migrating state:
docker compose up -d postgres mongodb
npm run db:migrate-state-to-mongo
npm run db:migrate
npm run db:seednpm run db:setup runs the same migration and seed steps after the database
services are available. npm run dev starts the API on port 8787, Vite on
port 5173, and a local update agent bound only to 127.0.0.1:8788. This makes
the local checkout act like a deployment for testing Admin Console's
Check updates and Install update flow. Local updates replace the
checkout with origin/main, run npm install, and rebuild the app; they do not
run the VPS Docker deployment. Run npm run dev:api and npm run dev:web manually
only when you do not need the local update flow.
Run npm run dev, rather than only npm run dev:web, when using Admin Console
data-source synchronization. Vite proxies /api/* to the API on port 8787;
if that API is stopped, the browser will receive 502 Bad Gateway. Verify the
API before retrying a sync:
curl -i http://localhost:8787/api/healthThe response should be HTTP/1.1 200 OK with {"status":"ok"}. A successful
funding-source sync updates the PostgreSQL catalog and also refreshes the
browser cache for fast page loads.
For the Python AI backend used by the model connection chat, create the
Python environment described in python-backend/README.md, then run
npm run dev:python in a second terminal. It listens on port 8010.
If the browser shows a blank page immediately after renaming or moving a source
module, stop and restart npm run dev so Vite rebuilds its module graph. Then
reload the page. A successful npm run build confirms that the source imports
resolve correctly.
The workspace UI supports English (Canada), French (Canada), and Simplified Chinese. Change the language from Settings; the preference is persisted for the current browser profile and is used for workspace labels, dates, numbers, currency formatting, and generated forecast language.
OpenBcon keeps provider keys and application encryption secrets on the server.
Admin configuration is redacted before it is returned to the browser, and
production session cookies are HttpOnly, Secure, and SameSite=Lax.
Production startup rejects placeholder encryption keys, wildcard or local CORS
origins, and demo-data seeding. The Python service also fails closed if its
production CORS configuration is missing or is not an explicit HTTPS origin.
Configured AI endpoints are restricted to the allowlisted provider hosts by default, and private AI endpoints are disabled in production. PostgreSQL, MongoDB, Ollama, and the internal API services are kept on the private Docker network; only the reverse proxy is exposed publicly.
Before deploying, run the checks locally:
npm audit --omit=dev --audit-level=moderate
python-backend/.venv/bin/python -m pip install pip-audit # one-time audit tool
python-backend/.venv/bin/pip-audit -r python-backend/requirements.txt
npm run checkThe current audit baseline is zero reported vulnerabilities for both production
and development dependencies. Re-run the dependency audits after dependency
updates or before a release; do not use npm audit fix --force without reviewing
the resulting major-version changes.
The repository includes a Docker deployment with these services:
api: the built React application and Express API on the private Docker networkpython: the FastAPI/LangGraph generation service on the private Docker networkollama: optional private local LLM runtime, enabled only withENABLE_OLLAMA=truepostgresandmongodb: persistent application data servicescaddy: same-origin routing for/apiand/ai-apiupdater: private, token-protected update agent used by Admin Console
The default Compose file lets Caddy own public ports 80 and 443. If a VPS
already uses Hostinger Traefik on those ports, Caddy can instead listen on
127.0.0.1:8080 while Traefik owns public HTTPS. The complete setup and
troubleshooting steps are documented here:
Admin Console includes a Deployment Setup wizard for deployments that use
separate public and dashboard domains. It validates both hostnames, lets you
choose whether Caddy or an existing Traefik instance owns HTTPS ports 80/443,
selects the initial Test or Live Mode, and generates a server-side environment
template plus deployment commands. The wizard keeps only non-secret draft values in the current browser;
the database administrator username is fixed as admin; passwords are generated inside the VPS and shown once
on the result page. API keys, SMTP credentials, and OAuth secrets must still be
entered in deploy/.env.production on the VPS. The wizard prepares the
configuration but does not remotely execute Docker commands.
For a fresh VPS, the same setup is also available before the application is running. Execute:
./deploy/deploy.shWhen deploy/.env.production is missing, the script starts a one-time
Bootstrap Setup page on the VPS temporary port 8090 and waits for the form to
be saved. Open the one-time public URL printed by the script, enter the public
domain, dashboard domain, admin email, admin password, proxy plan, and initial
mode, then save. The admin
email becomes the first OpenBcon administrator account, and the setup page
requires a 12-character minimum password. The setup URL is
protected by a one-time token and expires after 24 hours. If the VPS firewall
blocks it, temporarily allow inbound TCP 8090 while configuring, then close
that port after setup completes. The script sets the database administrator
usernames to admin, generates the passwords and encryption key on the VPS,
and displays the database credentials
once so they can be stored securely, writes deploy/.env.production, creates
the initial administrator account in Shared, Test, and Live databases, and
continues with the normal database migration and Docker startup. To reconfigure an existing
deployment, run ./deploy/deploy.sh --setup; the previous environment file is
backed up before it is replaced. Both domains must have A records pointing to
the VPS first: the public domain serves the landing page and public program
directory, while the dashboard domain serves sign-in, the workspace, and Admin
Console. If an external Traefik owns ports 80/443, it must route both selected
domains to 127.0.0.1:8080; the bootstrap step creates the OpenBcon Caddy
override but cannot modify a separately managed Traefik installation.
After saving, the setup page shows configuration-write status, both DNS
resolutions, service startup, HTTPS, and /api/health checks. It also shows the
public and dashboard URLs or the next troubleshooting step. The temporary setup
service is stopped automatically after deployment succeeds or fails. The deployment wizard creates
one shared database prefix using the format dbob plus 10 random digits, for
example dbob4829137056. PostgreSQL and MongoDB use that prefix for the
shared catalog, then add _test and _live for the isolated runtime
databases. The prefix is stored in DBOB_DATABASE_PREFIX and reused on later
restarts of the same deployment.
The Bootstrap Setup page displays the generated PostgreSQL and MongoDB
credentials once. Store them in a secure password manager, then rotate them as
soon as the deployment has been verified. A password rotation must update both
the database account and the matching application configuration; changing only
.env.production will break authentication.
Use alphanumeric passwords generated with openssl rand -hex 32, update the
database roles, and then update these PostgreSQL values with the same password:
POSTGRES_PASSWORD, DATABASE_URL_SHARED, DATABASE_URL_TEST,
DATABASE_URL_LIVE, OPENBCON_DB_DSN_SHARED, OPENBCON_DB_DSN_TEST, and
OPENBCON_DB_DSN_LIVE. Update MONGODB_ROOT_PASSWORD after changing the
MongoDB root password. Back up deploy/.env.production first, validate the
Compose configuration, and recreate only api, python, and caddy; never
delete the PostgreSQL or MongoDB volumes. The full command sequence is in the
Hostinger VPS deployment guide.
The AGPL community build keeps the Commercial licensing section visible and
read-only in Admin Console. A paid commercial deployment can hide that section
by setting the build-time variable VITE_COMMERCIAL_LICENSED=true and
rebuilding the API image. This flag controls the compiled UI only; licensing
rights remain governed by the applicable commercial agreement.
For a VPS where Caddy can use ports 80 and 443 directly:
cp deploy/.env.production.example deploy/.env.production
openssl rand -hex 32
# Edit deploy/.env.production with the public DOMAIN and any server-side# API/SMTP/OAuth credentials. The setup wizard generates database credentials.
./deploy/deploy.shThe first deployment runs PostgreSQL migrations and does not seed demo data. Sign in with the admin email and password created by Bootstrap Setup. The bootstrap administrator is created in Shared, Test, and Live databases so the operator can switch modes without losing administrative access; regular users remain isolated to the mode in which they were created.
Both Compose files include Ollama behind an optional ollama profile. The
default deployment does not start or download Ollama. Enable it only when a
local model is required:
docker compose --profile ollama up -d ollama ollama-modelFor production, set ENABLE_OLLAMA=true in deploy/.env.production and run
the deployment command again. Leave it as false when using OpenAI,
OpenRouter, Anthropic, Google, or another external provider.
The default local model is smollm2:135m; model data survives container
restarts in the bconomics-ollama-data volume.
In Admin Console, add or import the Ollama preset at
public/ai-model-presets/ollama.json, then select Ollama and
smollm2:135m as the default enabled model. For the host-run development API,
use http://127.0.0.1:11434/api/chat; for the production Docker network, use
http://ollama:11434/api/chat. The Ollama endpoint is
kept private and does not require an API key.
Admin Console's Mode Switch is also a database boundary. Test Mode is a
fully independent demonstration environment, including its own app_users
table and authentication sessions:
- Test Mode uses
DATABASE_URL_TESTandMONGODB_DATABASE_TEST; generation uses the deterministic mock gateway and writes test users, sessions, companies, applications, reports, usage, billing bindings, and audit data. - Live Mode uses
DATABASE_URL_LIVEandMONGODB_DATABASE_LIVE; generation uses the configured real model gateway and writes only to the live tenant stores. - Shared platform data uses
DATABASE_URL_SHAREDandMONGODB_DATABASE_SHARED. This contains platform configuration, Admin Console settings, AI model configuration, Advisory Hub sections and agents, authentication/provider settings, data-source settings, and the shared funding-program catalog. It never stores user sessions or tenant business records.
The server-authoritative active mode is OPENBCON_ENVIRONMENT_MODE and
defaults to test. Changing it requires updating the deployment environment
and restarting the Node and Python services. Admin Console saves a requested
mode in the shared configuration and keeps the browser cache aligned with the
currently active server mode until that restart completes. Client localStorage,
query parameters, and request headers cannot switch the server across database
boundaries. The frontend does not send the platform mode in API requests;
every request is resolved from the server's OPENBCON_ENVIRONMENT_MODE.
The public GET /api/runtime/environment endpoint exposes only the active mode
and whether a restart is pending; it never returns secrets.
Live connection variables are intentionally required before Live Mode can be
used. Test and Live PostgreSQL databases must both be separate from the
shared catalog database. Do not point either mode at the shared stores. The
bundled deploy/deploy.sh creates the mode databases before API migrations.
To do this manually, run the two database creation commands separately:
docker compose --env-file deploy/.env.production -f deploy/docker-compose.production.yml \
exec postgres psql -U admin -d postgres \
-c "CREATE DATABASE dbob1234567890_test OWNER admin;"
docker compose --env-file deploy/.env.production -f deploy/docker-compose.production.yml \
exec postgres psql -U admin -d postgres \
-c "CREATE DATABASE dbob1234567890_live OWNER admin;"The browser cache is hydrated from the server-reported active mode's database and missing keys are not copied into the other mode. This prevents deleted Admin sections, applications, and old local snapshots from reappearing after a mode switch.
Verify the active mode after deployment with:
curl -sS https://your-domain.example/api/runtime/environmentThe response reports activeEnvironmentMode, the requested mode saved by
Admin Console, and whether a restart is required. It does not expose database
URLs, credentials, API keys, or other secrets. After changing
OPENBCON_ENVIRONMENT_MODE, recreate the API and Python services so both
processes load the same mode from their environment:
docker compose --env-file deploy/.env.production \
-f deploy/docker-compose.production.yml \
up -d --force-recreate api pythonFor updates:
git pull --ff-only
./deploy/deploy.shdeploy/deploy.sh stamps the frontend image with the current Git commit and
the exact Git release tag when the checkout is tagged. In Admin Console, open
Updates, select Check updates, review the release tag, and select
Install update when one is available. Install update first backs up
deploy/.env.production to /root/openbcon.env.production.backup, then forces
the checkout to main at the latest origin/main commit and runs the normal
deployment script. Local tracked changes, local commits, and untracked checkout
files are discarded; database volumes are preserved. The deployment script keeps
the Caddy bind mount anchored to OPENBCON_ROOT (default /opt/openbcon) so
updates launched by the containerized agent use the host checkout correctly.
- the authenticated Node API queries the fixed OpenBcon GitHub
maincommit - the authenticated Node API reads GitHub release tags and matches the current commit to its tag when available
- the frontend compares that commit with the build's
VITE_APP_COMMITvalue deploy/deploy.shsetsVITE_APP_COMMITautomatically fromgit rev-parsedeploy/deploy.shsetsVITE_APP_VERSIONfrom the exact Git tag, orunreleasedfor an untagged checkout- local Vite builds fall back to the current Git tag and commit when no build
stamp is provided; untagged checkouts are labeled
Unreleased - production deployments include a private update agent on the Docker network;
the agent is enabled automatically by
deploy/deploy.shand receives a random token stored in the ignoreddeploy/.env.production - Install update is a destructive code update: it force-switches to
main, resets toorigin/main, and cleans untracked checkout files after backing up the production env file; it never deletes database volumes - the API may briefly restart while the update is installed; Admin Console waits for the status endpoint to return and reports the final result
- after a successful install, Admin Console clears the browser Cache Storage,
service workers,
localStorage, andsessionStorage, then reloads with a cache-busting URL so stale frontend data cannot survive the update; this also signs the current browser out when its session is stored locally - GitHub failures and timeouts are shown as a check error; they do not affect the running application
The endpoint is GET /api/updates?currentCommit=<commit> and requires an
authenticated administrator session. Installation uses
POST /api/updates/apply and status is read from GET /api/updates/status.
Neither endpoint accepts a user-provided upstream URL or shell command. If
Install update is unavailable, run ./deploy/deploy.sh once on the VPS to
create the private updater service and token. The updater requires access to
the Docker socket; keep it on the private Compose network and never expose
port 8788 publicly.
Always supply --env-file deploy/.env.production when running Compose commands
directly, including logs and ps. Never run docker compose down --volumes
unless production data is intentionally being deleted.
The billing flow now supports Stripe Checkout and the Stripe customer portal.
- Copy
.env.exampleto.env. - Add your Stripe server credentials:
STRIPE_TEST_SECRET_KEYSTRIPE_LIVE_SECRET_KEYSTRIPE_WEBHOOK_SECRETAPP_STATE_ENCRYPTION_KEY
- Start the app with
npm run dev. - Open
/admin#paymentsand confirm these Stripe references:testSecretKeyReference->STRIPE_TEST_SECRET_KEYliveSecretKeyReference->STRIPE_LIVE_SECRET_KEYwebhookSecretReference->STRIPE_WEBHOOK_SECRET
- Save the Admin Console configuration in the browser. Platform configuration is
stored in MongoDB. Raw payment secrets are encrypted by the Node API before
persistence; browsers receive placeholders instead of plaintext secrets. Keep
APP_STATE_ENCRYPTION_KEYstable so existing secrets remain decryptable after restarts. - In the Stripe Dashboard, register your webhook endpoint, for example:
http://localhost:8787/api/webhooks/stripe
If the checkout success, cancel, or billing-portal return URLs are left blank in
the Admin Console, the server automatically falls back to the current app origin
and routes users back to /settings#billing.
npm run dev
npm run build
npm run lint
npm run test
npm run check
npm run preview
npm run db:up
npm run db:migrate
npm run db:seed
npm run db:downQuick Build accepts the public application identifier and launches one Strategic Report for that application:
/quick-build?app_id=3a819e8f5ce9f1d8
Clicking Start creates the application first, then immediately navigates to
/strategic-reports?app_id=.... Strategic Reports owns the generation step: it
loads the application by its public app_id, runs the configured LangGraph
workflow, persists the single report, and renders the completed business
analysis and financial model. Quick Build does not run generation itself.
In development and test mode, the Python service may use the configured demo
identity when no session cookie is present. Production must set
OPENBCON_RUNTIME_ENV=production; then the same-origin session cookie is
required for generation and the application workspace is checked server-side.
If generation fails or exceeds the two-minute client timeout, Strategic Reports
shows the backend error and offers Retry generation instead of leaving an
indefinite loading state.
The public generation API uses the same identifier:
POST http://localhost:8010/api/business-plan/generateContent-Type: application/json
{"app_id":"3a819e8f5ce9f1d8","language":"en-CA"}The forecast-only endpoint is:
POST http://localhost:8010/api/business-plan/forecastContent-Type: application/json
{"app_id":"3a819e8f5ce9f1d8","language":"en-CA"}The backend loads the application, company, and funding-program records from
PostgreSQL, then reads the current enabled Strategic Report sections and assigned
agents from MongoDB. Sections are generated in the configured order using each
agent's current name, role, and prompt; there are no Python-side default section
values. The LangGraph run trace and final result are stored in the application's
single strategic_reports row.
The supported output languages are en-CA, fr-CA, and zh-CN. The selected
language is passed to LangGraph prompts and stored with the Strategic Report.
Users can change the workspace language from Settings. The choice is persisted
locally and also controls locale-aware number, date, currency, and forecast formatting.
The report page resolves that row from the application relationship, so the
navigation URL can be /strategic-reports?app_id=<applications.app_id>; the
stored Strategic Report ID is displayed by the page and does not need to be
passed as a second query parameter.
Financial forecasting is part of the Strategic Report. By default it produces three years of monthly periods (36 months), with revenue rows first, expense rows second, and calculated total revenue, total expenses, and net cash flow. Strategic Report renders the forecast with trend charts, net-cash-flow bars, and annual summary cards. The detailed line-item table opens on Year 1 and the cards switch it to the selected year's twelve monthly periods, so users can review each year without scanning all 36 columns at once.
Strategic Report cover pages are structured document sections rather than free-form LLM HTML. Business Analysis and Technology Analysis each recognize their configured Cover Page section and render a consistent cover with the report title, business name, funding program, structured subtitle, date, bold typography, centered alignment, and a brand-colored accent.
Clicking an analysis download action or a Table of Contents item opens a scrollable document preview that mirrors the downloaded document: the cover is shown first, followed by the configured sections in order. DOCX and PDF exports use the same cover data and insert a page break before the first analysis section. Generated prompts are not rendered as cover-page copy, so the cover remains suitable for a client-facing business plan.
src/
config/ Platform configuration and persistence
data/ Navigation and demo records
lib/ Domain and generation helpers
pages/ Landing, dashboard, and admin surfaces
persistence/ PostgreSQL synchronization and offline fallback
server/
db/ PostgreSQL pool, migrations, and seed data
app.ts API routes and validation
stateRepository.ts
The Admin Console reads and writes platform settings through the authenticated
API and MongoDB-backed dynamic state. Sensitive payment and AI model fields are
redacted in bootstrap responses and encrypted by the server before persistence.
The browser may keep an encrypted local copy for editing continuity, but it is
not the security boundary. The server validates a strict state-key allowlist and
requires the database admin role for platform writes.
Workspace settings such as the profile, billing selections, default company, and Quick Build preferences are persisted for the active workspace. Payment gateway secrets are never written back to the remote state store in plaintext.
Strategic Report settings are also managed from the Admin Console and persisted with the platform configuration. Administrators can:
- enable, rename, and reorder the sections shown during package generation
- define the document types available to those sections
- add, remove, and edit Strategic Report agents, including their names, roles, and prompts
- assign a document type and agent to each section
- configure reusable
cover-pageandmain-contentlayouts, including their names, descriptions, and CSS declarations - preview layout changes immediately before saving them
Layouts are intentionally edited as CSS declarations rather than arbitrary selector rules. For example:
padding: 36px 42px; background: #ffffff; gap: 18px;
Each Strategic Report section references one layout by ID. The report document
preview applies the saved declarations to the corresponding page, while the
cover-page layout also controls structured cover-page rendering. Layout
definitions are normalized to the current platform configuration, so the selected
Test or Live environment remains the source of truth and removed or stale local
section snapshots are not reintroduced.
At least one section, one document type, and one agent remain available so the generation workflow always has a valid configuration.
The landing page can be managed directly from /admin#landing-page, including:
- header navigation items and signed-in or signed-out CTA labels
- grouped content sections for hero, CTA copy, features, workflow, and open-source messaging
- dynamic proof points shown on the public homepage
- footer sitemap links, platform links, and legal link destinations
Saved opportunities now bridge directly into the application workflow:
- saving a program can materialize a corresponding application record
- each application stores the Quick Build step-one funding context
/quick-build?app_id=...restores an existing application instead of starting a new one- the Step 2 business profile can automatically import the configured default company
- generated packages can be reopened later from the dedicated
/strategic-reportsroute - each application maps to one Strategic Report through
strategic_reports.application_id
Payment settings under /admin#payments now focus on gateway configuration:
- Stripe and Waffo Pancake can each store separate test and live secret references
- environment-variable names remain visible as references
- raw payment keys are redacted in localStorage and stored in encrypted browser storage
- checkout success and cancel URLs can be overridden per deployment
- customer self-serve subscription changes use the Stripe billing portal
- webhook signature verification uses server environment variables rather than synced admin state
Stripe checkout remains the only live billing flow wired to the server today. Waffo Pancake is available in the Admin Console as a configurable gateway option for secret and mode management.
Before production deployment:
- Set
NODE_ENV=production,SEED_DEMO_DATA=false, andCORS_ORIGINto the exact public origin. - Run migrations
025_auth_sessions.sqland026_billing_resource_bindings.sqlthroughnpm run db:migrateor withAUTO_MIGRATE=trueduring the release. - Put the Node API behind the same origin as the frontend at
/api, and proxy/ai-apito the private Python service athttp://127.0.0.1:8010. - Keep production secrets in a secret manager and use Admin only for references or encrypted-at-rest secure storage.
- Configure TLS and a managed PostgreSQL backup policy.
PostgreSQL stores relational domain data, especially users, companies, funding
programs, applications, and strategic reports. Internal application relations
use the numeric applications.id, while external generation calls use the
unique 16-character applications.app_id.
MongoDB stores editable dynamic JSON configuration and lightweight workspace state
in the dynamic_state collection using three scopes:
platformfor branding, landing-page content, modules, AI/payment configuration, and data sourcesworkspacefor Funding Shortlist preferences and Quick Build draftsuserfor personal settings, pinned resources, and active workspace selection
The selected environment mode chooses the MongoDB database before these scopes
are read or written. Strategic Report section configuration therefore comes
from the current mode's platform document only; it never falls back to the
other mode's configuration.
Sensitive payment keys and AI model API keys inside
bconomics-platform-config-v1 are not returned to the browser in plaintext. The
API redacts them in bootstrap payloads, encrypts raw values before saving them to
MongoDB, and decrypts payment references only for server-side payment
operations. Stripe checkout sessions and customer IDs are also bound to the
authenticated workspace and user in billing_resource_bindings.
On first migration, existing app_state JSON documents are copied to MongoDB.
The PostgreSQL app_state table is no longer used. On later visits, MongoDB and
the relational applications table are loaded before the React application mounts.
Mutations are debounced and written in batches, and every mutation creates an audit
record in PostgreSQL.
See docs/DATABASE.md for the schema, API contract, deployment guidance, and migration path toward fully normalized domain tables.
Browser authentication uses a server-side auth_sessions table and an
HttpOnly bconomics_session cookie. In production, missing or expired sessions
are rejected by the Node API and Python generation API. The generation and
forecast endpoints resolve the session workspace and filter the requested
application by that workspace, so a user-supplied app_id cannot cross
workspace boundaries. AI connection tests are restricted to administrators and
workspace owners because they can consume configured provider credentials and
model quota. The test response is capped at 64 KB.
New password registrations create an account, establish a session immediately,
and send a one-time verification link. Email verification can be completed
later from the link or by requesting a resend. Development defaults to
EMAIL_PROVIDER=console, which logs the preview link instead of sending an
email. This is also the default for a production deployment in Test Mode, so
SMTP is optional while the platform is being evaluated. Before switching to
Live Mode, configure SMTP by setting EMAIL_PROVIDER=smtp, SMTP_HOST,
SMTP_PORT, SMTP_SECURE, SMTP_USER, SMTP_PASSWORD, EMAIL_FROM, and
DASHBOARD_APP_URL (PUBLIC_APP_URL remains a legacy alias). Existing users from before email verification was introduced
are treated as verified by the database migration.
Google registration and login are available when
GOOGLE_OAUTH_CLIENT_ID, GOOGLE_OAUTH_CLIENT_SECRET, and
GOOGLE_OAUTH_REDIRECT_URI are configured. Register the exact callback URL in
Google Cloud Console: https://YOUR_HOST/api/auth/google/callback (or the
equivalent local URL). OAuth state is stored in short-lived HttpOnly cookies,
Google email verification is required, and the app never receives the Google
client secret.
Platform state writes are server-authorized: only a database user with the
admin role can update or delete platform configuration. Login failures are
rate-limited per IP and email, and payment resources are checked against the
current workspace/user before Stripe portal access or session lookup.
Local Node persistence routes and the Python generation service may use the
configured demo context when no cookie is present during development and test
runs. Set OPENBCON_RUNTIME_ENV=production for the Python service in production;
then both APIs require the login or registration API to establish a session and
the Python service validates the session workspace before generation. The
authentication endpoints also apply short-window rate limits to registration,
password-reset requests, and verification-email resends. Production password
reset and verification delivery require SMTP in Live Mode. Test Mode may use
the console provider and logs email previews instead of sending messages. Do
not expose the Node API, Python AI API,
PostgreSQL, MongoDB, payment routes, or model endpoints publicly without TLS,
secret management, and
database network controls.
The frontend calls the Python service through the same-origin /ai-api path.
Vite proxies that path to port 8010 during development; a production reverse
proxy must provide the equivalent route and must not expose port 8010 directly.
Keep .env and provider keys out of Git. Use a secret manager in production and
never place raw AI or payment credentials in frontend configuration. Review and
back up the database before applying destructive historical migrations, including
the migration that removes the legacy funding-package tables.
The security review also checks for committed credential patterns, production
CORS settings, session-cookie flags, workspace authorization, AI endpoint
allowlisting, and Python dependency advisories. Keep
OPENBCON_ALLOW_PRIVATE_AI_ENDPOINTS=false in production unless a private
endpoint is explicitly required and network access is independently restricted.
Open /admin#data-sources to manage the sources that populate Grants & Loans,
Templates, Social Resources, and Tools. Administrators can search and filter by
module, change a source's destination, enable or disable it, and run a manual sync.
Synchronized records are cached locally in the demo and become available in their
selected workspace module.
Supported columns are:
Program Name, Type, Provider, Amount, Deadline, Match, URL, Location
Common alternatives such as Name, Agency, Maximum Amount, Closing Date,
and Region are mapped automatically.
Templates, Social Resources, and Tools use:
Title, Description, Category, Status, URL, Updated
Alternatives such as Name, Summary, Format, Channel, Link, and
Last Updated are also recognized.
Paste a public or link-readable Google Sheets URL and optionally provide the sheet tab name. The frontend converts the sharing URL to CSV and imports the rows. The included funding, template, and tools CSV files can be used to test the sync flow without an external account.
Airtable synchronization uses a server-side proxy so the personal access token is never stored in the browser. Configure the base ID, table, view, proxy URL, and environment-variable name in Admin.
The integration proxy receives:
{
"provider": "airtable",
"baseId": "appXXXXXXXXXXXXXX",
"tableName": "Funding Programs",
"view": "Published",
"credentialReference": "AIRTABLE_ACCESS_TOKEN"
}It should return either an array of field objects or the Airtable-style shape:
{
"records": [
{
"fields": {
"Program Name": "Community Growth Loan",
"Type": "Loan",
"Amount": 50000
}
}
]
}Protect the proxy with administrator authorization, validate the requested base and table against an allowlist, and read the Airtable token from server-side environment variables.
OpenBcon uses a dual-license structure:
- Community edition:
AGPL-3.0-or-later - Commercial edition: available by separate paid agreement
The commercial edition is intended for customers that need:
- proprietary or closed-source deployment rights
- private modifications without AGPL disclosure obligations
- white-label, OEM, or embedded distribution rights
- paid implementation, customization, or ongoing support
In the community edition, OpenBcon attribution in the landing page and dashboard footer is required. Commercial license holders can negotiate white-label controls, including whether that attribution is visible.
See COMMERCIAL-LICENSE.md for the commercial licensing model and CLA.md for the contributor agreement required for external contributions.
git init
git add .
git commit -m "Initial open source release"
git branch -M main
git remote add origin <your-repository-url>
git push -u origin mainDo not commit production credentials, customer data, generated documents, or third-party assets that you do not have the right to redistribute.















