V
public

 

vibe_erp

vibe_erp is an ERP/EBC framework for the printing industry, sold worldwide and deployed self-hosted-first. It is not an ERP application: it is the substrate on which any printing shop's workflows, forms, roles, and rules can be assembled by configuration and plug-ins instead of by forking the core. The reference business under raw/ is one example customer, used as an executable acceptance test, never as the spec.

Why a framework, not an app

Printing shops differ in process, terminology, paperwork, and order of operations. An app that hard-codes one shop's workflow becomes a fork farm the moment a second customer signs up. vibe_erp follows the Clean Core philosophy borrowed from SAP S/4HANA: the core stays generic and upgrade-safe, and every customer-specific concept lives in metadata rows or plug-ins. The core never knows what a "plate" or a "press" is — those concepts are introduced by a plug-in. Upgrading the core does not touch the customer's extensions.

Architecture in one picture

┌──────────────────────────────────────────────────────────────────────┐
│                          Customer's network                          │
│                                                                      │
│  Browser (React SPA) ─┐                                              │
│  AI agent (MCP, v1.1)─┼─► Reverse proxy ──► vibe_erp backend (1 image)│
│  3rd-party system    ─┘                       │                      │
│                                                │                      │
│   Inside the image (one Spring Boot process):  │                      │
│     ┌─────────────────────────────────────┐   │                      │
│     │  HTTP layer (REST + OpenAPI + MCP)  │   │                      │
│     ├─────────────────────────────────────┤   │                      │
│     │   Public Plug-in API  (api.v1.*)    │◄──┤  loaded from         │
│     │   — the only stable contract        │   │  ./plugins/*.jar     │
│     ├─────────────────────────────────────┤   │  via PF4J            │
│     │   Core PBCs (modular monolith):     │   │                      │
│     │   identity · catalog · partners ·   │   │                      │
│     │   inventory · warehousing ·         │   │                      │
│     │   orders-sales · orders-purchase ·  │   │                      │
│     │   production · quality · finance    │   │                      │
│     ├─────────────────────────────────────┤   │                      │
│     │   Cross-cutting:                    │   │                      │
│     │   • Flowable (workflows-as-data)    │   │                      │
│     │   • Metadata store (Doctype-style)  │   │                      │
│     │   • i18n (ICU MessageFormat)        │   │                      │
│     │   • Reporting (JasperReports)       │   │                      │
│     │   • Job scheduler (Quartz)          │   │                      │
│     │   • Audit, security, events         │   │                      │
│     └─────────────────────────────────────┘   │                      │
│                                                ▼                      │
│                                       PostgreSQL  (mandatory)        │
│                                       File store  (local or S3)      │
└──────────────────────────────────────────────────────────────────────┘

Optional sidecars for larger deployments (off by default):
   • Keycloak (OIDC)        • Redis (cache + queue)
   • OpenSearch (search)    • SMTP relay

The full architecture lives at docs/superpowers/specs/2026-04-07-vibe-erp-architecture-design.md.

Stack

  • Kotlin on the JVM, Spring Boot, single fat-JAR / single Docker image
  • PostgreSQL (the only mandatory external dependency)
  • Embedded Flowable (BPMN 2.0) for workflows-as-data
  • PF4J + Spring Boot child contexts for plug-in classloader isolation
  • ICU4J + Spring MessageSource for i18n
  • JasperReports for reporting
  • React + TypeScript SPA for the web client

Repository layout

vibe-erp/
├── api/
│   └── api-v1/                 ← THE CONTRACT (semver, published to Maven Central)
├── platform/                   ← Framework runtime (internal)
├── pbc/                        ← Core PBCs (one Gradle subproject each)
├── reference-customer/
│   └── plugin-printing-shop/   ← Reference plug-in, built and CI-tested, not loaded by default
├── web/                        ← React + TypeScript SPA
├── docs/                       ← Framework documentation
└── distribution/               ← Bootable assembly: fat JAR + Docker image

Building

# Build everything (compiles all JVM modules + the web SPA, runs 356 unit tests)
./gradlew build

# Bring up Postgres + the reference plug-in JAR
docker compose up -d db
./gradlew :reference-customer:plugin-printing-shop:installToDev

# Boot the framework against it
./gradlew :distribution:bootRun

The bootstrap admin password is printed to the application logs on first boot.

Running the end-to-end demo

The dev profile opts in to a one-shot DemoSeedRunner that stages a starter dataset on first boot (5 items, 2 warehouses with opening stock, 4 partners, one open sales order, one open purchase order — everything prefixed DEMO-). Combined with the React SPA served out of the same fat-jar, that's enough to click through the entire buy-sell loop in the browser.

docker compose up -d db
./gradlew :distribution:bootRun
open http://localhost:8080

Then:

  1. Log in as admin — the password is in the bootRun log, under vibe_erp bootstrap admin created.
  2. The dashboard shows every PBC populated with seeded rows. Click through Items, Partners, Locations, Stock Balances — each page is live against Postgres.
  3. Click Sales Orders → DEMO-SO-0001. The order is in DRAFT; click Confirm. The Journal entries panel on the same page shows an AR POSTED row appear, created reactively by pbc-finance from the SalesOrderConfirmedEvent.
  4. Pick DEMO-WH-FG as the shipping location and click Ship. The order flips to SHIPPED, the Inventory movements panel shows the SALES_SHIPMENT ledger rows, and the journal entry settles to AR SETTLED. Navigate to Stock Balances and confirm the two finished-good rows dropped by the shipped quantity.
  5. Do the mirror-image flow on Purchase Orders → DEMO-PO-0001 (Confirm → Receive into DEMO-WH-RAW). Stock grows, an AP row posts and settles, and another ledger row appears.
  6. Shop Floor renders any IN_PROGRESS work order with a live progress bar; create one via Work Orders or via the workflow engine and watch it update every 5 seconds.

REST endpoints are live under /api/v1/** for every PBC (see /v3/api-docs or the Swagger UI at /swagger-ui/index.html for the full catalog). The SPA uses them directly — no separate backend server is needed.

Status

Current stage: end-to-end runnable demo. All 10 core PBCs are live against real Postgres, the full buy-sell-make loop is wired via cross-PBC events, every cross-cutting platform service (auth + authorization + plug-in HTTP + linter + Liquibase + metadata + i18n + events/outbox + JasperReports + FileStorage + Quartz + embedded Flowable) is running, and the R1 React SPA is served out of the same fat-jar with a seeded starter dataset so the entire buy-sell-make loop can be walked in a browser on first boot.

JVM modules 24 Kotlin subprojects + :web
Unit tests 356, all green
Real PBCs 10 of 10
Cross-cutting services live 12
Plug-ins serving HTTP 1 (reference printing-shop — 8 endpoints, own DB schema, metadata, i18n, TaskHandlers, JobHandler, BPMN, reports, file storage)
Web SPA Served by Spring Boot at / — login, dashboard, 14 pages, live ship/receive/confirm verbs, shop-floor dashboard
Production-ready No — OIDC, MCP server, JSON Schema form renderer, GL-level finance, and richer per-PBC verbs are still pending

For the full feature inventory, completed work, and next-priority list, see PROGRESS.md. For the detailed roadmap, see docs/superpowers/specs/2026-04-07-vibe-erp-implementation-plan.md.

Documentation

License

Apache License 2.0. See LICENSE.