Page - bitcobblers/wod-wiki GitHub Wiki
[!info] Review status Current State describes the stored Page; Future State describes recommended page composition for feedback. No new fields, mode rules or ticket resolutions are implemented here. See todo#Datatype review guide.
-
Store:
page -
Key path:
id(UUID) -
Type source:
apps/playground/src/types/storage.ts -
Database version:
wodwiki-db(v23)
The stored Page is a grouping/address record for notes, not a content-bearing Note row:
-
Calendar page —
date(YYYY-MM-DD) defines the journal-date route; one per journal date. -
Custom page —
slugdefines a named route for a grouped collection of notes.
Notes associate with Pages via the PageNote junction table (page_notes). Page has no body text, segments, or tags of its own; authored workout logic lives strictly in Note.
Library note and block results resolve named routes from Page.slug through
page_notes. Entry.pageId retains the Page UUID; Entry.pageSlug supplies
/p/:slug. Membership ordering uses position, then creation time, and skips
calendar pages when choosing a named route. Notes without a named page open
at /notes/:noteId; result recording keeps that note's UUID.
| Field | Type | Notes |
|---|---|---|
id |
string | UUID |
date? |
string | YYYY-MM-DD — calendar page; unique when present |
slug? |
string | Custom page slug; unique when present |
title? |
string | Display name |
createdAt |
number | Unix ms |
| Index | Key path | Unique | Purpose |
|---|---|---|---|
by-date |
date |
yes | calendar route lookup |
by-slug |
slug |
yes | named route lookup |
None.
-
PageNote.
pageId— membership junction between Page and Note - Legacy denormalized
pageIdon child rows (Session, Attachment, EventRecord) is deprecated; canonical joins and telemetry resolve exclusively through Note.id.
- A rendered page composes one or more Notes. Any authored description/configuration belongs to the owning note's
rawContent, not a duplicatePage.bodyor categories/provenance payload on the grouping row. - Keep calendar/custom addressing and existing placement. A note may appear in multiple query-composed pages without acquiring multiple
pageIdvalues; query inclusion belongs in collection. - A composed view must retain each note's identity, order and write target. Start with per-note editing; seamless whole-page editing needs transaction-mapped ownership boundaries before it is safe.
- Do not extend
pageIdcopying to more stores merely for reuse. Existing copies need a defined update policy when a note moves; this review does not prescribe an index-drop migration. - Keep journal
Page.dateseparate from content creation/import time. Displaying a note on a date does not rewrite its source history. -
The
/p/:sluguniversal page umbrella: any slug is a page and renders generically at/p/:slug. Specialized prefix routes (/c/:slugfor collections,/e/:slugfor efforts,/d/:slugfor dashboards) provide tailored interactions for those slug types, but resolve to the same underlying Page presentation model. -
Navigation identity: lists retain
noteIdfor canonical editing and result ownership,pageIdfor the Page UUID, andpageSlugfor/p/:slugviewing. -
Per-note edit boundary preservation: multi-note pages compose distinct notes rather than concatenating text into a single editable string. Each embedded note maintains its independent
noteId, versioned segments, and save target.
Known implementation gap: the review's isolated JournalDatePage slicing reproduction lost a line inserted near a note boundary. That is evidence about its fixed-offset algorithm, not a live browser/persistence test. It blocks extending concatenated editing, not read-only multi-note presentation.
Owner: Define the mode-resolution rule matrix (read-only vs edit).
Proposed precedence: source authority limits writes → selected mode controls authoring → note type supplies defaults → layout places controls. Evaluate authority against the actual owning note, not one permission flag for the whole page.
| Action | Recommended read presentation | Recommended edit presentation |
|---|---|---|
| Change text, query definitions or widget configuration | No protected-source write; offer an explicit supported Edit/copy workflow. | Validate and save to the identified note; retain draft on failure or stale revision. |
| Run, inspect, follow links, adjust temporary filters | Allowed when supported by the host; does not imply source authoring. | Same shared actions. |
| Save results or attachments | Separate explicit destination; see Session and Attachment. | Same destination requirement. |
| Try a syntax example or feed scratch | Local/example content may be editable without changing teaching/seed source. | Authoring source is a distinct operation. |
| Persist dashboard defaults | Explicit source-authoring operation, not an implicit consequence of exploring a chart. | Write through the guarded note-authoring path. |
- Is clone-to-edit universal? Proposed answer: no. Retain explicit personal copies where supported, ephemeral syntax examples, and existing persisted feed scratches. These differences are not automatically bugs.
- What is the shared mode mechanism? Proposed answer: hosts derive allowed source actions, and shared editor/widget adapters enforce them. CodeMirror read-only state alone does not reject direct programmatic transactions; hide authoring controls and guard source-write operations while permitting trusted document loads.
-
Where do controls live? Retain the map's proposed desktop-header/mobile-overflow placement using existing
ResponsiveActions; no responsive fields on Page. Provide a discoverable exit from editing, keyboard access, focus restoration and save/error state. - Still open: default read/edit mode and toggle/copy availability for each supported type/source combination. Also decide which dashboard controls are temporary versus persistent. Read-safe source protection need not wait for a closed type enum.
Owner for syntax: Resolve syntax pages as typed notes.
| Question | Proposed answer / remaining feedback |
|---|---|
| What is authored? | Note content and teaching configuration; avoid a second independent segment list in Page. The exact syntax descriptor/configuration fields remain open. |
| Is scrolling a stored segment kind? | Not by default. Reuse content/example components within the existing page composer and specialized scroll layout. A new kind must have source semantics beyond its placement. |
| What happens to canvas content? | Map prose, buttons, widgets, challenges and examples to supported content presentations; preserve unknown source. A per-kind conversion inventory and unsupported-kind behavior remain open, not a promised lossless automatic migration. |
| Does NoteEditor replace MarkdownCanvasPage? | Recommended no forced replacement. Keep the host/composer for scrolling, runtime coordination and responsive layout; share EditorWindow and segment components. Local example edits remain distinct from teaching-source edits. |
Dashboard notes already use dashboard: true and query fences with presentation suffixes; the old dashboard fence is retired. Reuse QueryBlockView, WidgetChart and DashboardView, rather than inventing graph-only storage kinds. Query definitions remain scoped to their own Query Document. Dashboard format/authoring work stays outside this map; the crosswalk owns shared interaction behavior.
Owner: Assemble the crosswalk & behavioral spec.
Recommended answer: judge completeness against the datatype contracts, then assemble their links; do not reopen storage design in a second spec. The final acceptance remains human review, not an automatic resolution from these draft answers.
- Can two journal notes be edited/reordered and reopened without crossing text, result or attachment ownership?
- Can a syntax example run/reset locally while teaching source stays unchanged, including mobile, keyboard and reduced-motion behavior?
- Do identical query widgets retain distinct edit targets and reject stale saves without losing drafts?
- Can collections show empty/error results, navigate to a note and prevent recursive embedding without altering Library deep links?
!