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

216 lines
7.8 KiB
Markdown

# 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<void>
onPublish: (input: PublishInput) => Promise<void>
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<void>
onRemove: (name: NameRef) => Promise<void>
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 `<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.