# 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. ```ts activeBlog: BlogRef | null blogs: BlogSummary[] onCreateBlog: () => void onSelectBlog: (blog: BlogRef) => void disabled?: boolean ``` **PostEditor** — Slate-based editor with autosave and preview. ```ts mode: 'create' | 'edit' blog: BlogRef value: EditorState onChange: (s: EditorState) => void onSaveDraft: (s: EditorState) => Promise onPublish: (input: PublishInput) => Promise canPublish: boolean status: 'idle'|'saving'|'publishing'|'error'|'success' ``` **PostList** — virtualized list scoped to active blog. ```ts blog: BlogRef filters: PostFilters onOpenPost: (id: Id) => void ``` **MembersPanel** (shared blogs). ```ts blog: BlogRef members: Membership[] onInvite: (name: NameRef, role: Role) => Promise onRemove: (name: NameRef) => Promise currentUserRole: Role ``` **Header/Nav** — global actions. ```ts 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 `` 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.