2026-07-06 17:28:59 +00:00
|
|
|
<!DOCTYPE html>
|
|
|
|
|
<html lang="en">
|
|
|
|
|
<head>
|
|
|
|
|
<meta charset="UTF-8">
|
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
|
|
<title>Roject — Developer Documentation</title>
|
|
|
|
|
<link rel="stylesheet" href="../_assets_/styles.css">
|
|
|
|
|
<link rel="stylesheet" href="../_assets_/nav.css">
|
|
|
|
|
</head>
|
|
|
|
|
<body>
|
|
|
|
|
<div class="page">
|
|
|
|
|
|
2026-07-12 14:14:58 +00:00
|
|
|
<div style="width:100%;height:400px;overflow:hidden;background:#000;margin-bottom:2rem;border-radius:8px;">
|
|
|
|
|
<img src="../_assets_/roject.svg" alt="Rojects"
|
2026-07-11 12:06:55 +00:00
|
|
|
style="width:100%;height:100%;object-fit:cover;object-position:center;">
|
|
|
|
|
</div>
|
|
|
|
|
|
2026-07-06 17:28:59 +00:00
|
|
|
<header>
|
|
|
|
|
<p class="date">Project Documentation</p>
|
|
|
|
|
<h1 style="font-size: 300%;">Roject</h1>
|
|
|
|
|
<p class="subtitle">Developer reference for human and agent contributors. Keep this file up to date as the project evolves.</p>
|
|
|
|
|
</header>
|
|
|
|
|
|
|
|
|
|
<section>
|
2026-07-14 12:34:47 +00:00
|
|
|
<h2>What it is</h2>
|
2026-07-06 17:28:59 +00:00
|
|
|
|
|
|
|
|
<div class="card">
|
|
|
|
|
<p>
|
2026-07-11 12:06:55 +00:00
|
|
|
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,
|
2026-07-14 12:34:47 +00:00
|
|
|
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.
|
2026-07-06 17:28:59 +00:00
|
|
|
</p>
|
|
|
|
|
</div>
|
2026-07-14 12:34:47 +00:00
|
|
|
</section>
|
2026-07-06 17:28:59 +00:00
|
|
|
|
2026-07-14 12:34:47 +00:00
|
|
|
<section>
|
|
|
|
|
<h2>What exists now</h2>
|
2026-07-14 11:31:11 +00:00
|
|
|
|
|
|
|
|
<div class="card">
|
2026-07-14 12:34:47 +00:00
|
|
|
<h3>Auth & accounts</h3>
|
2026-07-14 11:31:11 +00:00
|
|
|
<p>
|
2026-07-14 12:34:47 +00:00
|
|
|
User accounts are managed by <strong>rokojori-auth</strong> at
|
|
|
|
|
<code>account.rokojori.com</code> — registration, login, JWT issuance, refresh
|
|
|
|
|
token rotation, roles, and account deletion. Roject verifies the shared
|
|
|
|
|
<code>accessToken</code> JWT cookie and transparently refreshes expired tokens
|
|
|
|
|
via <code>account.rokojori.com/api/auth/refresh-session</code>.
|
2026-07-14 11:31:11 +00:00
|
|
|
</p>
|
2026-07-11 12:06:55 +00:00
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="card">
|
2026-07-14 12:34:47 +00:00
|
|
|
<h3>Groups, projects & storage</h3>
|
2026-07-11 12:06:55 +00:00
|
|
|
<p>
|
2026-07-14 12:34:47 +00:00
|
|
|
Groups and projects with member management (viewer / editor / admin roles).
|
|
|
|
|
Each project gets a real directory on disk at <code>storage/<uuid>/root/</code>
|
|
|
|
|
with a default <code>index.html</code> on creation. All data lives as JSON files
|
|
|
|
|
in <code>data/</code> — no external database.
|
2026-07-11 12:06:55 +00:00
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="card">
|
2026-07-14 12:34:47 +00:00
|
|
|
<h3>Editor</h3>
|
2026-07-11 12:06:55 +00:00
|
|
|
<p>
|
2026-07-14 12:34:47 +00:00
|
|
|
A full editor page (<code>/editor.html</code>) with a 3-panel resizable layout
|
|
|
|
|
(Left / Center / Right). Each panel holds one or more sections side by side;
|
|
|
|
|
each section holds a <code><tab-container></code> with drag-and-drop tabs.
|
|
|
|
|
The Left panel shows the file tree (create, rename, delete).
|
|
|
|
|
A <code>FileEditorRegistry</code> routes files to the correct panel by extension:
|
|
|
|
|
HTML → <code>html-editor-panel</code> (iframe, contenteditable, MutationObserver,
|
|
|
|
|
undo/redo, Ctrl+S save); all other text formats → <code>code-panel</code>
|
|
|
|
|
(CodeMirror 5, syntax highlighting, dark theme). An optional project-level
|
|
|
|
|
<code>workspace/editor/file-editors.json</code> overrides the defaults.
|
2026-07-11 12:06:55 +00:00
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="card">
|
2026-07-14 12:34:47 +00:00
|
|
|
<h3>AI chat & utilities</h3>
|
2026-07-06 17:28:59 +00:00
|
|
|
<p>
|
2026-07-14 12:34:47 +00:00
|
|
|
A <code>rojo-chat-panel</code> provides a streaming AI chat interface backed by
|
|
|
|
|
LangChain + OpenAI-compatible models. A reusable <code><confirm-dialog></code>
|
|
|
|
|
component replaces browser <code>confirm()</code> for destructive actions.
|
|
|
|
|
An <code>EmailService</code> facade (<code>source/server/email/</code>) provides
|
|
|
|
|
a <code>sendEmail()</code> entry point backed by a swappable <code>EmailSender</code>
|
|
|
|
|
interface; the default is <code>SMTPEmailSender</code> (Nodemailer).
|
2026-07-11 12:06:55 +00:00
|
|
|
</p>
|
2026-07-06 17:28:59 +00:00
|
|
|
</div>
|
2026-07-11 12:06:55 +00:00
|
|
|
|
2026-07-14 11:31:11 +00:00
|
|
|
<div class="card">
|
2026-07-14 12:34:47 +00:00
|
|
|
<h3>Electron desktop app</h3>
|
2026-07-14 11:31:11 +00:00
|
|
|
<p>
|
2026-07-14 12:34:47 +00:00
|
|
|
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 <code>userData/tokens.json</code> and re-used
|
|
|
|
|
across sessions. All requests to <code>localhost</code> have
|
|
|
|
|
<code>Authorization: Bearer</code> injected automatically via
|
|
|
|
|
<code>session.webRequest.onBeforeSendHeaders</code>. Run with
|
|
|
|
|
<code>npm run electron:dev</code>.
|
2026-07-14 11:31:11 +00:00
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
|
2026-07-13 19:56:25 +00:00
|
|
|
<div class="card">
|
2026-07-14 12:34:47 +00:00
|
|
|
<h3>Deployment & CI</h3>
|
2026-07-13 19:56:25 +00:00
|
|
|
<p>
|
2026-07-14 12:34:47 +00:00
|
|
|
Live at <code>https://roject.rokojori.com</code> on Server A. nginx handles TLS
|
|
|
|
|
and reverse-proxies to a Node.js process managed by systemd. Auto-deploy on push
|
|
|
|
|
to <code>main</code> via a Gitea webhook calling <code>POST /api/deploy</code>
|
|
|
|
|
(HMAC-SHA256 verified). The deploy script runs detached so it survives the
|
|
|
|
|
<code>systemctl restart</code> that kills the parent process.
|
2026-07-13 19:56:25 +00:00
|
|
|
</p>
|
|
|
|
|
</div>
|
2026-07-14 12:34:47 +00:00
|
|
|
</section>
|
2026-07-13 19:56:25 +00:00
|
|
|
|
2026-07-14 12:34:47 +00:00
|
|
|
<section>
|
|
|
|
|
<h2>What's next</h2>
|
2026-07-12 18:59:23 +00:00
|
|
|
|
2026-07-13 11:54:11 +00:00
|
|
|
<div class="card">
|
|
|
|
|
<p>
|
2026-07-14 12:34:47 +00:00
|
|
|
Current tasks, known bugs, and longer-horizon features are tracked on the
|
|
|
|
|
<a href="../boards/index.html">Boards</a>.
|
2026-07-13 11:54:11 +00:00
|
|
|
</p>
|
|
|
|
|
</div>
|
2026-07-06 17:28:59 +00:00
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
<section>
|
|
|
|
|
<h2>Technical Implementation</h2>
|
|
|
|
|
|
|
|
|
|
<div class="card">
|
|
|
|
|
<h3>Backend</h3>
|
|
|
|
|
<p>
|
|
|
|
|
Node.js + Express, TypeScript compiled on the fly with <code>ts-node</code>.
|
2026-07-14 12:34:47 +00:00
|
|
|
Auth is handled by <code>rokojori-auth</code>; Roject verifies the shared
|
2026-07-13 13:37:19 +00:00
|
|
|
<code>accessToken</code> JWT cookie using <code>jsonwebtoken</code> +
|
|
|
|
|
<code>cookie-parser</code>. All entity IDs are UUIDs via
|
2026-07-14 12:34:47 +00:00
|
|
|
<code>crypto.randomUUID()</code>. Start the server with <code>npm start</code>.
|
2026-07-06 17:28:59 +00:00
|
|
|
</p>
|
|
|
|
|
<div class="tags">
|
|
|
|
|
<span class="tag">Node.js</span>
|
|
|
|
|
<span class="tag">Express</span>
|
|
|
|
|
<span class="tag">ts-node</span>
|
2026-07-13 13:37:19 +00:00
|
|
|
<span class="tag">jsonwebtoken</span>
|
|
|
|
|
<span class="tag">cookie-parser</span>
|
2026-07-06 17:28:59 +00:00
|
|
|
<span class="tag">UUID IDs</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2026-07-11 12:24:17 +00:00
|
|
|
<div class="card">
|
|
|
|
|
<h3>Frontend — Editor Singleton & Client/Server Split</h3>
|
|
|
|
|
<p>
|
|
|
|
|
The <code>Editor</code> singleton (<code>src/editor/Editor.ts</code>) is the
|
2026-07-14 12:34:47 +00:00
|
|
|
central hub of the frontend — it owns all open document state, the
|
|
|
|
|
<code>FileEditorRegistry</code>, and the five events that panels and tab containers
|
|
|
|
|
subscribe to (<code>onDocumentOpened</code>, <code>onDocumentDirty</code>,
|
|
|
|
|
<code>onDocumentSaved</code>, <code>onFilesChanged</code>,
|
|
|
|
|
<code>onFileTypeUnknown</code>). For the full event reference and the TypeScript
|
|
|
|
|
compilation split between client and server, see the
|
2026-07-11 12:24:17 +00:00
|
|
|
<a href="../reference/editor-singleton/index.html">Editor Singleton reference</a>.
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
|
2026-07-06 17:28:59 +00:00
|
|
|
<div class="card">
|
|
|
|
|
<h3>Frontend</h3>
|
|
|
|
|
<p>
|
|
|
|
|
Vanilla HTML, raw CSS (no Tailwind, no framework). Every UI component is a
|
|
|
|
|
custom element with its own <code>.ts</code> and <code>.css</code> file in
|
2026-07-12 12:01:01 +00:00
|
|
|
<code>source/components/<name>/</code>. CSS uses the element tag as root
|
2026-07-06 17:28:59 +00:00
|
|
|
selector with <code>display: block</code>. TypeScript compiles to
|
2026-07-12 12:01:01 +00:00
|
|
|
<code>build/app/components/</code> via <code>tsconfig.client.json</code>
|
2026-07-14 12:34:47 +00:00
|
|
|
(<code>module: ESNext</code>, no bundler). HTML pages live in
|
|
|
|
|
<code>source/pages/</code> and are copied to <code>build/app/</code> by
|
|
|
|
|
<code>scripts/copy-pages.js</code>. Build with <code>npm run build</code>.
|
2026-07-06 17:28:59 +00:00
|
|
|
</p>
|
|
|
|
|
<div class="tags">
|
|
|
|
|
<span class="tag">Web Components</span>
|
|
|
|
|
<span class="tag">raw CSS</span>
|
|
|
|
|
<span class="tag">module: ESNext</span>
|
|
|
|
|
<span class="tag">no bundler</span>
|
|
|
|
|
<span class="tag">tsc --build</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="card">
|
|
|
|
|
<h3>Shared Library</h3>
|
|
|
|
|
<p>
|
|
|
|
|
A personal TypeScript library lives as a git submodule at
|
2026-07-12 12:01:01 +00:00
|
|
|
<code>source/library-ts/</code>. It has two parts: <code>browser/</code>
|
2026-07-06 17:28:59 +00:00
|
|
|
(DOM-capable) and <code>node/</code> (Node.js only). The browser part is
|
2026-07-14 12:34:47 +00:00
|
|
|
compiled separately via TypeScript project references into
|
|
|
|
|
<code>build/app/library-ts/browser/</code>. The node part is included by
|
|
|
|
|
<code>tsconfig.ts-node.json</code>.
|
2026-07-06 17:28:59 +00:00
|
|
|
</p>
|
|
|
|
|
<div class="tags">
|
|
|
|
|
<span class="tag">git submodule</span>
|
2026-07-12 12:01:01 +00:00
|
|
|
<span class="tag">source/library-ts/</span>
|
2026-07-06 17:28:59 +00:00
|
|
|
<span class="tag">project references</span>
|
|
|
|
|
<span class="tag">composite: true</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
<footer>
|
|
|
|
|
Roject — developer documentation
|
|
|
|
|
</footer>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
<script>var NAV_ROOT = '../';</script>
|
|
|
|
|
<script src="../_assets_/nav-data.js"></script>
|
|
|
|
|
<script src="../_assets_/nav.js"></script>
|
|
|
|
|
</body>
|
|
|
|
|
</html>
|