App Home Tab Design Proposal

Date: 2026-04-22 Scope: Design + implement the @brandbot App Home tab as a persistent premium brand surface.

Why the Home tab matters for this product

The Home tab is the ONLY always-visible Slack surface we control — when a user clicks the bot in their sidebar, the Home tab renders. Unlike slash command responses (ephemeral, single-use, disappear on channel switch), Home persists. For a "premium brand agent" product, this is the single best place to deliver the product-surface-not-chat-log experience.

Block budget: 100 (vs. 50 for messages). Roughly 2× what we have to work with on /brand {category}.

Design principles applied

Running the same /critique + /arrange + /typeset lens, plus the shared design language from docs/SLACK-UX.md:

Proposed layout

[image block]  CF navy wordmark on beige (600px wide PNG via rasterizer)
               ← hero identity anchor, visual signature

header: California Forever Brand Guide    ← 📖 prefix? or clean?
context: Powered by Grain & Mortar · {lastUpdated}

divider

header: Tagline
rich_text_preformatted: "Building the next great American city."    ← copy button

divider

header: Mission
section: [one-line truncated mission, plain prose]

divider

header: Colors at a glance
rich_text: (rich_text_section with color swatches, bold name, hex — same pattern as /brand colors but condensed to 4-6 top colors)
context: Full palette → <url|/brand colors>
← "Full palette" context points to the slash command AND the web section

divider

header: Explore the guide
[actions block with URL buttons]:
  [Colors]  [Typography]  [Voice & Tone]  [Messaging]    (row 1 — max 5 per actions block)
  [Foundation]  [Logo]  [Applications]  [Icons]          (row 2 — second actions block)
  [Photography]  [Open full brand guide →]                (row 3)

Each button is a URL button linking to the brand guide site section. Not a slash-command trigger — this keeps things simple (no interactivity endpoint wiring needed for v1) and the full brand guide UX is richer than the Slack summary anyway.

divider

header: Use in Slack
rich_text_list:
  • `/brand colors` (code) — palette with hex + usage
  • `/brand voice` (code) — traits, tone, writing rules
  • `/brand messaging` (code) — tagline, pitch, pillars
  • …

context: 10 commands available. Try `/brand help` for the full list.

divider

context: 📖 View the full brand guide → <url|california-forever-brand-guide.vercel.app>

Total block count: ~25 blocks. Well under the 100 limit, room to expand.

Interaction model

v1 — URL buttons only. Every button in the "Explore the guide" actions block is a URL button (url property, no action_id needed). Clicking opens the brand guide site section in a new tab. This is the simplest approach — no interactivity endpoint wiring, no request signing for button clicks, no action_id → handler routing.

v2 (later) — Action buttons. Wire /app/api/slack/interactivity/route.ts + action_id-based routing so buttons trigger things INSIDE Slack (e.g. post the /brand colors response to the user's DM). Requires a new Slack scope (interactivity.is_enabled: true in manifest) and a re-install. Defer until v1 lands.

Publish trigger

Event-driven via app_home_opened. Subscribe in the Slack app manifest. When the event fires for a user, the /api/slack/events handler:

  1. Looks up tenant by team_id.
  2. Fetches the tenant's brand content (colors + messaging + brand-foundation minimally — three API calls in parallel).
  3. Builds the Home view.
  4. Calls views.publish with the user_id and the view.

Caching: render in-memory per (tenant, user) with a short TTL (60s) so repeat opens in the same minute skip the fetches. Content updates propagate on the next open past TTL.

Scope addition: app_home_opened is a bot event; subscribing requires no new OAuth scope (reads tenant's own bot events). Manifest update + re-install only.

What this doesn't cover

What happens next

  1. Approval on this doc.
  2. Implement in these steps: - Update slack-app-manifest.json to subscribe to app_home_opened. - Reinstall the app in G&M workspace (manifest changes require re-install). - Build a formatHome() formatter in lib/slack/format.ts that returns the view object. - Extend app/api/slack/events/route.ts with an app_home_opened handler that fetches tenant content and calls views.publish. - Smoke-test by opening @brandbot's Home tab in G&M Slack.
  3. Preview via scripts/post-redesign-previews.ts analog (or direct views.publish to Eric's user).
  4. Iterate on layout.
  5. Commit atomically, push, verify in Slack.
  6. Update docs/SLACK-UX.md with the Home tab spec + publish flow.

Open questions