Skip to main content

Advanced Composer

Overview

The Advanced Composer is the full-featured post creation experience in CommonPlace, accessible at /compose or by clicking "Open full editor" from the quick composer. It extends the quick composer's intent-first design with four different editor types, deep visual customization, auto-saving drafts, a mix-and-match draft panel, post preview, and a confirmation gate before publishing.

The composer supports four editor types: Simple Text for quick posts, Longform Article for rich-text pieces with a title (minimum 500 characters), Drawing for visual creation on a canvas, and Magnetic Poetry for arranging word tiles. Each editor type maintains its own draft independently, and users can switch between editors without losing work.

Visual customization goes beyond the quick composer with a full style panel offering surface tones (light, dark, warm, cool), textures (flat, paper, soft-card, ghost), font selection, and emphasis levels (subtle, normal, strong). Styles are automatically saved per-intent so they persist across sessions, and users can save named style presets for quick reuse.

Relevant Invariants

  • Invariant #4: "Intent Precedes Interpretation" -- Intent selection is prominent and required before content can be submitted.
  • Invariant #14: "Privacy Is Infrastructure" -- Auto-save drafts are per-user and stored securely. Unsaved content triggers a browser beforeunload warning.
  • Invariant #12: "Slowness Is Baked In" -- The confirmation gate ("Ready to Share") adds intentional friction before publishing.

User Experience

User Flow

  1. Draft restoration: If a previous auto-saved draft exists, a prompt offers to resume or start fresh.
  2. Intent selection: "What kind of post is this?" with six intent pills (same as quick composer).
  3. Editor type selection: "How do you want to create?" with four options. Draft indicators show which editors have saved drafts.
  4. Style customization: Collapsible panel with tabs for Surface, Text, and Effects. Saved per-intent styles load automatically. Style presets can be saved and applied.
  5. Audience selection: "Who can see this?" with public, friends, or circles options.
  6. Sharing permission: Toggle to allow or disallow resharing.
  7. Content note: Optional content warning that collapses the post content behind a note.
  8. Content creation: The selected editor renders in the main content area.
  9. Media attachment: Images (up to 10) and voice notes can be added.
  10. Draft management: Auto-save indicator, explicit "Save Draft" button, and draft panel for managing multiple drafts with mix-and-match loading.
  11. Preview: Preview button opens a modal showing how the post will appear.
  12. Publish: "Ready to Share" opens a confirmation gate for final review before submitting.

Editor Types

EditorDescriptionValidation
Simple TextPlain text with character limit (5000)Must have content, images, or voice
Longform ArticleRich text editor with title fieldTitle required; minimum 500 characters
DrawingCanvas-based drawing toolMust have created a drawing
Magnetic PoetryDraggable word tilesMust have arranged at least one word

Style Options

Surface Tones: Light, Dark, Warm, Cool

Textures: Flat (clean/minimal), Paper (subtle texture), Soft Card (gentle shadows), Ghost (translucent blur)

Emphasis: Subtle (light/gentle), Normal (balanced), Strong (bold/prominent)

Fonts: System default plus additional font options defined in FONT_OPTIONS

Technical Implementation

Key Files

FilePurpose
src/components/AdvancedComposer.jsxMain composer component (2037 lines). Handles all editor types, style management, drafts, preview, and submission
src/components/composer/editors/SimpleTextEditor.jsxSimple text editor with style application
src/components/composer/editors/LongformEditor.jsxRich text editor with title and HTML content
src/components/composer/editors/DrawingEditor.jsxCanvas-based drawing editor
src/components/composer/editors/MagneticPoetryEditor.jsxWord tile arrangement editor
src/components/composer/DraftPanel.jsxDraft management panel with load, delete, pin, rename, and duplicate
src/components/composer/PostConfirmationGate.jsxPre-publish confirmation dialog
src/components/composer/SharingToggle.jsxToggle for sharing permission
src/components/composer/ContentNoteInput.jsxContent warning input
src/hooks/useAutoSave.jsAuto-save draft functionality
src/hooks/useDrafts.jsMulti-draft management with auto-save, pinning, renaming
src/hooks/usePostPresets.jsStyle preset management

Draft System

The Advanced Composer uses two draft systems:

  1. Auto-save drafts (useAutoSave): Automatically saves the current compose state on content changes. Offers restore/dismiss on return.

  2. Draft panel (useDrafts): A more sophisticated system supporting multiple named drafts per editor type. Features:

    • Load content only: Import text from a draft while keeping the current intent (mix-and-match).
    • Load full: Import content, intent, and style from a draft.
    • Auto-save: Background saving with unsaved changes indicator.
    • Pin/Rename/Duplicate/Delete: Full draft management.

The useAutoSave hook stores auto-save data in IndexedDB (commonplace_drafts database) for fast client-side persistence. The useDrafts hook stores named drafts in the composer_drafts Supabase table with (user_id, editor_type) as the conflict key.

Drawing Draft Optimization

Drawing drafts present a special challenge because canvas data as base64 can be very large. The composer uploads drawing drafts to Supabase storage (draft-drawings bucket, with post-images as fallback) and stores only the URL in the draft record. A simple hash check (first 100 chars + length) prevents redundant re-uploads of unchanged drawings.

Style Persistence

When a user posts with a specific intent and style, the style is saved to user_intent_styles with upsert on (user_id, intent). When the same intent is selected in future sessions, the saved style loads automatically. Users can also save named presets to style_presets with usage tracking (use_count, last_used_at).

Submission Flow

  1. handleReadyToShare() validates all inputs and opens the confirmation gate.
  2. The PostConfirmationGate component shows a final review of the post.
  3. On confirm, handleSubmit() executes:
    • Upload images (with retry, 3 attempts per image)
    • Upload voice note (if present)
    • Upload drawing to storage (if drawing editor)
    • Create post record with all metadata
    • Create post_circles records (if circle audience)
    • Create post_images records
    • Mark external clip as posted (if from browser extension)
    • Save intent style
    • Clear all drafts
    • Navigate based on audience (circle page, circles list, or feed)

Database Tables

TablePurpose
postsCreated post with all fields including editor_type, title, structured_content, post_style, content_note
composer_draftsPer-user, per-editor drafts with content, intent, post_style, is_auto_save flag
user_intent_stylesSaved style preferences per intent per user
style_presetsNamed style presets with source_intent, use_count, last_used_at

Edge Cases

ScenarioBehavior
Browser closed with unsaved contentbeforeunload event shows browser-native "unsaved changes" warning
Switching editor typesCurrent editor content saved to database as draft; new editor's draft loaded if it exists
Drawing draft saveCanvas data uploaded to storage to avoid large base64 in database records
Longform article under 500 charactersValidation error prevents publishing; character count shown
Rate limit exceeded on post createError displayed; confirmation gate closed so user can see the error
External clip attachedExternalContentCard displayed in composer; external_clip_id stored on post; clip marked as posted via RPC
Image upload fails after 3 attemptsError thrown with descriptive message
  • Posts -- Posts created by the Advanced Composer
  • Intent System -- Intent selection and per-intent styles
  • Voice Narration -- Voice recording integration
  • Feed -- Published posts appear in the feed

Last updated: 2026-02-07