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 (oralt=""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
anyin 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.