Project Documentation
Developer reference for human and agent contributors. Keep this file up to date as the project evolves.
Roject is a self-hosted, agent-based IDE for working with files and projects. It provides specialised editors for different file types — a WYSIWYG HTML editor, a CodeMirror-backed code editor, and more to come — all within a multi-panel, tab-based workspace. Projects can be hosted on a Roject server (remote) or opened directly from the local filesystem (local), making it usable both as a lightweight self-hosted CMS and as a full desktop development environment. Designed for individual developers or small teams; no external database dependency.
User accounts are managed by rokojori-auth at
account.rokojori.com — registration, login, JWT issuance, refresh
token rotation, roles, and account deletion. Roject verifies the shared
accessToken JWT cookie and transparently refreshes expired tokens
via account.rokojori.com/api/auth/refresh-session.
Groups and projects with member management (viewer / editor / admin roles).
Each project gets a real directory on disk at storage/<uuid>/root/
with a default index.html on creation. All data lives as JSON files
in data/ — no external database.
A full editor page (/editor.html) with a 3-panel resizable layout
(Left / Center / Right). Each panel holds one or more sections side by side;
each section holds a <tab-container> with drag-and-drop tabs.
The Left panel shows the file tree (create, rename, delete).
A FileEditorRegistry routes files to the correct panel by extension:
HTML → html-editor-panel (iframe, contenteditable, MutationObserver,
undo/redo, Ctrl+S save); all other text formats → code-panel
(CodeMirror 5, syntax highlighting, dark theme). An optional project-level
workspace/editor/file-editors.json overrides the defaults.
A rojo-chat-panel provides a streaming AI chat interface backed by
LangChain + OpenAI-compatible models. A reusable <confirm-dialog>
component replaces browser confirm() for destructive actions.
An EmailService facade (source/server/email/) provides
a sendEmail() entry point backed by a swappable EmailSender
interface; the default is SMTPEmailSender (Nodemailer).
Roject runs as a standalone Windows desktop application. The Express server starts
in-process inside Electron's main process. A custom login window calls the auth
API directly; tokens are stored in userData/tokens.json and re-used
across sessions. All requests to localhost have
Authorization: Bearer injected automatically via
session.webRequest.onBeforeSendHeaders. Run with
npm run electron:dev.
Live at https://roject.rokojori.com on Server A. nginx handles TLS
and reverse-proxies to a Node.js process managed by systemd. Auto-deploy on push
to main via a Gitea webhook calling POST /api/deploy
(HMAC-SHA256 verified). The deploy script runs detached so it survives the
systemctl restart that kills the parent process.
Current tasks, known bugs, and longer-horizon features are tracked on the Boards.
Node.js + Express, TypeScript compiled on the fly with ts-node.
Auth is handled by rokojori-auth; Roject verifies the shared
accessToken JWT cookie using jsonwebtoken +
cookie-parser. All entity IDs are UUIDs via
crypto.randomUUID(). Start the server with npm start.
The Editor singleton (src/editor/Editor.ts) is the
central hub of the frontend — it owns all open document state, the
FileEditorRegistry, and the five events that panels and tab containers
subscribe to (onDocumentOpened, onDocumentDirty,
onDocumentSaved, onFilesChanged,
onFileTypeUnknown). For the full event reference and the TypeScript
compilation split between client and server, see the
Editor Singleton reference.
Vanilla HTML, raw CSS (no Tailwind, no framework). Every UI component is a
custom element with its own .ts and .css file in
source/components/<name>/. CSS uses the element tag as root
selector with display: block. TypeScript compiles to
build/app/components/ via tsconfig.client.json
(module: ESNext, no bundler). HTML pages live in
source/pages/ and are copied to build/app/ by
scripts/copy-pages.js. Build with npm run build.
A personal TypeScript library lives as a git submodule at
source/library-ts/. It has two parts: browser/
(DOM-capable) and node/ (Node.js only). The browser part is
compiled separately via TypeScript project references into
build/app/library-ts/browser/. The node part is included by
tsconfig.ts-node.json.