Commit Graph

304 Commits

Author SHA1 Message Date
Jeff Emmett 7850b9d34c feat: move rApp secrets to Infisical, add seed script
Remove DATABASE_URL and ADMIN_DIDS from docker-compose.yml (now
injected via Infisical entrypoint). Add scripts/seed-infisical.sh
to interactively populate 21 module-specific secrets (R2, Immich,
Twenty, Discourse, FAL, RunPod, etc.) into the rspace Infisical
project. Update Dockerfile to include scripts/ in the image.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 18:06:21 -08:00
Jeff Emmett 5e0f30567a fix: prevent pointer events from hijacking two-finger touch pan
On touch devices, both pointer and touch events fire. When a second
finger was added, the pointer handler re-captured the interaction,
fighting the touch-based pan/pinch. Now the touch handler releases
pointer captures and sets a flag that blocks the pointer handler
during two-finger gestures. Also cancels shape drag on multi-touch
and closes the context menu on touchstart for reliable mobile dismiss.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 18:02:53 -08:00
Jeff Emmett 658eb966d6 fix: push overlapping siblings instead of displacing the dragged shape
The overlap resolver now moves siblings in the drag direction rather
than snapping the dragged shape away from them. Supports chain-pushing
(A pushes B into C) with a recursion depth of 3.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:51:34 -08:00
Jeff Emmett 7db6068229 feat: add forgotten-shape tooltip and "Hide Faded" toggle
Hovering a forgotten shape now shows a tooltip explaining the state.
A new "Hide Faded" toolbar button lets users hide all forgotten shapes
entirely, with the preference persisted in localStorage. Hidden shapes
reappear automatically when another user remembers them.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 15:05:20 -08:00
Jeff Emmett 384ef23ae1 chore: add backlog tasks 74-76
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 15:04:39 -08:00
Jeff Emmett 3808b51a64 feat: strip demo pages to show just the interactive component
Demo pages now render the same clean shell as regular spaces — just the
<folk-*> component full-page, no marketing wrapper (hero, feature cards,
CTA). Descriptions belong on landing pages, not demos.

- Remove demo branch from 7 module route handlers (rcal, rcart, rfunds,
  rnotes, rtrips, rtube, rvote)
- Delete 7 demo.ts files (~1200 lines of dead markup)
- Remove renderDemoShell() and DEMO_PAGE_CSS from server/shell.ts
- Remove demoPage field from RSpaceModule interface
- Rename top rApp dropdown item from "rSpace" to "rStack"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 15:03:46 -08:00
Jeff Emmett 6bd23a6778 fix(rspace): serve canvas through renderShell like all other rapps
The rspace module was serving raw canvas.html as a standalone page
(bypassing renderShell) because canvas-module.html didn't exist.
This meant navigating to rspace caused a full page replacement with
no shared shell, tabs, or TabCache support — appearing to open in a
"new window."

Now extracts body content, styles, and scripts from canvas.html at
startup (stripping the duplicate shell chrome) and renders through
renderShell like every other module. This makes rspace fully
interoperable with the tab system and TabCache.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 14:55:36 -08:00
Jeff Emmett a39cf6e1c2 feat: auto-provision personal spaces on first visit + redirect logged-in users from demo
Server-side middleware creates the user's personal space when they visit
{username}.rspace.online for the first time (token in cookie, verified once).
Client-side redirect sends logged-in demo users to their personal space.
"Try Demo" button sets a sessionStorage flag to bypass the redirect.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 14:31:32 -08:00
Jeff Emmett 1a615c29c9 feat(rphotos): fix gallery API routing and embed Immich at /album
Fix getApiBase() regex to match /rphotos instead of /photos, add
/album route with iframe embed via renderExternalAppShell, and update
Immich links to navigate within rSpace instead of opening externally.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 14:31:19 -08:00
Jeff Emmett b66e9b44de feat: hide "Try Demo" header button when logged in
The header demo button is now hidden via data-hide when the user has
an active EncryptID session. Reacts to auth-change events so it
appears on logout and disappears on login without page reload.
Landing page hero CTAs already swap to "Go to My Space" when logged in.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 14:16:59 -08:00
Jeff Emmett f7ecf50588 feat: upgrade 6 module demos to use real interactive components
Replace static HTML mockups and WebSocket skeleton demos with the actual
self-contained web components (with built-in demo data) for rcart, rtube,
rfunds, rnotes, rtrips, and rvote — matching the rcal demo pattern.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 14:10:52 -08:00
Jeff Emmett ef1d93d7e9 feat(encryptid): persist login across subdomains via cross-domain cookie
EncryptID sessions were lost when navigating between rspace.online
subdomains (e.g. demo→cca) because localStorage is per-origin. Now
stores a domain-wide cookie (eid_token, domain=.rspace.online, 30 days)
alongside localStorage. On new subdomain visits, the cookie is synced
to localStorage at module load time. Expired tokens are auto-refreshed
via the server before being discarded. Sign-out clears both stores.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 14:10:36 -08:00
Jeff Emmett 5408eb0376 feat: add outputPaths to module interface and browsable list pages
Add OutputPath type to RSpaceModule so each module declares what content
types it produces (e.g. notebooks, routes, campaigns). Auto-generate
browsable list pages at /:space/:moduleId/:path that render a card grid
inside the standard shell, fetching items from the module's API.

Declares outputPaths across 23 modules (rwallet/rinbox skipped).

Move campaign demo from standalone campaign-demo space to
/rsocials/campaign route with a dedicated timeline view and
/api/campaigns endpoint.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 13:55:29 -08:00
Jeff Emmett 4979c3d80c feat(rcal): replace static demo with interactive folk-calendar-view
The demo page was a frozen July 2026 static HTML grid with no real
functionality. Now embeds <folk-calendar-view space="demo"> which
provides full month/week/day views, navigation, lunar overlay, source
filtering, event modals, keyboard shortcuts, and 37 demo events.
Keeps hero, temporal zoom showcase, feature cards, ecosystem
integrations, and CTA sections around the interactive component.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 11:49:13 -08:00
Jeff Emmett 317bc46de6 feat: three-state FUN — present, forgotten (faded), deleted
Shapes now have three states instead of two. "Forgetting" a shape fades
it (35% opacity, greyscale) for all connected clients rather than hiding
it. Other users can then choose to "forget too", "remember" (restore),
or "delete" (hard-remove from DOM). A forgottenBy map tracks who forgot,
enabling social signaling around shared attention.

- folk-shape.ts: :state(forgotten) CSS + forgotten property
- community-sync.ts: forgetShape(id,did), rememberShape, hardDeleteShape,
  getShapeVisualState, hasUserForgotten, getFadedShapes, getDeletedShapes
- community-store.ts: forgottenBy map server-side, rememberShape clears map
- canvas.html: right-click context menu, two-section memory panel (Fading/
  Deleted), close button fades instead of removes, Delete key escalates

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 11:44:02 -08:00
Jeff Emmett a61f562bbf feat: persistent tab bar, offline save improvements, and shape validation
- Tab bar state persists to localStorage per space
- Emergency synchronous localStorage fallback for beforeunload saves
- Merge Automerge full-sync instead of replacing (preserves local changes)
- Validate shape coordinates before applying (prevent NaN/Infinity)
- Save on visibilitychange for mobile browser tab backgrounding
- Add OutputPath type for module browsable content types
- Fix canvas module ID from "canvas" to "rspace" in tab-cache

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 11:11:14 -08:00
Jeff Emmett f69ee9f977 fix: shape resize sync and transform event name alignment
- Sync #attrWidth/#attrHeight during resize so CSS reflects new dimensions
- Call #dispatchTransformEvent() directly for immediate visual update
- Fix TransformEvent to fire "folk-transform" matching CommunitySync listeners
- Reduce min-width/min-height on folk-markdown and folk-wrapper to 80x40px

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 11:11:02 -08:00
Jeff Emmett c7674ac526 feat: color-coded visibility badges and contextual space display names
- Visibility badges now color-coded: green (public), yellow (permissioned),
  red (private) with matching card border tints
- Public spaces show eye icon instead of lock
- Private spaces display as "username's (you)rSpace" instead of raw name
- Applied consistently across space switcher dropdown and My Spaces modal

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 10:42:06 -08:00
Jeff Emmett aeb9247f96 fix: shape resize/rotate by converting screen coords to canvas space
Resize and rotation handlers in folk-shape.ts passed raw event.clientX/Y
(screen coordinates) to toLocalSpace/angleFromOrigin, but those methods
expect canvas-parent coordinates. With any zoom/pan, the two coordinate
systems diverge, making resize non-functional and rotation erratic.

Added #screenToParent() to convert viewport coords to the parent's
coordinate space using getBoundingClientRect + parent scale. Applied to:
- Resize handle drag (pointermove → toLocalSpace)
- Rotation start (pointerdown → angleFromOrigin)
- Rotation drag (pointermove → angleFromOrigin)

Also syncs ghost placeholder size with zoom changes so the dotted
preview stays accurate if user zooms while in placement mode.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 10:38:06 -08:00
Jeff Emmett 7616fe0757 feat: show resize handles on selected shapes + pan-first canvas navigation
Resize handles now appear when a shape is highlighted/focused, not just during
active drag. Canvas left-click+drag now pans by default; hold 250ms then drag
for marquee selection.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 10:13:22 -08:00
Jeff Emmett 2bbe50991d fix: exclude server paths from space-to-subdomain redirect
The bare-domain routing logic was redirecting all multi-segment paths
like /api/modules → api.rspace.online/modules. Add exclusion for
known server path prefixes (api, admin, admin-data, admin-action,
.well-known) so they fall through to Hono route handlers instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 23:11:49 -08:00
Jeff Emmett 85ac897a1a fix: use single-segment admin endpoints to bypass Cloudflare redirect
Cloudflare has a wildcard rule that redirects any multi-segment path
on rspace.online to a subdomain (e.g. /foo/bar → foo.rspace.online/bar).
This broke both /api/* and /admin/api/* paths.

Replace with single-segment endpoints:
- GET /admin-data — returns spaces + modules (admin-only)
- POST /admin-action — handles mutations like delete-space

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 22:58:37 -08:00
Jeff Emmett caae204c2b fix: bypass Cloudflare /api/* redirect for admin dashboard
Cloudflare has a redirect rule that rewrites rspace.online/api/* to
http://api.rspace.online/*, causing Mixed Content errors in the browser.
Add a separate /admin/api router that serves the same admin data at
paths that don't trigger the redirect rule.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 22:51:23 -08:00
Jeff Emmett 8d77c6eee8 fix: canvas tools place shapes exactly where the ghost placeholder shows
- newShape() with explicit position now places directly at click point
  instead of routing through findFreePosition spiral which could nudge
  the shape away from the cursor
- Sticky note converted to setPendingTool so it shows dotted placeholder
  before placement instead of instantly spawning at viewport center
- Feed tool converted to setPendingTool with __postCreate for the same
  click-to-place UX
- Removed wb-sticky from mobile keepOpen list since it's now a
  placement tool that should close the menu

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 22:42:33 -08:00
Jeff Emmett 47b585665d fix: rename rStack to rSpace in app switcher dropdown
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 22:35:21 -08:00
Jeff Emmett 2b58068a1a feat: persistent sessions with 30-day JWT and auto-refresh on page load
Sessions now last 30 days instead of 15 minutes. Both the rstack-identity
component and legacy header auto-refresh the token when < 7 days remain,
so users who visit at least once every ~23 days stay logged in indefinitely.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 22:33:31 -08:00
Jeff Emmett 783be14a11 fix: default canvas to dark mode and hide legacy community-info box
Canvas page was hardcoded to data-theme="light" while all other pages
default to dark. Also hides the redundant #community-info overlay
(slug/URL box) since the shell header space switcher already shows this.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 22:30:27 -08:00
Jeff Emmett b12cc52892 feat: admin dashboard with user management and delete capabilities
- Add tabbed admin UI (Spaces | Users) with auth gate
- Add admin API endpoints on EncryptID: list users, delete user, clean space members
- Add admin force-delete space endpoint on rSpace (bypasses owner check)
- Protect all admin endpoints with ADMIN_DIDS env var
- Add ADMIN_DIDS to both Docker Compose configs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 22:30:21 -08:00
Jeff Emmett 34877b1f9e feat: add "My Spaces" modal to identity dropdown
Adds a clickable "My Spaces" item in the profile dropdown that opens
a full-screen overlay showing all user spaces as clickable cards.
Fetches /api/spaces, splits into "Your Spaces" and "Public Spaces"
sections, with navigation via rspaceNavUrl and a "Create New Space" CTA.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 22:26:31 -08:00
Jeff Emmett d5563d4636 fix: pass auth token in WebSocket connections for private spaces
WebSocket clients were connecting without auth tokens, causing 401
rejections for authenticated/members_only spaces. Now reads the
encryptid_session from localStorage and appends ?token= to WS URLs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 22:08:07 -08:00
Jeff Emmett f8c51fad0b fix: move /notifications and /admin routes before /:slug wildcard
Hono matches routes in definition order, so /:slug was catching
"notifications" and "admin" as slug params and returning 404.
Static routes must be defined before parameterized routes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 21:54:27 -08:00
Jeff Emmett 1db8341fb2 feat: email forwarding via Mailcow aliases + private space access gate
Email forwarding (EncryptID):
- New mailcow.ts API client for alias CRUD via Mailcow REST API
- Schema: email_forward_enabled + email_forward_mailcow_id columns
- API endpoints: GET/POST email-forward status, enable, disable
- Profile email change hook updates/disables alias automatically
- Docker: rmail-mailcow network + MAILCOW_API_URL/KEY env vars

Private spaces:
- Access gate overlay blocks members_only spaces for unauthenticated users
- Space visibility injected into HTML via middleware
- Auto-provision creates spaces as members_only by default
- Personalized "Create {username}'s Space" CTA in space switcher
- Removed unused /notifications endpoint

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 21:54:07 -08:00
Jeff Emmett 75b148e772 Merge branch 'dev'
# Conflicts:
#	modules/rcal/mod.ts
#	modules/rfiles/mod.ts
#	modules/rforum/mod.ts
#	modules/rmaps/mod.ts
#	modules/rnetwork/mod.ts
#	modules/rswag/mod.ts
#	modules/rwork/mod.ts
#	shared/module.ts
2026-02-28 19:51:51 -08:00
Jeff Emmett 5613370817 refactor: rename module directories to match r-prefixed module IDs
All 22 module directories under modules/ now match their module IDs
(e.g. modules/cart → modules/rcart, modules/canvas → modules/rspace).
Updated all import paths, vite build config, HTML template asset refs,
docker-compose standalone commands, and .gitignore accordingly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 19:49:26 -08:00
Jeff Emmett 8895c0fb75 feat: always-visible tab close buttons + rApp dropdown shows open apps
- Tab close (×) buttons now visible at 35% opacity instead of hidden,
  brightening on hover so users can see they're clickable
- [+] dropdown now shows all rApps including already-open ones
- Already-open rApps shown dimmed with a cyan dot indicator
- Clicking an open rApp surfaces it (switches tab) instead of duplicating

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 17:10:08 -08:00
Jeff Emmett 29d49c7b26 feat: always-visible tab close buttons + rApp dropdown shows open apps
- Tab close (×) buttons now visible at 35% opacity instead of hidden,
  brightening on hover so users can see they're clickable
- [+] dropdown now shows all rApps including already-open ones
- Already-open rApps shown dimmed with a cyan dot indicator
- Clicking an open rApp surfaces it (switches tab) instead of duplicating

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 17:08:45 -08:00
Jeff Emmett 3ea787ed82 fix: add cache-busting version params to module script tags
Browsers were serving stale JS from cache. Added ?v=3 to all four
updated module component scripts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 00:52:18 +00:00
Jeff Emmett bb6643cf70 feat: port standalone app features to unified rSpace modules
rCal: keyboard navigation (←→ nav, 1/2/3 views, T today, L lunar) and
clickable source badges for event filtering.
rWork: inline create form with priority/description, inline title editing,
and priority badge cycling (replaces prompt() dialogs).
rNetwork: force-directed layout (80-iteration simulation), node detail
panel with trust scores, and purple trust badges on person nodes.
rMaps: provider search with dimming, enhanced detail with OSM directions
link, and browser geolocation pin display.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 00:05:34 +00:00
Jeff Emmett abbfb552cc feat: client-side tab caching for instant tab switching
Previously loaded tabs stay in the DOM and are shown/hidden via CSS.
New tabs are fetched via fetch() + DOMParser on first visit, then
cached. Switching back is instant with no network request.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 23:21:10 +00:00
Jeff Emmett d9bd7557fa fix: dropdown menus use fixed positioning to escape overflow clipping
Dropdown menus in app-switcher and space-switcher were clipped by
overflow:hidden on .rstack-header__left (mobile). Changed from
position:absolute to position:fixed with dynamic getBoundingClientRect
positioning. Bumped shell asset versions to v=5 to bypass CF cache.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 21:36:18 +00:00
Jeff Emmett 08928a9f8e fix: app-switcher dropdown navigates within demo on subdomains
On demo.rspace.online, the dropdown was linking to landing pages
(rspace.online/moduleId) instead of navigating between demo pages.
Changed condition to only use landing-page links on the bare domain.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 21:06:52 +00:00
Jeff Emmett 58af5a304c feat: enhance rcal, rtrips, and rmaps demos to match standalone quality
rCal: add Day/Week/Month view switcher with 24-hour timeline, 48 demo
events across 3 months, now indicator, and per-view navigation.

rTrips: add 4 demo trips with varied statuses (Planning/Booked/In
Progress/Completed), destination chains, collaborator avatars, emoji
categories, and grouped itinerary by date.

rMaps: add interactive zoom/pan (mouse wheel + drag + touch), provider
detail panel with descriptions and specialty tags, click-to-zoom on
pins and legend items, and zoom controls.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 20:04:50 +00:00
Jeff Emmett bf1d126ee5 fix: prevent double space prefix in dashboard links on subdomains
Dashboard card hrefs were /{space}/{moduleId}, causing double-prefix
(/demo/demo/rbooks) when accessed via demo.rspace.online subdomain
routing. Now renders /{moduleId} and resolves via __rspaceNavUrl on
the client for cross-context compatibility.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 09:04:47 +00:00
Jeff Emmett db078d3152 feat: embed external apps via iframe in rSpace shell
Add ?view=app iframe integration for 4 existing modules (rNetwork→Twenty CRM,
rSocials→Postiz, rForum→Discourse, rFiles→Seafile) and 2 new modules
(rDocs→Docmost, rDesign→Affine). Each module shows its demo view by default
with an "Open Full App" button to switch to the iframe-embedded external app.

Also includes: splat demo data seeding, MI search bar mobile layout fix.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 08:56:08 +00:00
Jeff Emmett e55e56bc06 feat: move search bar to second row on mobile header
On screens <= 640px, the header wraps to two rows: logo/app-switcher
and identity on top, "Ask Mi Anything" search bar full-width below.
Header and tab row switch from fixed to sticky positioning on mobile,
eliminating the need for magic padding-top values on #app.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 07:17:38 +00:00
Jeff Emmett 9db9c89bed fix: dark background on all demo pages + calendar mobile improvements
Shell CSS: add body background (#0f172a) so all module pages have the
dark theme instead of transparent/white on mobile. Add mobile media
queries for #app padding and nav wrapping.

Calendar: add day-detail panel that opens on tap (crucial for mobile
where event labels are hidden). Improve touch targets, add source
badges in event modal, shorter weekday headers for narrow screens.

Cache-bust shell.css, cal JS, and swag JS via ?v=2 query params to
bypass Cloudflare edge cache.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 07:10:40 +00:00
Jeff Emmett e40db06407 fix: show mockup section from start in rSwag demo
Step 2 (design mockup + "Use Sample Design" button) was gated behind
demoStep >= 2, but the only way to reach step 2 was clicking a button
inside the hidden section. Now mockup is always visible alongside
product selection.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 06:55:16 +00:00
Jeff Emmett 01fa8b1ba5 feat: enhance demo modes across 12 modules + add inbox/sharp/x402 deps
Improve interactive demos for notes, maps, network, vote, calendar,
choices, trips, work, books, wallet, and inbox modules with richer
mock data and better mobile responsiveness. Update server routing
and landing page. Add sharp, imapflow, mailparser, and x402 dependencies.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 06:48:51 +00:00
Jeff Emmett 7e5a8624d7 feat: rSwag design-on-demand demo with Printful hybrid pipeline
Add hoodie product + Printful metadata (SKU/sizes/colors) to product catalog.
Rewrite swag designer demo with 4-step interactive flow: product selection
with size/color pickers, inline SVG mockups, artifact generation with
provider matching (cosmolocal + Printful fallback sorted by distance),
revenue split visualization, and pipeline diagram. Add cosmolocal tee and
sticker sheet to cart demo catalog. Add pipeline and fulfillment sections
to swag landing page.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 06:48:10 +00:00
Jeff Emmett f1e90924c0 fix: improve rcal/rtube/rpubs demo rendering and mobile CSS
rCal: add mobile responsive breakpoints, event times with colored
borders, and Today button. rTube: auto-select first video, hide Live
Stream tab in demo, show duration/date metadata. rPubs: fix mobile
layout height calc and toolbar stacking.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 05:57:43 +00:00