Skip to main content

Post

Location: src/components/Post.jsx

Overview

Post is the primary content display component for CommonPlace. It renders a single post card with intent-based visual styling, author information, content (text, images, drawings, magnetic poetry, voice, external clips), and interaction actions (save, share, respond, report). When a post is a share (is_share === true), it renders a SharedPostCard for the referenced content.

Intent styling applies CSS custom properties and classes derived from the author per-intent style preferences (surface, frame, font, emphasis, effects), giving each post a unique visual identity controlled by its creator rather than by algorithmic ranking.

Relevant Invariants

  • Invariant #4: "Intent Precedes Interpretation" -- Posts display their intent badge and styling, never ranked or scored.
  • Invariant #6: "No Public Comparative Metrics" -- No like counts, view counts, or ranking indicators.
  • Invariant #10: "Expressive Freedom Is Spatially Contained" -- Style customization is authored by the poster, contained to the post card.

Props

PropTypeRequiredDefaultDescription
postobjectYes--Post data including id, content, intent, user_id, profiles, post_images, etc.
sessionobjectYes--Supabase auth session
onUpdatefunctionNo--Callback after post update (edit/delete)
isSavedbooleanNofalseInitial saved state
onToggleSavefunctionNo--Callback when save state changes
savedDataobjectNo--Existing saved_posts record (note, shelf)
userShelvesarrayNo--User shelf list for save popover
onShelvesChangefunctionNo--Callback when shelves are modified
authorIntentStylesobjectNo--Intent-to-style map for this post's author (pre-scoped by Feed via authorIntentStyles[post.user_id])
hideSaveButtonbooleanNofalseHides the save action (used on SavedPage)
onShareToCirclefunctionNo--Callback to open share-to-circle modal
onUnsavefunctionNo--Callback for unsaving a post (passed through to PostActions; used on SavedPage)

Token-Based Custom Styling

Posts created with the Advanced Composer's PostCustomizer store style_tokens inside the post_style JSONB column. When present, Post renders with token-derived visual styles:

  • Extraction: usePostStyleFor(post) extracts tokens from post.post_style.style_tokens
  • Computation: useStyleFor(tokens) computes colors, clip-paths, shadow, font family, etc.
  • Clip-path border wrapper: When the post uses non-rounded corners (hexagon, diamond, etc.), the <article> is wrapped in an outer <div> that provides the border color and clip-path, with the inner article using the surface color — creating clipped borders with optional glow via drop-shadow
  • Corner accents: Decorative corner lines when cornerAccent is enabled and the post doesn't use clip-path corners
  • Intent badge: The token's primary color overrides the default intent accent for the badge border
  • Fallback: Posts without style_tokens render exactly as before using the CSS-class-based intent system

Key Behaviors

  • Intent Styling: Resolves DEFAULT_INTENT_STYLE merged with authorIntentStyles[post.intent] to compute surface, frame, font, emphasis, and effects CSS classes. The parent (Feed/SavedPage) passes the already-scoped per-author map, so Post accesses by intent key directly.
  • Editor Types: Renders different content views based on post.editor_type: simple (default text), longform (rich HTML), drawing (canvas image), magnetic_poetry (tile display).
  • Save Popover: Portal-based popover for shelf selection, note adding, and inline shelf creation.
  • Lightbox: Full-screen image viewing for post images.
  • Share Posts: When post.is_share is true, renders a SharedPostCard referencing the original.
  • Build-On: Supports build-on replies via useBuildOn hook.
  • Content Notes: Renders ContentNoteDisplay if the post has a content_note.
  • Voice: Renders VoicePlayer if post.voice_url is present.

Sub-components

ComponentLocationPurpose
PostHeadersrc/components/post-parts/PostHeader.jsxAuthor name, timestamp, intent label
PostContentsrc/components/post-parts/PostContent.jsxText/HTML content display
PostImagessrc/components/post-parts/PostImages.jsxImage grid with lightbox trigger
PostActionssrc/components/post-parts/PostActions.jsxRespond, save, share, report buttons
IntentBadgesrc/components/post-parts/IntentBadge.jsxCorner avatar + intent emoji badge
SavePopoversrc/components/post-parts/SavePopover.jsxSave-to-shelf popover
Lightboxsrc/components/post-parts/Lightbox.jsxFull-screen image viewer

Usage

import Post from '@/components/Post';

<Post
post={postData}
session={session}
onUpdate={refreshFeed}
authorIntentStyles={stylesMap}
/>
  • Feed -- Parent component that renders Post lists
  • IntentBadge -- Avatar + intent indicator
  • CreatePost -- Post creation
  • AdvancedComposer -- Full editor for styled posts
  • usePostStyle -- Token extraction via usePostStyleFor()
  • StyleContext (src/contexts/StyleContext.jsx) -- useStyleFor() for computing derived values

Last updated: 2026-02-08