TYPO3-style backend shell: module rail | page tree | module content #33

Closed
opened 2026-07-14 18:47:19 +02:00 by dominik.polakovics · 0 comments

Restructure the backend UI into a TYPO3-style shell: module rail | page tree | module content, replacing the current always-visible tree | edit | preview three-column layout.

Motivation

  • Extensibility: the module rail is the point — Page and View are the first two modules; more (media, settings, …) will follow. Modules must be a real registry (id, icon, label, component), not two hardcoded screens.
  • Workflow: persistent tree + module switching for editing vs. previewing a page.
  • Familiarity: editors know TYPO3; match its mental model.

Shell layout

  • Dark top header stays as-is (brand, Publish all, status pill, language switcher).
  • Below it, three columns:
    1. Module rail — icon-only, ~48px, tooltips. Icons from an icon library dependency (e.g. lucide-solid) so future modules get icons for free.
    2. Page tree — drag-resizable with persisted width, collapsible to give the module full width. Architecturally per-module-optional (a future module may not want a tree), though both current modules show it.
    3. Module content — the active module fills the rest.

Modules (strictly exclusive, TYPO3-pure)

  • Page module: the edit screen, full-width; element list + form in a centered max-width (~720–860px) column. Keeps the existing publish/discard/undo header and page-settings toggle.
  • View module: the preview iframe, full-width, keeps the existing desktop/mobile viewport toggle in its own toolbar.
  • The current side-by-side edit+preview layout goes away.

Preview bridge

  • Clicking an element in the View preview jumps to the Page module with that element selected (bridge becomes a cross-module navigation gesture; hover-highlight may stay).
  • In-iframe link browsing is free-form and does not sync tree selection or URL.

Routing

  • Add @solidjs/router. URL scheme: /:module/:lang/*path (e.g. /page/en/blog/post.md).
  • Module, language, and page are deep-linkable and reload-safe; the Go server's index.html fallback (internal/server/server.go serveStatic) already supports client routes.
  • URL replaces the sessionStorage page-selection persistence as source of truth. Element selection stays ephemeral (not in URL).
  • Switching modules preserves the selected page; switching pages preserves the module.
  • / redirects to /page/<defaultLang>. A URL naming a nonexistent page falls back to the empty state (no error page).
  • Empty state (no page in URL): neutral "select a page from the tree" placeholder; no auto-selection.

Unsaved-changes guard (new feature)

Navigation guard on module switch, tree page switch, and browser beforeunload: prompt discard / save & continue / stay. Today there is no guard; FormPane has real local dirty state with an explicit Save button.

Scope boundaries

  • Layout-only: tree supports select + expand/collapse only; create/rename/move/delete stay where they live today. Context menus and drag-and-drop are follow-ups.
  • No mobile/responsive layout — desktop-first backend, like TYPO3.
  • Tree expansion state and preview viewport keep their sessionStorage persistence.

Main change points

  • web/src/App.tsx:205 and web/src/styles.css:76 — the .app-body grid becomes rail | tree | content.
  • New module registry + rail component.
  • Routing wired into web/src/selection.ts (URL becomes the selection source of truth).
  • PagePane and PreviewPane become the two module bodies.
Restructure the backend UI into a TYPO3-style shell: **module rail | page tree | module content**, replacing the current always-visible `tree | edit | preview` three-column layout. ## Motivation - **Extensibility:** the module rail is the point — Page and View are the first two modules; more (media, settings, …) will follow. Modules must be a real registry (id, icon, label, component), not two hardcoded screens. - **Workflow:** persistent tree + module switching for editing vs. previewing a page. - **Familiarity:** editors know TYPO3; match its mental model. ## Shell layout - Dark top header stays as-is (brand, Publish all, status pill, language switcher). - Below it, three columns: 1. **Module rail** — icon-only, ~48px, tooltips. Icons from an icon library dependency (e.g. `lucide-solid`) so future modules get icons for free. 2. **Page tree** — drag-resizable with persisted width, collapsible to give the module full width. Architecturally per-module-optional (a future module may not want a tree), though both current modules show it. 3. **Module content** — the active module fills the rest. ## Modules (strictly exclusive, TYPO3-pure) - **Page module:** the edit screen, full-width; element list + form in a centered max-width (~720–860px) column. Keeps the existing publish/discard/undo header and page-settings toggle. - **View module:** the preview iframe, full-width, keeps the existing desktop/mobile viewport toggle in its own toolbar. - The current side-by-side edit+preview layout goes away. ## Preview bridge - Clicking an element in the View preview **jumps to the Page module** with that element selected (bridge becomes a cross-module navigation gesture; hover-highlight may stay). - In-iframe link browsing is free-form and does **not** sync tree selection or URL. ## Routing - Add `@solidjs/router`. URL scheme: `/:module/:lang/*path` (e.g. `/page/en/blog/post.md`). - Module, language, and page are deep-linkable and reload-safe; the Go server's index.html fallback (`internal/server/server.go` serveStatic) already supports client routes. - URL replaces the sessionStorage page-selection persistence as source of truth. Element selection stays ephemeral (not in URL). - Switching modules preserves the selected page; switching pages preserves the module. - `/` redirects to `/page/<defaultLang>`. A URL naming a nonexistent page falls back to the empty state (no error page). - Empty state (no page in URL): neutral "select a page from the tree" placeholder; no auto-selection. ## Unsaved-changes guard (new feature) Navigation guard on module switch, tree page switch, and browser `beforeunload`: prompt **discard / save & continue / stay**. Today there is no guard; `FormPane` has real local dirty state with an explicit Save button. ## Scope boundaries - **Layout-only:** tree supports select + expand/collapse only; create/rename/move/delete stay where they live today. Context menus and drag-and-drop are follow-ups. - No mobile/responsive layout — desktop-first backend, like TYPO3. - Tree expansion state and preview viewport keep their sessionStorage persistence. ## Main change points - `web/src/App.tsx:205` and `web/src/styles.css:76` — the `.app-body` grid becomes rail | tree | content. - New module registry + rail component. - Routing wired into `web/src/selection.ts` (URL becomes the selection source of truth). - `PagePane` and `PreviewPane` become the two module bodies.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Cloonar/deckle#33
No description provided.