Intent System
Overview
The Intent System is a foundational feature of CommonPlace that requires every post to carry an explicit intent signal before it can be published. Rather than leaving readers to guess the author's tone or purpose, the intent system provides upfront context about how a post should be received.
There are exactly six intent types, each with a distinct emoji, label, description, and color scheme. The intent is selected before any content is written, making it the first decision a user makes when composing. This "intent-first" design prevents the platform from becoming an undifferentiated stream of content and helps readers calibrate their responses appropriately.
The intent system also supports per-intent visual customization. Each user can configure different fonts, surfaces, frames, and even avatars for each intent type, giving their posts a consistent visual identity tied to the kind of sharing they are doing.
Relevant Invariants
- Invariant #4: "Intent Precedes Interpretation" -- Every post carries an intent signal chosen by the author before writing, ensuring readers have context before reacting.
- Invariant #6: "No Public Comparative Metrics" -- Intents are informational labels, never ranked, scored, or compared against each other.
- Invariant #17: "AI Doesn't Compete with Humans" -- The intent system is entirely user-driven; no AI suggests or auto-assigns intents.
User Experience
User Flow
- When the user opens the composer (either quick or advanced), the first thing they see is the intent selection prompt: "How should this be received?"
- The user selects one of six intent pills, each displayed with its emoji and label.
- On selection, the compose area transforms to reflect the selected intent's color scheme and any saved per-intent style (font, surface, effects).
- The user writes their content within the styled frame.
- The intent badge appears on the published post as a small indicator overlapping the author's avatar in the corner of the post card.
- Readers see the intent emoji and can hover/tap for the full label, immediately understanding the author's purpose.
The Six Intents
| Intent Key | Emoji | Label | Description |
|---|---|---|---|
thinking_out_loud | 💭 | Thinking Aloud | Processing thoughts out loud. Not necessarily looking for solutions. |
open_to_discussion | 💬 | Invite to Discuss | The author welcomes different perspectives on this. |
sharing_personal | :white_heart: | Personal Share | Something personal. Handle with care. |
asking_for_help | :hand_raised: | Asking for Help | Looking for advice, support, or practical help. |
just_for_fun | 😀 | Just for Fun | Lighthearted -- just sharing for the joy of it. |
sharing_information | 📌 | Offering Resource | Sharing something useful -- an article, tool, idea, or recommendation. |
Technical Implementation
Key Files
| File | Purpose |
|---|---|
src/lib/constants/intents.js | Canonical single source of truth for all 6 intent definitions, CSS mappings, and lookup helpers |
src/components/post-parts/IntentBadge.jsx | Renders the corner avatar + intent indicator overlay on post cards |
src/hooks/useIntentStyles.js | Fetches per-user intent styles (font, frame, surface, effects, avatar) for viewing and editing |
src/components/CreatePost.jsx | Quick composer with intent-first selection phase |
src/components/AdvancedComposer.jsx | Full editor with intent selection, per-intent style loading, and style presets |
Data Model
The INTENT_OPTIONS array defines each intent with id, emoji, label, and description. The INTENT_CSS_MAP maps each intent key to a shorter CSS key used for CSS custom property names (e.g., thinking_out_loud maps to thinking).
CSS custom properties follow the pattern --intent-{cssKey}-{property}, for example:
--intent-thinking-accent--intent-discussion-bg-tint--intent-personal-border
Database Tables
| Table | Purpose |
|---|---|
intent_styles | Stores per-user, per-intent visual customizations (font, frame, surface, effects, avatar_url, photo_url, background_image_url) |
user_intent_styles | Stores style preferences saved from the Advanced Composer (surface, texture, font, emphasis) |
style_presets | Named style presets that users can save and reuse across intents |
Hooks API
useIntentStyles(userId) -- Returns { styles, loading } where styles is a map of intent key to style object for viewing another user's posts.
useMyIntentStyles() -- Returns { styles, loading, updateStyle, updatePhoto, user } for the current user to read and modify their own intent styles. Uses upsert on intent_styles with conflict resolution on (user_id, intent).
Lookup Helpers
getIntentById(id)-- Returns the full intent object for a given keygetIntentEmoji(id)-- Returns the emoji for a given intent keygetIntentLabel(id)-- Returns the display labelgetIntentCssKey(id)-- Returns the shortened CSS key
Edge Cases
| Scenario | Behavior |
|---|---|
| No intent selected | Post button is disabled; user cannot publish without choosing an intent |
| User changes intent mid-compose | Compose frame re-styles to match the new intent; content is preserved |
| Author has no saved style for an intent | Default style is used: system font, flat frame, light surface, no effects, normal emphasis |
| Intent badge on shared posts | The original post's intent is displayed, not the sharer's |
| Viewing posts from users with custom styles | The author's intent_styles are fetched and applied per-post in the feed |
Related
- Posts -- Post creation uses the intent system as its first step
- Advanced Composer -- Full editor with per-intent style customization
- Feed -- Feed renders posts with per-author intent styles
Last updated: 2026-02-07