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
beforeunloadwarning. - Invariant #12: "Slowness Is Baked In" -- The confirmation gate ("Ready to Share") adds intentional friction before publishing.
User Experience
User Flow
- Draft restoration: If a previous auto-saved draft exists, a prompt offers to resume or start fresh.
- Intent selection: "What kind of post is this?" with six intent pills (same as quick composer).
- Editor type selection: "How do you want to create?" with four options. Draft indicators show which editors have saved drafts.
- Style customization: Collapsible panel with tabs for Surface, Text, and Effects. Saved per-intent styles load automatically. Style presets can be saved and applied.
- Audience selection: "Who can see this?" with public, friends, or circles options.
- Sharing permission: Toggle to allow or disallow resharing.
- Content note: Optional content warning that collapses the post content behind a note.
- Content creation: The selected editor renders in the main content area.
- Media attachment: Images (up to 10) and voice notes can be added.
- Draft management: Auto-save indicator, explicit "Save Draft" button, and draft panel for managing multiple drafts with mix-and-match loading.
- Preview: Preview button opens a modal showing how the post will appear.
- Publish: "Ready to Share" opens a confirmation gate for final review before submitting.
Editor Types
| Editor | Description | Validation |
|---|---|---|
| Simple Text | Plain text with character limit (5000) | Must have content, images, or voice |
| Longform Article | Rich text editor with title field | Title required; minimum 500 characters |
| Drawing | Canvas-based drawing tool | Must have created a drawing |
| Magnetic Poetry | Draggable word tiles | Must 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
| File | Purpose |
|---|---|
src/components/AdvancedComposer.jsx | Main composer component (2037 lines). Handles all editor types, style management, drafts, preview, and submission |
src/components/composer/editors/SimpleTextEditor.jsx | Simple text editor with style application |
src/components/composer/editors/LongformEditor.jsx | Rich text editor with title and HTML content |
src/components/composer/editors/DrawingEditor.jsx | Canvas-based drawing editor |
src/components/composer/editors/MagneticPoetryEditor.jsx | Word tile arrangement editor |
src/components/composer/DraftPanel.jsx | Draft management panel with load, delete, pin, rename, and duplicate |
src/components/composer/PostConfirmationGate.jsx | Pre-publish confirmation dialog |
src/components/composer/SharingToggle.jsx | Toggle for sharing permission |
src/components/composer/ContentNoteInput.jsx | Content warning input |
src/hooks/useAutoSave.js | Auto-save draft functionality |
src/hooks/useDrafts.js | Multi-draft management with auto-save, pinning, renaming |
src/hooks/usePostPresets.js | Style preset management |
Draft System
The Advanced Composer uses two draft systems:
-
Auto-save drafts (
useAutoSave): Automatically saves the current compose state on content changes. Offers restore/dismiss on return. -
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
handleReadyToShare()validates all inputs and opens the confirmation gate.- The
PostConfirmationGatecomponent shows a final review of the post. - 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_circlesrecords (if circle audience) - Create
post_imagesrecords - 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
| Table | Purpose |
|---|---|
posts | Created post with all fields including editor_type, title, structured_content, post_style, content_note |
composer_drafts | Per-user, per-editor drafts with content, intent, post_style, is_auto_save flag |
user_intent_styles | Saved style preferences per intent per user |
style_presets | Named style presets with source_intent, use_count, last_used_at |
Edge Cases
| Scenario | Behavior |
|---|---|
| Browser closed with unsaved content | beforeunload event shows browser-native "unsaved changes" warning |
| Switching editor types | Current editor content saved to database as draft; new editor's draft loaded if it exists |
| Drawing draft save | Canvas data uploaded to storage to avoid large base64 in database records |
| Longform article under 500 characters | Validation error prevents publishing; character count shown |
| Rate limit exceeded on post create | Error displayed; confirmation gate closed so user can see the error |
| External clip attached | ExternalContentCard displayed in composer; external_clip_id stored on post; clip marked as posted via RPC |
| Image upload fails after 3 attempts | Error thrown with descriptive message |
Related
- 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