# Board Classifieds Redesign ## Overview Replace the Board's passive tag-matching system with an active classifieds board where members post what they're seeking and offering. Posts are the single source of truth for board presence. The UI follows a corkboard/zine card layout. All communication happens on Slack via curated topic channels. ## Goals - Give members a reason to browse and return to the Board - Make the Board feel like a BBS — fun, personal, alive - Push all conversation to Slack (no in-app messaging) - Replace the abstract tag-state system with concrete, human-readable posts ## Design Decisions | Decision | Choice | Rationale | |----------|--------|-----------| | Visual style | Corkboard / zine cards | Fits existing design language, gives each post personality | | Posts vs matching | Posts replace tag-matching entirely | Single source of truth, simpler mental model | | Post lifecycle | Evergreen until removed by author | Simple, member-managed | | Posts per member | Unlimited | Community will self-regulate | | Slack integration | Web URL links to curated topic channels | `gammaspace.slack.com/archives/{channelId}` — tested, works reliably | | Slack deep links | Protocol (`slack://`) and app links do not work | Tested — only web URL format opens the correct channel | | Channel management | Admin-managed, curated set with tag mapping | Admin UI to map cooperative tags to Slack channels | | Unmapped tags | No Slack link shown | No fallback channel | | Visibility | All members see all posts | Behind `members-auth` middleware | | Migration | None needed | Pre-launch, test data only | ## Data Model ### New: `BoardPost` ``` author ObjectId, ref Member, required title String, required, max 120 seeking String, optional, max 500 offering String, optional, max 500 note String, optional, max 300 tags [String] — slugs from cooperative tag pool createdAt Date updatedAt Date ``` Validation: at least one of `seeking` or `offering` is required. ### New: `BoardChannel` ``` name String, required — display name (e.g. "Structure & Governance") slackChannelId String, required — Slack channel ID (e.g. "C09DDGZGXAP") tagSlugs [String] — cooperative tag slugs mapped to this channel createdAt Date updatedAt Date ``` ### Member Model Changes **Remove:** - `board.topics` (array of tag/state objects) - `board.details` - `board.offerPeerSupport` - `board.availability` - `board.personalMessage` **Keep:** - `board.slackHandle` — author's Slack identity, shown on posts - Privacy toggle for Slack handle visibility ## Board Page ### Layout Corkboard card grid. 2 columns on desktop, 1 column at ≤1024px. Newest posts first. ### Header - Page title "Board" with post count subtitle - "+ New Post" button - Tag filter drawer (existing pattern — toggleable, filters posts by tag) ### Post Card Each card displays: - **Type indicator:** SEEKING (gold) / OFFERING (green) / SEEKING ↔ OFFERING (ember) — derived from which fields are filled - **Title** — prominent, Brygada 1918 - **Seeking text** — if present - **Offering text** — if present - **Note** — personal touch, slightly different visual treatment - **Tags** — dashed-border pills - **Footer:** author avatar + name + circle badge - **Slack link:** "Discuss on Slack →" linking to mapped channel. Only shown if post's tags map to a channel. Uses `https://gammaspace.slack.com/archives/{channelId}`. If tags map to multiple channels, use the first match. ### New Post Form Inline at top of the Board page (not a modal). Fields: - Title (required, 120 chars) - Seeking (optional, 500 chars) - Offering (optional, 500 chars) - Note (optional, 300 chars) - Tags (multi-select from cooperative tag pool) Validation: at least one of seeking/offering required. Form appears on "+ New Post" click, collapses after submission. ### Empty State Friendly prompt to be the first to post, with link to create. ## Profile Board Section Replaces the current cooperative tag selector, details textarea, and peer support section. ### Shows - List of member's active posts (compact card previews) - Edit and delete actions per post - "+ New Post" button (navigates to Board page or opens same inline form) - Slack handle setting (identity-level, not per-post) - Privacy toggle for Slack handle ### Removes - `CooperativeTagSelector` three-state tag picker - Details textarea - Offer Peer Support toggle + conditional fields (availability, personal message) ### No Posts State Prompt to visit the Board and post something. ## Admin: Board Channels New admin page for managing Slack channel mappings. ### UI - List of board channels showing: display name, Slack channel ID, mapped tags - Add / edit / remove channels - Tag mapping: multi-select from cooperative tags - Unmapped tag indicator: shows cooperative tags not yet assigned to any channel ### Behavior - Admins create channels in Slack manually, then register them here by pasting the channel ID - Frontend uses the channel list to build Slack links on post cards ## API Routes ### New | Method | Path | Auth | Purpose | |--------|------|------|---------| | GET | `/api/board/posts` | member | List all posts, newest first. Tag filtering via query params. Populates author name/avatar/circle/slackHandle. | | POST | `/api/board/posts` | member | Create a post. Validates at least one of seeking/offering. | | PATCH | `/api/board/posts/:id` | member (own post) | Edit a post. | | DELETE | `/api/board/posts/:id` | member (own post) | Delete a post. | | GET | `/api/board/channels` | member | List channels with tag mappings (for building Slack links). | | GET | `/api/admin/board-channels` | admin | List channels for admin UI. | | POST | `/api/admin/board-channels` | admin | Create channel mapping. | | PATCH | `/api/admin/board-channels/:id` | admin | Update channel mapping. | | DELETE | `/api/admin/board-channels/:id` | admin | Remove channel mapping. | ### Remove | Path | Reason | |------|--------| | `GET /api/board/suggestions` | Replaced by posts | | `PATCH /api/members/me/board` | Board profile fields removed (slackHandle stays on existing member profile patch) | ## Components ### Stays (repurposed) - `CooperativeTagSelector` — simplified to a plain tag picker (no three-state toggle) for use in post creation form ### Goes - Match-card UI on Board page - Peer support section on profile page ### New - `BoardPostCard` — the corkboard card component - `BoardPostForm` — inline creation/edit form - `BoardPostList` — grid layout for post cards (used on Board page and profile) - Admin channel management components ## Composables ### Remove - `useBoard` (the old `getSuggestions` wrapper) ### New - `useBoardPosts` — CRUD for posts, tag filtering - `useBoardChannels` — fetch channel mappings, resolve tag→channel for Slack links