Skip to content

feat(authoring-screens): mutation flows for create/edit/post/manage#38

Merged
themightychris merged 12 commits into
mainfrom
feat/authoring-screens
May 17, 2026
Merged

feat(authoring-screens): mutation flows for create/edit/post/manage#38
themightychris merged 12 commits into
mainfrom
feat/authoring-screens

Conversation

@themightychris
Copy link
Copy Markdown
Member

Summary

Implements the authoring-screens plan, replacing the public-screens read-only stubs with real authoring flows:

  • Project create / edit (/projects/create, /projects/:slug/edit) — full form with slug availability check, markdown overview, tag pickers, staff featured toggle, admin Danger-zone delete-with-undo-toast.
  • Modal flows from /projects/:slug — Post Update, Post Help-Wanted Role, Add Member, Manage Members (role edit / transfer maintainer / remove), Express Interest, Fill Role, Close Role.
  • Help-Wanted index — "Post a role" picker that redirects to the chosen project with the post-role modal pre-opened.
  • Profile edit (/members/:slug/edit) — name, bio (MarkdownEditor), staff slug rename, Slack handle, topic + tech tag pickers, multipart avatar upload.
  • Account settings (/account) — identity card, newsletter toggle (private-only PATCH), sessions table with revoke + sign-out, legacy-claim entry, danger zone.
  • Tag management — inline Edit / Merge / Delete buttons on /tags/:namespace/:slug for staff.

Shared building blocks:

  • MarkdownEditor component with toolbar + char count. Preview is rendered server-side via new POST /api/_preview per specs/behaviors/markdown-rendering.md — no client-side markdown library in the bundle (verified by grep on the production build).
  • TagPicker — namespace-scoped autocomplete against /api/tags. Staff can create new tags inline.
  • Sonner <Toaster> mounted in App for success / error toasts on every mutation.

Test plan

  • npm run -w apps/web type-check / npm run -w apps/api type-check clean
  • npm run lint clean
  • npm run -w apps/web test — 11 files, 30 tests passing (includes new ProjectEdit create-flow smoke test and ExpressInterestModal happy + rate-cap tests)
  • npm run -w apps/web build succeeds and emits no markdown library symbols (verified grep -E 'remark|micromark|markdown-it|marked|unified' dist/assets/*.js returns zero)
  • POST /api/_preview API tests pass (4/4, including sanitization of <script> + javascript: URLs)
  • Browser validation against running dev server: /projects/create and /members/:slug/edit show "Sign in required" for anonymous users; /account redirects anonymous → /login?return=/account; no Sign in to … stubs remain except the genuinely-anonymous CTAs called out in the plan ("Sign in to contribute" on project detail header, "Sign in to express interest" on help-wanted cards)

🤖 Generated with Claude Code

npm install -w apps/web react-hook-form @hookform/resolvers sonner zod
npx shadcn@latest add select textarea label checkbox --yes --cwd apps/web
Used by the shared <MarkdownEditor> on every authoring screen so that no
markdown library ships to the client. Renders source through the same
sanitize-and-demote pipeline that produces serialized *Html fields, with a
50k-char cap.
- POST/PATCH/DELETE methods for projects, members, updates, buzz,
  help-wanted, people, tags, plus session revoke and newsletter toggle.
- Auto-set Content-Type on string bodies.
- Slugify helper for client-side title→slug derivation.
- Forward refs in shadcn Input / Textarea so react-hook-form and
  imperative focus/selection work.
MarkdownEditor: side-by-side source + preview, toolbar, char count.
Preview is rendered server-side via POST /api/_preview per
specs/behaviors/markdown-rendering.md — no client-side markdown library.

TagPicker: namespace-scoped autocomplete against /api/tags. Staff can
create new tags inline; non-staff sees autocomplete only.
- PostUpdateModal — composes via MarkdownEditor, posts to updates
- PostHelpWantedModal — title, description, hours, tags
- AddMemberModal — slug + optional role; inline 409 error surfaced
- ManageMembersModal — inline role edits, transfer, remove
- ExpressInterestModal — optional message; honors 30-day rate-cap
- FillRoleModal — optional filledBySlug
- PostRolePickerModal — project picker for /help-wanted CTA
- TagEditModal — staff edit/merge with confirmation
- ProjectEdit (/projects/create + /projects/:slug/edit): title, slug
  with availability check (staff-only on edit), summary, overview
  (MarkdownEditor), stage select, links, chat channel, tag pickers,
  staff featured toggle, admin Danger-zone delete-with-undo-toast.
- ProfileEdit (/members/:slug/edit): name, bio, slug rename for staff,
  Slack handle, topic + tech tag pickers, avatar multipart upload.
- Account (/account): identity card (GitHub-sourced), newsletter toggle
  via private-only PATCH, sessions table with revoke/sign-out,
  legacy-claim link, danger zone.
- App.tsx: route /projects/create + /:slug/edit → ProjectEdit;
  /members/:slug/edit → ProfileEdit; /account → Account; mount Sonner
  Toaster.
- ProjectDetail: replace disabled Post Update with PostUpdateModal,
  surface Add Member / Manage Members buttons for maintainer+staff,
  Express Interest + Fill / Close transitions, +Add in Members
  sidebar; honor ?openModal=help-wanted from the picker.
- HelpWantedCard: open ExpressInterestModal instead of disabled stub.
- HelpWantedIndex: 'Post a role' picker for signed-in users.
- TagDetail: staff inline Edit / Merge / Delete via TagEditModal.
…tModal

- ProjectEdit: filling title auto-fills slug and POST /api/projects fires
  with the right payload (happy path).
- ExpressInterestModal: POSTs to the correct express-interest endpoint
  with optional message; 30-day rate-cap is exercised via 409
  already_expressed mock.
… 400 to 422

Fastify's ajv validation returns statusCode 400 but the project's
setErrorHandler converts every body validation failure into the
unified 422 validation_failed envelope (see apps/api/src/lib/errors.ts).
@themightychris themightychris force-pushed the feat/authoring-screens branch from 0c8cf45 to 7c7ff04 Compare May 17, 2026 00:52
@themightychris themightychris merged commit e7c6998 into main May 17, 2026
1 check passed
@themightychris themightychris deleted the feat/authoring-screens branch May 17, 2026 00:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant