@pa1nd/atelier
v0.16.1
Published
The Atelier app shell — discovers, mounts, and serves feature modules around one shared chrome: a single runtime hosting many small, context-window-sized apps. Install as a dependency, run with `atelier`, install modules with `atelier add`.
Downloads
1,711
Maintainers
Readme
Atelier is an app shell + module runner. Point your agent at a folder — a frontend.jsx and/or a backend.js — and it becomes a routed, hot-reloading, real-time module. The shell handles routing, bundling, a shared real-time WebSocket, workspaces, and (optional) auth, so a module stays a file or two of React and a handful of route handlers.
my-studio/
node_modules/@pa1nd/atelier the shell — five files, ~3k lines (or a checkout at ./atelier/)
notes/ → /global/notes a module (a folder with a frontend.jsx)
$acme/board/ → /acme/board a workspace moduleThe whole shell is five files (~3k lines), and your modules ship zero dependencies of their own — no React, no bundler, no WebSocket client to vendor. It ships zero pixels and zero assumptions: no default theme, no dev/prod notion. An instance is a folder you run.
Platform. Atelier runs anywhere Node 24+ does — there is no OS-specific install layer (you run it; your process manager / PaaS / reverse proxy is your concern).
Quickstart
npm create @pa1nd/atelier my-studio # scaffold a tiny instance that depends on @pa1nd/atelier
cd my-studio && npm install
npm run dev # http://localhost:1844 (override with PORT=…), hot reload, discovers sibling modulesOr add the shell to an existing folder — npm install @pa1nd/atelier, then npx atelier: the folder that owns node_modules is the instance. Install modules with npx atelier add <source> — a collection's git repo on GitHub, any git url, a served collection on your network, or a local folder/bundle (docs). (Working from a checkout of this repo instead? The subfolder layout still works: the instance is the folder containing atelier/; run npm install && npm run dev inside atelier/.)
The folder you run in is the instance. Its atelier.config.json is the source of truth (which modules run, which chrome, port, auth, …); environment variables override it at startup. Want a second instance? Run a second folder — or the same folder with different startup config (e.g. a different PORT and auth).
You'll see an "add a chrome" screen until you install a chrome module — the shell ships no chrome and has no built-in theme. Write or install one (a global-workspace folder exporting meta = { isChrome: true, hidden: true } and a chrome function) and point your config's defaultChrome at it. See Modules → the chrome.
Write a module
Scaffold one — paste this next to atelier/ (or anywhere your config path-mounts):
mkdir -p hello && cat > hello/frontend.jsx <<'EOF'
export const meta = { name: 'Hello', icon: 'sparkles' } // icon: any lucide name
export default function Module() {
return <div className="p-8 text-xl">hello from a module</div>
}
EOFReload — it appears in the rail. A folder with a frontend.jsx is the whole requirement. Add a backend.js for an API:
// hello/backend.js — routes mount at /api/<workspace>/hello
export default {
mountRoutes(router, ctx) {
router.get('/ping', (req, res) => res.json({ ok: true, from: ctx.qualifiedId }))
},
}The full contract — ctx, the real-time WebSocket, ctx.module(id) slots, hot-reload teardown, the chrome slot, @atelier/kit, workspaces, and atelier.config.json — is in the documentation.
Documentation
Four pages (a chrome may also surface these in-app), in this order:
- docs/README.md — Atelier: running an instance, what lives in
atelier/, andatelier.config.json. - docs/INSTALL.md — Install: creating an instance, collections and the sharing verbs (
package/publish/add/list), the shipping convention. - docs/MODULES.md — Modules: module shape,
ctx, real-time (self/broadcast), hot-reload, cross-module slots, sidecar servers — plus the special modules (the chrome +@atelier/kit). - docs/WORKSPACES.md — Workspaces: the multi-tenant model (
global+$<ws>/), thequalifiedId, rail and picker. - docs/AUTH.md — Auth: the auth-module slot, the
user/defaultUsercontract, request + WebSocket gating, takeover render. - CHANGELOG.md — version history and migration notes.
Tests
npm test # node:test characterization suite (zero extra deps)Run it after any change to the shell (server.js, build.js, discovery.js, client.jsx, chrome-resolve.js).
Contributing
The shell (server.js, client.jsx, build.js, discovery.js, chrome-resolve.js) is cross-cutting — changes there are their own task, separate from any single module. If a module needs something the shell doesn't provide, the convention is to name the gap and propose extending the shell rather than reaching around it. Keep the surface small.
The name
An atelier is a painter's studio. The name comes from an old idea — God is the painter, we are the painting; the creator stands outside what's created. Atelier is where that inverts: you step into the painter's role, and the agents become your servants, the way we are to a creator we can't fully know. The studio is where the created learns to create.
License
MIT © 2026 pa1nd.
