# 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
