Files
q-blog/docs/Q-Blog_Project_Instructions.md
greenflame089 0b100af686 Release v0.2.2
2025-08-22 07:28:42 -04:00

7.8 KiB

Q-Blog — Project Instructions (1.0 Track)

Generated 2025-08-16 23:37Z

Default instructions for all Q-Blog chats. Optimize for correctness, accessibility, collaboration, and a focused writing UX. Keep answers decisive and artifact-oriented.


1) Intent

Q-Blog is a modern blogging workspace for individuals and small teams. Writers can own multiple blogs under one Name, and enable Shared Blogs with roles (Owner/Editor/Author). North star: inclusive, predictable publishing with a resilient, testable UI.


2) Core flows & stable components (props)

Flows: Read → Draft → Edit → Publish → Manage Blogs → Collaborate.

BlogSwitcher — select active blog; scopes all lists/forms.

activeBlog: BlogRef | null
blogs: BlogSummary[]
onCreateBlog: () => void
onSelectBlog: (blog: BlogRef) => void
disabled?: boolean

PostEditor — Slate-based editor with autosave and preview.

mode: 'create' | 'edit'
blog: BlogRef
value: EditorState
onChange: (s: EditorState) => void
onSaveDraft: (s: EditorState) => Promise<void>
onPublish: (input: PublishInput) => Promise<void>
canPublish: boolean
status: 'idle'|'saving'|'publishing'|'error'|'success'

PostList — virtualized list scoped to active blog.

blog: BlogRef
filters: PostFilters
onOpenPost: (id: Id) => void

MembersPanel (shared blogs).

blog: BlogRef
members: Membership[]
onInvite: (name: NameRef, role: Role) => Promise<void>
onRemove: (name: NameRef) => Promise<void>
currentUserRole: Role

Header/Nav — global actions.

onOpenMembers?: () => void
onCreatePost: () => void
onSwitchBlog: () => void
unreadCount?: number

Stable props change only via coordinated refactor with tests & docs.


3) Tech & repo posture

React 18 + TypeScript (strict) + Vite; MUI v5; Slate editor; Redux Toolkit + RTK Query; i18next (strings).
Testing: Vitest + RTL + user-event + MSW + jest-axe.
Config parity across dev/test/build (aliases, JSX, TS). Alias: @ → src. Layout: src/, tests/, docs/, .gitea/.


4) Behavior contracts

Blog scoping & routing

  • Every view is scoped to active blog. Route params encode scope (conceptually /{name}/{blog}/...). Changing blog updates lists/forms without leaks.

Editor & autosave

  • Debounced autosave writes drafts with polite live region announcements. Clear “Last saved” time; explicit Publish pathway. Toolbar enable/disable is deterministic from selection.

Post lifecycle

  • States: draft | scheduled | published | archived. Idempotent publish; show attribution (createdBy, updatedBy, updatedAt).

Media

  • Client validates type/size; shows upload progress; failed uploads are retryable; all <img> have alt (or alt="" if decorative).

5) Accessibility (A11y)

  • Landmarks: header/nav/main/footer; Skip link focuses main. One H1 per route.
  • Keyboard: all controls reachable; Esc closes dialogs/popovers and restores focus.
  • Names/roles/states: explicit labels; toggles expose aria-pressed.
  • Live regions: succinct progress for save/publish/upload; no spam.
  • Preferences: honor prefers-reduced-motion; enforce contrast tokens.
  • Tests: axe checks for key pages; keyboard journey tests for protected flows.

6) Data, permissions & contracts

  • Entities: Name 1..N Blog; Post 1..1 Blog (immutable link). (nameId,blogHandle) unique.
  • Roles: Owner (all), Editor (edit any, manage drafts), Author (own posts). Deny by default.
  • RTK Query is the only remote path; queries/mutations define cache keys by blog.
  • Validation: Prefer Zod for forms & responses (or JSON Schema + AJV if aligning w/ Q-Chess); failed validation → friendly error with retry path.
  • Concurrency: optimistic where safe; use revision/ETag to detect conflicts; show resolve UI on 409.

7) Testing standards

  • Register matchers once in tests/setup.ts. Use accessible queries (getByRole, getByLabelText).
  • Unit: selectors, reducers, guards (can()), formatters, sanitizers.
  • Component: editor toolbar & autosave, blog switch scoping, lists (virtualized), dialogs focus.
  • A11y: axe smoke on read/draft/manage; keyboard-only journeys.
  • MSW: success + error + invalid payload paths. Deterministic tests; fake timers for debounce.
  • Coverage gate per package; exclude fixtures/build artifacts.

8) Performance & resilience

  • Virtualize long lists; memoize high-churn components.
  • Abortable fetch with timeouts; retry/backoff for GETs; idempotency keys for create/update.
  • Perceived speed: skeletons & optimistic UI (draft saves); defer non-critical work to idle.
  • Offline-friendly drafts: queued writes with clear status and conflict handling.

9) TypeScript posture

Strict mode, zero any in public props; no @ts-nocheck. Prefer discriminated unions for async/status shapes. Treat red squiggles as must fix before PR.


10) Security & content safety

  • Sanitize editor output on save and render (DOMPurify allowlist). Never render untrusted HTML directly.
  • Validate inputs at boundaries; never trust client-visible state for authorization (server checks required).
  • Error boundaries: route-level and editor-level with friendly fallback + “copy details” action.
  • Minimal telemetry for quality (crashes, vitals); no PII.

11) Internationalization & theming

Centralize strings; use Intl for dates/numbers; prep RTL-safe layouts. Theme tokens (color/spacing/typography) audited for WCAG AA; respect prefers-color-scheme.


12) Docs & decision hygiene

Docs live in docs/. Keep: ARCHITECTURE, TESTING, ACCESSIBILITY, SECURITY, USER_JOURNEYS, GLOSSARY, RISKS, ROADMAP_DEPENDENCIES, DECISIONS/ (short ADRs). Update docs when behavior or contracts change.


13) Delivery & workflow (assistants)

  • Prepare files locally; share download links (send full files once edits exceed a few lines). Keep a resendable copy.
  • Prefer thin vertical slices (schema→API→state→UI→tests→docs). Include acceptance notes + quick verify.
  • If assumptions are needed, state them briefly and proceed with a concrete artifact.

14) Single source of truth (constants)

Centralize shared constants and import everywhere: roles, statuses, limits (upload sizes), blog handle rules, debounce durations, routes, a11y labels. UI, data, and tests must reference the same values.


15) Versioning & releases

SemVer with human changelogs; each release includes notes, migration steps, and quick verify. CI gates: typecheck, lint (jsx-a11y), unit/component tests, axe smoke, coverage, build.


16) Common error → action

  • MUI v4 import fails → switch to @mui/material / @mui/icons-material.
  • Unexpected HTML execution → sanitize on save+render; add unit tests with known XSS vectors.
  • Data shape mismatch → validation failed: show friendly error; log redacted details; fix schema or endpoint.
  • Keyboard trap → ensure focus trap + restore; add test.
  • Leaked posts across blogs → check scoping (selector/query keys) and route params; add failing test then fix.

17) Checklists

Before sending anything

  • No red underlines; strict TS passes.
  • Vite build + Vitest green (unit & component); axe smoke passes (no criticals).
  • Dev/test/build configs match (aliases, JSX, TS options).
  • Public props typed; callers match; no any in props.
  • Landmarks + labels; toggles use aria-pressed; live regions only when meaningful.
  • Lists scoped to active blog; routes stable and shareable.
  • Editor: autosave status visible; publish path explicit; sanitized output.

Thin vertical delivery

  • Code + tests + docs move together.
  • Include acceptance criteria and quick verification steps.
  • If any contract changes, add/adjust a short Decision Record.