Preview token propagation:
- JavaScript in storefront base.html appends _preview query param to
all internal links when in preview mode, so clicking nav items
(Services, Contact, etc.) preserves the preview bypass
Scraped content enrichment:
- POC builder now appends first 5 scraped paragraphs to about/services/
projects pages, so the POC shows actual content from the prospect's
site instead of just generic template text
- Extracts tagline from second scraped heading
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The hero and CTA section macros expect button.text.translations but
template JSONs used button.label.translations. Changed all 5 template
homepage files: label → text in button objects.
Also fixed existing CMS pages in DB (page 56) to match.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Build POC button on site detail now passes site_id to the POC
builder, which populates the existing site's store with CMS content
instead of trying to create a new site (which failed with duplicate
slug error).
- poc_builder_service.build_poc() accepts optional site_id param
- If site_id given: uses existing site, skips hosted_site_service.create()
- If not given: creates new site (standalone POC build)
- API schema: added site_id to BuildPocRequest
- Frontend: passes this.site.id in the build request
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Same issue as Create Site button — bg-teal-600 not in Tailwind purge.
Switched to bg-purple-600 and removed $icon('sparkles') which may
not exist in the icon set.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When deleting a hosted site, the associated Store is now soft-deleted
(sets deleted_at). This frees the subdomain for reuse via the partial
unique index (WHERE deleted_at IS NULL).
Previously the Store was orphaned, blocking subdomain reuse.
Closes docs/proposals/hosting-cascade-delete.md.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Button was invisible — likely due to bg-teal-600 not being in the
Tailwind CSS purge or $icon rendering issue. Switched to bg-purple-600
(known to work) and simplified button content.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Draft sites with a linked prospect show a "Build POC from Template"
section with:
- Template dropdown (generic, restaurant, construction, auto-parts,
professional-services) loaded from /admin/hosting/sites/templates API
- "Build POC" button that calls POST /admin/hosting/sites/poc/build
- Loading state + success message with pages created count
- Auto-refreshes site detail after build (status changes to POC_READY)
Visible only for draft sites with a prospect_id.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace raw ID inputs with a live search dropdown that queries
/admin/prospecting/prospects?search= as you type
- Shows matching prospects with business name, domain, and ID
- Clicking a prospect auto-fills business name, email, phone
- Selected prospect shown as badge with clear button
- Optional merchant ID field for existing merchants
- Remove stale "Create from Prospect" link on sites list (was just
a link to the prospects page)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Site creation form:
- Replace old "Create from Prospect" button (called removed endpoint)
with inline prospect_id + merchant_id fields
- Schema requires at least one — form validates before submit
- Clean payload (strip nulls/empty strings before POST)
Sites list:
- Add trash icon delete button with confirmation dialog
- Calls DELETE /admin/hosting/sites/{id} (existing endpoint)
- Reloads list after successful deletion
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Slugify now handles both domains and business names gracefully:
- Domain: strip protocol/www/TLD → batirenovation-strasbourg
- Business name: take first 3 meaningful words, skip filler
(le, la, du, des, the, and) → boulangerie-coin
- Cap at 30 chars
Clients without a domain get clean slugs from their business name
instead of the full title truncated mid-word.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Site detail template: x-show → x-if to prevent Alpine evaluating
expressions when site is null during async loading
- Slugify: prefer domain_name over business_name for subdomain
generation (batirenovation-strasbourg vs bati-rnovation-strasbourg-
peinture-ravalement-dans). Cap at 30 chars. Strip protocol/TLD.
- POC builder passes domain_name for clean slugs
- Remove .lu/.fr/.com TLD from slugs automatically
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The POC viewer was loading the storefront in an iframe, which hit the
StorefrontAccessMiddleware subscription check (POC sites don't have
subscriptions yet). Fixed by rendering CMS sections directly in the
preview template:
- Load ContentPages and StoreTheme from DB
- Render hero, features, testimonials, CTA sections inline
- Apply template colors/fonts via Tailwind CSS config
- HostWizard preview banner with nav links
- Footer with contact info
- No iframe, no subscription check needed
Also fixed Jinja2 dict.items collision (dict.items is the method,
not the 'items' key — use dict.get('items') instead).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Schema: add merchant_id/prospect_id with model_validator requiring
at least one. Remove from-prospect endpoint (unified into POST /sites)
- Service: rewrite create() — if merchant_id use it directly, if
prospect_id auto-create merchant from prospect data. Remove system
merchant hack entirely. Extract _create_merchant_from_prospect helper.
- Simplify accept_proposal() — merchant already exists at creation,
only creates subscription and marks prospect converted
- Tests: update all create calls with merchant_id, replace from-prospect
tests with prospect_id + validation tests
Closes docs/proposals/hosting-site-creation-fix.md
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add wallet diagnostics page at /admin/loyalty/wallet-debug (super admin only)
with explorer-sidebar pattern: config validation, class status, card inspector,
save URL tester, recent enrollments, and Apple Wallet status panels
- Fix Google Wallet fat JWT: include both loyaltyClasses and loyaltyObjects in
payload, use UNDER_REVIEW instead of DRAFT for class reviewStatus
- Fix StorefrontProgramResponse schema: accept google_class_id values while
keeping exclude=True (was rejecting non-None values)
- Standardize all module configs to read from .env file directly
(env_file=".env", extra="ignore") matching core Settings pattern
- Add MOD-026 architecture rule enforcing env_file in module configs
- Add SVC-005 noqa support in architecture validator
- Add test files for dev_tools domain_health and isolation_audit services
- Add google_wallet_status.py script for querying Google Wallet API
- Use table_wrapper macro in wallet-debug.html (FE-005 compliance)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move 39 documentation files from top-level docs/ into each module's
docs/ folder, accessible via symlinks from docs/modules/. Create
data-model.md files for 10 modules with full schema documentation.
Replace originals with redirect stubs. Remove empty guide stubs.
Modules migrated: tenancy, billing, loyalty, marketplace, orders,
messaging, cms, catalog, inventory, hosting, prospecting.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add 55 unit tests for hosting module (hosted site service, client
service service, stats service) with full fixture setup
- Fix table_empty_state macro: add x_message param for dynamic Alpine.js
expressions rendered via x-text instead of server-side Jinja
- Fix hosting templates (sites, clients) using message= with Alpine
expressions that rendered as literal text
- Fix prospecting templates (leads, scan-jobs, prospects) using
nonexistent subtitle= param, migrated to x_message=
- Align hosting and prospecting admin templates with shared design system
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Move platforms menu from CMS to Platform Admin section with create/edit
- Add platform create page, API endpoint, and service method
- Remove CMS-specific content from platform list and detail pages
- Create shared entity_selector + entity_selected_badge Jinja macros
- Create entity-selector.js generalizing store-selector.js for any entity
- Add Tom Select merchant filter to stores page with localStorage persistence
- Migrate store-products page to use shared macros (remove 53 lines of duped CSS)
- Fix broken icons: puzzle→puzzle-piece, building-storefront→store, language→translate, server→cube
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add sections covering CMS locale file structure, translated template
inventory, TranslatableText pattern for sections, and the new
title_translations/content_translations model API with migration cms_002.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>