Appearance
Code extensions
What is it?
Most of an application is configuration. When configuration is not enough you add code, in the language that suits the job:
| Where | Languages | Used for |
|---|---|---|
| Backend | Java, Python (FastAPI), Node.js (Express / TypeScript), Go (net/http) | logic, calculations, integrations, custom APIs |
| Frontend | React (TypeScript) | custom blocks and screens that no built-in block can express |
Backend code runs either embedded in the platform (Java only) or as its own service container in any of the three languages. See Backend services.
When should I use configuration and when code?
| Need | Use |
|---|---|
| New data, screen, form, menu, report | configuration |
| Validation, computed field, approval | configuration (rule, workflow) |
| Change a shipped page | layered override |
| Reaction when a record is saved | extension point bound to a service |
| Heavy calculation, third-party library, custom protocol | backend code (Java, Python, Node.js or Go) |
| A screen or widget no block can express | React custom block |
Start with configuration. Add code only for the last two.
What Studio does for each language today
| Language | Start | Edit | Compile / test / package in Studio | Run |
|---|---|---|---|---|
| Java | Build, Add Java backend (starter) | Advanced, Java source; or source-write | yes: Compile, Run tests, Package | embedded, or a service container controlled from Studio |
| Node.js | platform-cli service-plugin:scaffold --id <id> --runtime nodejs --out <dir>, or MCP erp_service_plugin_scaffold | source-write (CLI, MCP) | install, test, build through Node: run | service; self-registers with the platform |
| Python | the same scaffold with --runtime python (FastAPI) | source-write (CLI, MCP) | run pytest yourself for now; a Studio Python build step is Planned | service; self-registers with the platform |
| React | write a .tsx block | source-write, then erp plugin compile <file.tsx> | compile to a page/block artifact with the Code Plugin SDK | rendered by the platform like any block |
Every language talks to the platform the same way: plain REST with the tenant and user in the request headers, and a shared secret to self-register. A Python, Node.js or Go service is therefore a first-class citizen, even where Studio's own build buttons cover only Java and Node.
Read and write source from the command line or an agent
bash
erp source files --plugin-id leave-management
erp source read --plugin-id leave-management --path service/app/main.py
erp source write --plugin-id leave-management --path service/app/accrual.py --file ./accrual.py
erp source write --plugin-id leave-management --path frontend/LeaveCard.tsx --file ./LeaveCard.tsx
erp plugin op java-compile --plugin-id leave-managementThe same three operations are MCP tools (erp_plugin_op with source-files, source-read, source-write), so an AI coding assistant can write Java, Python, Node.js and React into a plugin and use the compile and test operations to check its work. Paths are relative to the plugin folder; the plugin's own metadata and build output are never touched, and only source and config file types are accepted.
Build, dependencies, debugging, logging
Java builds run in an isolated container against the libraries in the build image; Node builds can fetch npm packages. A library the worker image lacks needs adding to the image. Compile and test output is in the Output panel. A service's live logs are in Deploy, Manage backend service. Use each language's normal logging; the tenant is attached to each request.
Planned (placeholders)
Python build, test and deploy buttons in Studio; Node and Python starters in the Create Plugin wizard; remote debugging; publishing the React component SDK for use outside the repository. Planned.
Common mistakes
Reaching for code when a rule does it; a Java library missing from the worker image; forgetting that a service is a separate container (memory, restart); writing metadata files with source-write (use the artifact operations instead).
