rojects/workspace/outline/index.html

160 lines
7.1 KiB
HTML
Raw Normal View History

<!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">
<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>
<h2>Project Outline</h2>
<div class="card">
<h3>What it is</h3>
<p>
Roject is a self-hosted, browser-based CMS for creating, editing, and storing
HTML documents with assets, organised into projects. It is designed for individual
developers or small teams who want a lightweight authoring environment with no
external database dependency.
</p>
</div>
<div class="card">
<h3>What exists now</h3>
<p>
User accounts with registration, login, logout, and account deletion.
Groups and projects with member management (viewer / editor / admin roles).
Each project gets a real directory on disk at <code>storage/&lt;uuid&gt;/root/</code>
with a default <code>index.html</code> on creation.
</p>
<p style="margin-top:0.75rem">
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>&lt;tab-container&gt;</code>. Tabs are draggable
between containers. The Left panel shows the file tree with create, rename,
and delete for files and folders. The Center panel holds the WYSIWYG HTML
editor (iframe, <code>contenteditable</code>, MutationObserver, undo/redo,
Ctrl+S save). The Right panel is empty by default and receives dropped tabs.
</p>
<p style="margin-top:0.75rem">
A <code>FileEditorRegistry</code> routes files to the correct panel by suffix.
HTML files open in <code>html-editor-panel</code>; all other known text formats
open in <code>code-panel</code> (CodeMirror 5, syntax highlighting, dark theme,
Pin/Undo/Redo/Save toolbar). The registry checks an optional project-level
<code>workspace/editor/file-editors.json</code> first, then falls back to
in-memory defaults. Unknown extensions show an error in the file tree instead
of attempting to open.
</p>
<p style="margin-top:0.75rem">
A <code>rojo-chat-panel</code> provides a streaming AI chat interface backed
by a LangChain + OpenAI-compatible model. Each panel instance holds its own
conversation session in memory.
A reusable <code>&lt;confirm-dialog&gt;</code> component replaces browser
<code>confirm()</code> for destructive actions (currently project deletion).
</p>
</div>
<div class="card">
<h3>What still needs work</h3>
<p>
This is a loose reminder, not a fixed backlog. Things we know are missing or
incomplete: the Right panel has no default content and relies on manual tab
dragging to populate; portrait mode's secondary section switcher
(when a panel has multiple side-by-side sections) is not yet wired up; the
member list UI shows raw UUIDs instead of usernames; the group editor and
account delete button still use the browser <code>confirm()</code> instead of
the custom dialog; non-text files (images, PDFs) in the tree are visible but
not openable (a <code>MediaViewerPanel</code> is planned); and there is no
real-time multi-user collaboration yet.
</p>
</div>
</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>.
No database — all data lives as JSON files in <code>data/</code>
(auto-created on first run). Auth uses <code>express-session</code> +
<code>bcryptjs</code>. All entity IDs are UUIDs via
<code>crypto.randomUUID()</code> — no central counter, safe for parallel
instances. Start the server with <code>npm start</code>.
</p>
<div class="tags">
<span class="tag">Node.js</span>
<span class="tag">Express</span>
<span class="tag">ts-node</span>
<span class="tag">express-session</span>
<span class="tag">bcryptjs</span>
<span class="tag">UUID IDs</span>
</div>
</div>
<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
<code>src/components/&lt;name&gt;/</code>. CSS uses the element tag as root
selector with <code>display: block</code>. TypeScript compiles to
<code>public/components/</code> via <code>tsconfig.client.json</code>
(<code>module: ESNext</code>, <code>moduleResolution: bundler</code>, no
bundler). HTML pages load components with
<code>&lt;script type="module"&gt;</code>. Shared state uses a module-level
singleton (<code>editor-state.ts</code>) rather than globals.
Build with <code>npm run build</code>.
</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
<code>src/library-ts/</code>. It has two parts: <code>browser/</code>
(DOM-capable) and <code>node/</code> (Node.js only). The browser part is
compiled separately via TypeScript project references
(<code>src/library-ts/browser/tsconfig.roject.json</code>, <code>strict: false</code>)
into <code>public/library-ts/browser/</code>. The node part is included by
<code>tsconfig.ts-node.json</code> (extends server config, <code>strictNullChecks: false</code>).
</p>
<div class="tags">
<span class="tag">git submodule</span>
<span class="tag">src/library-ts/</span>
<span class="tag">project references</span>
<span class="tag">composite: true</span>
</div>
</div>
</section>
<footer>
Roject &mdash; developer documentation
</footer>
</div>
<script>var NAV_ROOT = '../';</script>
<script src="../_assets_/nav-data.js"></script>
<script src="../_assets_/nav.js"></script>
</body>
</html>