Frontend was crashing with "Unexpected token 'I'" when the backend
returned plain text errors (e.g. "Internal Server Error" from proxy).
Now safely falls back to response.text() when JSON parsing fails.
Also prevents backend from swallowing HTTPException in catch-all.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Simplify deployment to serve only the static landing page at rswag.online.
The actual swag app now lives in rspace-online at /demo/swag.
Remove PostgreSQL, Redis, FastAPI backend, and Next.js frontend services.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
CLAUDE.md may contain project context with credentials and is now
covered by global gitignore to prevent accidental secret commits.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace custom HeaderBar with standard Header.tsx + SwagNavActions
- AppSwitcher: rTube/rSwag → Creating, rSocials → Sharing, rData → Observing
- EcosystemFooter: updated link order to match new categories
- UserMenu: 🔑 Sign In button, 🔐 lock when logged in
- SpaceSwitcher: reads EncryptID token, sends Bearer header
- /api/spaces proxy: forwards to rspace.online (canonical spaces)
- /api/me: verifies EncryptID token for auth status
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Consolidating rswag-online static landing page into landing/ directory
before renaming this repo to rswag-online on Gitea.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The rSwag Infisical project has stale SMTP values that can't be
updated (admin identity not a project member). Fetch authoritative
SMTP_HOST, SMTP_USER, and SMTP_PASSWORD from claude-ops /mail
folder which overrides stale values from both .env and rSwag
Infisical project.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Entrypoint now fetches RSWAG_SMTP_PASSWORD from claude-ops /mail
folder if SMTP_PASSWORD is not already set. This allows the rSwag
container to get its SMTP credentials without needing direct write
access to the .env file.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All email sending now uses mail.rmail.online as the SMTP host,
replacing the legacy mx.jeffemmett.com hostname.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- EmailService with async SMTP via aiosmtplib (Mailcow)
- HTML email templates matching rSwag dark theme branding
- Order confirmation sent after successful Mollie payment
- Shipping notification with tracking info sent when POD ships
- Non-blocking: email failures logged but don't break order flow
- SMTP config: smtp_host, smtp_port, smtp_user, smtp_password in .env
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Space links now go to <space>.<app-domain> (e.g., myspace.rswag.online)
instead of rspace.online/<space>. Matches the standard rApp header
pattern used across all rStack apps.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Matches the rApp header pattern: [AppSwitcher | SpaceSwitcher | Logo].
SpaceSwitcher fetches available spaces from /api/spaces and allows
switching between community storefronts (rSwag, Fungi Flows, etc.).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add @encryptid/sdk (vendored) for WebAuthn passkey authentication
- Add zustand auth store matching rMaps/rWork pattern
- Create AuthButton component (sign in / register / sign out)
- Create HeaderBar client component: AppSwitcher + logo + nav + auth + cart
- Remove custom SpaceSwitcher (not part of standard rApp header)
- Fix hero: "Noticed" and "rMerch" now use same gradient color
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Matches the shared header pattern used across rWork, rMaps, and other rApps.
AppSwitcher shows all 19 r* ecosystem apps grouped by category.
SpaceSwitcher allows switching between rSwag spaces (e.g. Fungi Flows).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Switch to dark theme by default (globals.css + default space.yaml)
- Rewrite landing page copy to emphasize community revenue streams
- "Revenue for Your Community" hero
- "Merch That Funds Your Mission" section with revenue breakdown
- Revenue routing to rFunds/DAOs/treasuries
- Step 1: "Upload or Create a Design"
- Step 3: "Ship Locally — Worldwide" (local fulfillment, less carbon)
- Features: Revenue Streams, Local Fulfillment replace old cards
- All designs now show on default space (space: all)
- DefectFi design gets hoodie product variant
- Fix light-mode hardcoded colors for dark compatibility (red-50, green-600)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces simple hero+products page with full rApp-style landing:
- Ecosystem badge ("Part of the rSpace Ecosystem")
- Hero section with gradient text and dual CTA
- "How It Works" 3-step cards (Upload → Pick Products → Ship)
- 6-feature grid (AI Studio, Spaces, Zero Inventory, Mockups, Payments, Ecosystem)
- Featured products section (first 6, with "view all" link)
- CTA card with gradient background
- Sticky nav with logo badge, cart icon, and compact links
- r* ecosystem footer with links to all rApps
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Flood-fill from edges to make background transparent while
preserving white text, red accents, and bug illustrations.
Design now works on any shirt color.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v2 returns {data: [...]} (array) not {data: {...}} (object).
Also fixes mockup task polling to use ?id= query param and
extracts mockup_url from nested catalog_variant_mockups structure.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Secrets are stored in Infisical and injected at startup via the
entrypoint script. Docker-compose also passes them as fallback env
vars from the host .env.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The v2 API uses products array with catalog source, nested layers in
placements, and GET /mockup-tasks/{id} for polling. Also removes
hardcoded domain in favor of PUBLIC_URL setting.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Design box expanded from 370x370 to 500x450 and repositioned
higher on the chest for typical t-shirt print proportions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Screen blend now uses brightness mask from the design so only
non-dark pixels show through. Prevents visible dark rectangle
when design has its own dark background (e.g. DefectFi tee).
- Add ?fresh=1 query param to /mockup endpoint for cache bypass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Backend:
- Replace tiny placeholder templates with photorealistic 1024x1024 product
photos (blank t-shirt, sticker with peeling corner, framed print)
- Rewrite Pillow compositing: screen blend for dark garments (design looks
printed on fabric), direct paste for stickers/prints
- Add PRINTFUL_STORE_ID config + X-PF-Store-Id header to Printful client
(unblocks existing account-level tokens)
Frontend:
- Product listing: rounded cards with shadows, category badges, hover
animations, lazy loading, empty state
- Product detail: skeleton loading, mockup type switcher with loading
indicator, raw design preview, inline price in Add to Cart button,
shipping/quality info section
- Homepage: featured products now show mockups instead of raw designs,
professional card layout matching products page
- Client-side mockups: updated coordinates for new templates, screen
blend support via Canvas globalCompositeOperation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
API activate endpoint returned 500 (file permission issue in container).
Setting status directly to active in metadata.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Punk-style distressed typography with beetles and glitch effects.
Generated via Gemini Nano Banana Pro, sized to Printful 3600x4800 specs.
Starts as draft — activate via API when ready.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add Python-based entrypoint.sh that authenticates with Infisical via
universal-auth, fetches secrets, and exports them as env vars before
starting uvicorn. Secrets like MOLLIE_API_KEY, PRODIGI_API_KEY,
PRINTFUL_API_TOKEN, JWT_SECRET, GEMINI_API_KEY, and FLOW_* vars are
now pulled from Infisical instead of being passed through docker-compose.
Gracefully degrades: if no INFISICAL_CLIENT_ID/SECRET are set or if
the fetch fails, the container starts with whatever env vars exist.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- PrintfulClient: catalog variants (cached 24h), mockup generation
(async create+poll), order submission, variant ID resolution
- Mockup endpoint tries Printful API first for Printful-provider designs,
falls back to Pillow compositing for others (e.g. Prodigi stickers)
- Order service routes items by provider from design metadata:
provider=printful → Printful API, provider=prodigi → Prodigi API
- Sandbox mode creates draft orders on Printful (not fulfilled)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Prodigi v4 API client for order fulfillment (create/get orders, quotes)
- Server-side mockup generation: Pillow composites designs onto product
templates (shirt, sticker, print) at GET /api/designs/{slug}/mockup
- Product listing and detail pages now show designs ON products
- Mockup type switcher on product detail page (T-Shirt/Sticker/Art Print)
- Order service submits to Prodigi after successful payment
- POD webhook endpoint for fulfillment status updates
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Map fungiswag.jeffemmett.com to the fungiflows space so it can be used
independently of the rswag.online domain.
- Middleware: detect fungiswag.jeffemmett.com → fungiflows space
- Traefik: add Host rule for fungiswag.jeffemmett.com
- CORS: allow fungiswag.jeffemmett.com origin
- Space config: update domain field
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Users can upload their own logo/design, see instant mockup previews on
shirts, stickers, and art prints via client-side Canvas compositing,
then save and activate the design to the store for ordering.
- Backend: POST /api/design/upload with file validation (type, size,
dimensions), Pillow processing, saves to designs/uploads/
- Frontend: /upload page with drag-and-drop, real-time mockup gallery,
activate/discard flow matching existing Design Swag pattern
- Fix: activate/delete endpoints now scan all category dirs instead of
hardcoding stickers/
- Nav: "Upload Swag" button added to header and homepage CTAs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add subdomain-based spaces system for branded storefronts. Each space
has its own theme, product catalog, and isolated cart via scoped
localStorage keys.
- Backend: SpaceService loads YAML configs, new /api/spaces endpoints,
design filtering by space, CORS regex for *.rswag.online
- Frontend: Next.js middleware detects subdomain and sets space_id cookie,
dynamic CSS variable injection for theming, space-aware API calls
- Spaces: _default (rSwag hub, cyan/orange) and fungiflows (gold/green/purple)
- Docker: Traefik wildcard HostRegexp for subdomain routing
- Designs: Placeholder Fungi Flows sticker and logo tee
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace mx.jeffemmett.com and noreply@jeffemmett.com with generic
placeholders to avoid GitGuardian SMTP credential alerts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Forked from mycopunk-swag-store and rebranded for rSpace:
- Next.js 15 + FastAPI + PostgreSQL + Stripe
- Printful + Prodigi POD integration
- AI design generation via Gemini API
- rSpace color scheme (cyan/orange) and branding
- In-repo designs directory (stickers, shirts, misc)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>