Consolidates token verification into server/auth.ts, removing the
external SDK dependency. All modules now import from the local module.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add guided tours to 6 modules that were missing them:
- Shadow DOM: rsocials dashboard, crowdsurf, rdata (TourEngine)
- Light DOM: rsplat, rbnb, rvnb (new LightTourEngine class)
Add solo mode toggle to collab overlay — click the presence badge
to hide your cursor/presence from others. Persists via localStorage,
dispatches event to canvas PresenceManager.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Newsletter campaigns now require N-of-M team member approval via rInbox
before Listmonk starts sending. The send-newsletter workflow node creates
a draft campaign and gates it through the team inbox; a manual submit-
approval route is also available. The multisig email UI shows a green
"Newsletter Approval" badge with campaign ID for newsletter approvals.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prominent teal gradient button in header and empty state of the
campaigns tab, linking to the AI-guided wizard.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Progressive approval workflow: paste brief → AI extracts structure →
AI generates per-platform posts → review with per-post regen →
commit (saves campaign, creates threads, drafts newsletters, builds workflow DAG).
Includes MI integration for Cmd+K campaign creation and vite build entry.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace manual thread ID entry with select dropdowns in both campaign planner
and workflow components. Server-side publish-thread handler now resolves
linked threadId from Automerge doc when inline content is empty.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Buttons, badges, focus states, avatars, links, inputs, and surfaces across
all rSocials components now use --rs-primary, --rs-error, --rs-success,
--rs-accent, --rs-bg-surface, --rs-input-bg, etc. with dark-mode fallbacks.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Full campaign editor with HTML body textarea, live iframe preview,
list selector with subscriber counts, save draft, send now, and
schedule send. Added edit/delete actions on draft campaigns and
GET/PUT/DELETE single-campaign proxy routes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rename "Threads" to "Posts & Threads" in hub nav, route title, and subPageInfos.
Thread gallery now shows draft/scheduled posts from campaigns alongside threads.
Add Postiz API client (postiz-client.ts) with settings schema for URL + API key.
Proxy routes: /api/postiz/status, integrations, posts, threads.
Wire workflow executor to call real Postiz API for post/thread/cross-post nodes.
Add "Send to Postiz" button in thread builder (editor + readonly views).
Add approval queue: PendingApproval schema (v5), GET/POST /api/approvals routes,
wait-approval workflow node creates pending approvals and pauses execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Declarative onboardingActions on RSpaceModule lets each rApp define its
own onboarding cards (import, upload, link, create). renderOnboarding()
renders them as a responsive card grid with upload handling. Adds ICS
import endpoint to rCal (POST /api/import-ics). 15 modules wired up.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The thread gallery already has a "New Thread" button linking to the editor,
so a separate hub button and subnav pill for the editor is redundant.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New gallery landing page at /campaigns showing all campaign workflows as
cards with miniature SVG previews. Click a card to open the editor at
?workflow=<id>. Editor gains back-link to dashboard and workflow attribute
for deep-linking.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add types/hono.d.ts declaring effectiveSpace, spaceRole, and isOwner
on Hono's ContextVariableMap. Remove 127 "as any" casts across 18
files. Fix ParticipantStatus type in rmaps SyncMessage union.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add threadId config field to publish-thread nodes
- Add "Create Thread" / "Edit Thread" button in config panel
- Opens thread editor in new tab (new or edit by ID)
- Styled button matching indigo accent theme
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix height to account for shell header (92px not 60px)
- Add min-height:0 on flex children to prevent overflow
- Replace text zoom buttons with SVG icons matching rFlows pattern
- Add fit-to-view icon (corner brackets) with separators
- Add category class per node (trigger/delay/condition/action)
with tinted backgrounds and category badge chips
- Add keyboard shortcuts: F=fit, +/-=zoom
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
SVG text labels were rendering alongside HTML span labels, causing
each input/output name to appear twice on drag & drop nodes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add shared ViewHistory<V> utility class that provides a proper navigation
stack for rApps with hierarchical views. Replaces hardcoded data-back
targets with stack-based back navigation across 10 rApps: rtrips, rmaps,
rtasks, rforum, rphotos, rvote, rnotes, rinbox, rschedule, rcart.
Rename rWork module to rTasks — directory, component (folk-tasks-board),
CSS, exports, domains, and all cross-module references updated.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add <rstack-module-setup> component for inline module configuration
(replaces static "Not Configured" instructions). Enhance settings
gear panel to show the current module's settingsSchema at the top.
Pass module-id through shell rendering and tab-cache switching.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add Listmonk newsletter management proxy API with role-based auth,
newsletter manager component, password setting type support, and
new backlog task files. Update newsletter subscribe URL.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add three alternative views to the campaign planner canvas:
- Timeline: horizontal chronological layout with day columns and phase bars
- Platform: kanban columns grouped by platform with post cards
- Table: compact sortable table with status, platform, content, dates
View switcher in toolbar preserves canvas state when switching. Clicking
any post in alt views navigates back to canvas with that node selected
and centered. Keyboard shortcuts guarded to canvas-only view.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Previously the planner restored a stale zoomed-out viewport from
localStorage, and fitView() could fail silently if the SVG had zero
dimensions during shadow DOM layout. Now: skip viewport restore on
initial load, retry fitView up to 3 rAFs, and clamp min zoom to 50%.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The /campaigns route was serving folk-campaign-manager (simple list view)
instead of folk-campaign-planner (the drag-and-drop flow canvas). The
planner was fully built but had no route.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
rsocials had defaultScope: "global" but client components passed the raw
space slug, creating threads in space-specific docs (e.g. commonshub).
Server routes then looked in the non-existent "global" doc → 404.
Changed to defaultScope: "space" to match how client actually works.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Links on subdomain routing (e.g. jeff.rspace.online) were including
the space in the path (/demo/rsocials/campaigns) instead of just
/rsocials/campaigns. Added basePath getter to all components and
detect subdomain in the server-rendered hub page.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add pointer-based gesture handling to the calendar for lateral navigation
(drag/swipe left/right) and pinch-to-zoom between temporal layers. Also
fix dark mode across 30+ canvas shape components by replacing hardcoded
white backgrounds and input styles with --rs-* CSS custom property
references (with light-mode fallbacks).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Subdomain routing (demo.rspace.online) already prepends the space,
so links should use /rsocials/... not /demo/rsocials/...
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Restructure rSocials landing to a hub with navigation cards for Campaigns,
Threads, and Thread Editor. Rename /thread routes to /thread-editor for
clarity. Render campaigns listing inline instead of redirecting. Also
improve rNotes notebook creation to auto-open first note for editing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Phase 1 — Fix scope system: new scope-resolver.ts resolves global vs
space-scoped docId prefixes. Server middleware sets effectiveSpace on
Hono context. All 18 modules updated to use dataSpace for Automerge
doc access while keeping space for display. Client runtime gets
setModuleScopes() and resolveDocSpace() for local-first scope
resolution.
Phase 2 — Seamless cross-space navigation: TabCache now tracks panes
per space:module key. OfflineRuntime maintains lazy WebSocket
connections per space. Space-switcher dispatches space-switch event
handled client-side with history.pushState instead of full reload.
Phase 3 — Spaces as layers: Layer type extended with spaceSlug and
spaceRole. Tab bar gains "Add Space Layer" picker. Canvas renders
cross-space shapes with visual indicators. Space layers persisted as
SpaceRefs via nesting API. Runtime provides getAllActiveSpaces() and
subscribeModuleAcrossSpaces() for module-level data aggregation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
onChange handler was resetting _tweetImages on every sync event,
undoing local deletions before they could round-trip. Now only
updates state in readonly mode; edit mode preserves local changes.
Also add cache-busting timestamps to uploaded/generated image URLs
to prevent browser from showing stale cached images.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Automerge proxy objects silently ignore property writes outside
change() calls. When this._thread was a proxy, removeTweetImage's
assignment to this._thread.tweetImages was silently discarded,
causing deleted photos to reappear.
Fix by deep-cloning all Automerge reads (subscribeOffline, onChange,
loadDraft) so this._thread is always a plain mutable object.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove the title input and header image upload/generate section from
the thread builder editor. Title is now auto-derived from first tweet.
Add link preview cards that render inline in tweet content, similar to
Twitter's URL card unfurling. Server-side /api/link-preview endpoint
fetches OG metadata (title, description, image) with caching.
URLs in tweet text are rendered as clickable links.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace infographic/typography prompts with atmospheric abstract art
prompts. Images now use flowing gradients, organic shapes, and moody
lighting to evoke the tweet's theme without any text or typography.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace generic "dark themed, minimal" prompts with detailed
infographic-style prompts that generate bold, shareable visuals
with typography overlays, iconic symbols, and data-viz elements.
Add try/catch error handling around fal.ai calls to prevent
unhandled network errors from crashing the request handler.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pass /data/ paths through subdomain routing without rewriting so
generated image files are accessible on *.rspace.online subdomains.
Move image upload/generate section above the compose textarea in the
thread builder editor layout.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Automerge throws "Cannot create a reference to an existing document
object" when assigning an Automerge proxy object back into the doc.
Now JSON round-trips the thread data before writing, and strips null
fields that should be absent rather than null in the document.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- tweetImages and imageUrl set to null instead of undefined when empty
(Automerge rejects undefined as invalid JSON)
- Updated ThreadData schema to allow null for optional fields
- This was the root cause of the 404 on image generation: saveDraft
threw on undefined, so the thread never synced to the server, and
the server-side route returned "Thread not found"
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two bugs:
- subscribeOffline() bailed if runtime wasn't initialized yet (race with
shell.ts init). Now waits for runtime to appear, then awaits init().
- getDoc() called runtime.getDoc() which doesn't exist — method is
runtime.get(). Caused "e.getDoc is not a function" crash in listThreads.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All callers of saveDraft() and saveToAutomerge() in generateImage,
uploadImage, uploadTweetImage, generateTweetImage, removeTweetImage,
and share handler now properly await these async methods. Without await,
runtime.change() fires before the Automerge doc subscription resolves,
causing "Document not open" errors.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
basePath was always returning /{space}/rsocials/ which works for path-based
routing (rspace.online/jeff/rsocials/) but double-prefixes on subdomain
routing (jeff.rspace.online/jeff/rsocials/ → rewritten to /jeff/jeff/rsocials/).
Now detects subdomain hosts (*.rspace.online, *.rsocials.online) and returns
/rsocials/ without the space prefix, since the space is the subdomain.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two bugs fixed:
- attachShadow called unconditionally in connectedCallback, crashing on
re-insertion ("Shadow root cannot be created on a host which already
hosts a shadow tree")
- saveToAutomerge/deleteFromAutomerge called runtime.change() before the
async subscribeOffline() had resolved, causing "Document not open" errors
Now tracks the subscribe promise and awaits it before any write operation.
Also guards shadow root creation in gallery and campaign manager components.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The reverse proxy couldn't work for a Next.js SPA — it caused double
space prefix in redirects and couldn't handle /_next/* static assets.
Switch to iframe approach with demo.rsocials.online directly. Fix
template literal bugs where getSchedulerUrl() was passed as a string
literal instead of being evaluated.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The rSpace Traefik router catches demo.rsocials.online (priority 120)
before the Postiz container can serve it, making iframe embedding fail.
Replace the iframe approach with a reverse proxy: /rsocials/scheduler/*
proxies to the Postiz container (postiz:5000) on the Docker network.
Rewrites redirect headers to stay within the scheduler path.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>