Offboard Wix: 4 marketing pages + contact form#334
Conversation
Brainstormed and planned with Claude. Spec covers porting four marketing pages (home, about, subscribe, contact) from Wix into the Rails app with per-page singular controllers, a separate marketing layout, S3-hosted assets, and a contact form. Plan breaks the work into 15 TDD-disciplined tasks for subagent-driven execution. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 168f687cea
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| t.string :phone | ||
| t.text :message, null: false | ||
| t.string :ip | ||
| t.string :user_agent |
There was a problem hiding this comment.
Store captured user agents without the 255-byte cap
Because ContactController#create copies request.user_agent into this column, any legitimate browser, extension, or bot that sends a User-Agent longer than PostgreSQL's string limit will make @message.save raise instead of saving the contact request and emailing the bakery. Use a text column here, or truncate/validate before saving, so long headers do not turn valid /contact submissions into 500s.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Addressed in 37ccecd — the offending file (the ContactMessage migration) was deleted in c6ed094 when we switched to the existing Feedback model, but the same length concern applied there. Added a before_validation to Feedback that truncates user_agent (512) and url (2048) so long request headers can't fail save and lose the submission. The length validations stay as belt-and-suspenders.
There was a problem hiding this comment.
what happens if we don't have claude api key on gh workflows etc
There was a problem hiding this comment.
Addressed in 2ea1a48. Per CLAUDE.md visual specs aren't in CI, but anyone running them locally without the key was getting a hard module-load failure (new Anthropic() throws at construction). Now: client construction is deferred (process.env.ANTHROPIC_API_KEY ? new Anthropic() : null) and each test calls test.skip(!client, ...) — running without the key reports tests as skipped instead of broken. Same fix applied to the existing email-screenshots.spec.ts for consistency.
Drop the ContactMessage model, ContactMailer, and associated admin/tests. Route contact form submissions into Feedback with source: "contact". Add name/phone columns to feedbacks, surface them in the mailer and admin, and set reply_to from the submitter's email when present. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
HomeController, AboutController, SubscribeController, and ContactController all declared layout "marketing" and skip_before_action :authenticate_user! independently. Pull both declarations into a shared MarketingController base. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add named route helpers (about_path, subscribe_path, contact_path) and replace raw <a href> tags with link_to in the marketing header, footer, home page CTAs, and subscribe CTA. The contact form's url also switches to contact_path. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Long browser User-Agent or referer URLs would fail validation and lose the submission. Both fields are captured from request headers, never user-typed, so silent truncation is the right behavior. Length validations stay as belt-and-suspenders for any caller that bypasses the callback.
The Anthropic SDK throws at construction without the key, which made the spec fail at module load. Defer client construction and call test.skip in each test body so 'bunx playwright test' without the key reports tests as skipped instead of broken.
… visual helper - contact_controller: redirect_to contact_path (×2) instead of literal '/contact' - feedback_mailer: reply_to: @feedback.email.presence — drop the splat-or-empty hash - feedback_test: drop 'contact is a valid source' (already covered by valid-sources loop) - visual specs: extract test/visual/helpers.ts for the Anthropic client guard, PNG height-crop fallback, and messages.create call. Both email and marketing specs now share the subtle 7900px height threshold rather than maintaining it twice.
|
Superseded by #351, which carries the same Wix offboarding work forward (pixel-matched to the live Wix design). |
…m CreditBundle Setting.holiday_menu_id lingers after a holiday ends, so the marketing nav kept advertising a menu that no longer accepts orders (the member app handles this gracefully with a closed state; marketing shouldn't advertise it at all). The subscribe page hardcoded Wix's stale $182/$98 pricing — 7-13% below what checkout actually charges. Render from the same CreditBundle rows the purchase flow uses so copy can't drift again. Refs #334 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Visual fixes from side-by-side screenshot audit against motzibread.com: - Body font: EB Garamond serif -> Mulish light (Wix uses Avenir LT Light / DIN Next Light; Mulish is the closest Google Fonts stand-in) - Home hero: full-bleed illustration with the three-line brick-red tagline overlaid in cream highlight boxes, as on Wix - Purple announcement bar under the header (pre-order link + hours; Wix renders it as a dismissible overlay, ours is a solid band) - Contact form: underline-only fields, placeholder labels with required asterisks, name/email side by side, plain-text Send (labels stay in the markup, visually hidden) - Section headings: Mulish instead of Oswald; terracotta on About, purple uppercase on Subscribe (with Wix's trailing dash quirk) - Footer: Wix three-column layout (logo + vertical nav / one-line terracotta address / IG), stacked right-aligned credits - About: restore the 'local grain movement' sentence Wix had; its 'here' link is dead on Wix, pointed at Common Grain Alliance pending owner confirmation - Sold-out badge angled like Wix's sticker Integration: - Marketing pages now load GA (shared layouts/_analytics partial), the browser error reporter, and ahoy tracking via a new marketing pack - Per-page meta descriptions + OpenGraph tags - Sign out link in the marketing nav for signed-in users - CanonicalHostRedirect middleware: set CANONICAL_HOST at DNS cutover and motzibread.herokuapp.com 301s to the custom domain (no-op until then; health checks exempt) Refs #334 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The subscription concept is legacy: creating an account just joins the weekly menu email list (sign-up sets receive_weekly_menu), and credits are an optional pre-purchase for a per-loaf discount. The Wix copy this branch ported still sold 'subscriptions', including a hardcoded 'Currently Sold Out' badge that contradicts prod, where Setting.accepting_subscribers is true. - /subscribe: 'How It Works' page — weekly menu email, then credits - Nav label Subscriptions -> How It Works (header + footer) - Home purple band: 'Get the Weekly Menu' - CTA: SUBSCRIBE NOW -> SIGN UP NOW - Sold-out badge now renders only when accepting_subscribers is off Refs #334 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Summary
Folds the four marketing pages (
/,/about,/subscribe,/contact) from the Wix-hosted motzibread.com into the Rails app. Self-hosts all marketing assets in S3 and adds a contact form that emails the bakery while persisting submissions for triage in/admin.HomeControllerrewritten to render instead of redirect; newAboutController/SubscribeController/ContactController) with a separatemarketing.html.erblayout andmarketing.scssscoped underbody.marketingContactMessagemodel + ActiveAdmin resource +ContactMailer.notify_bakery(with submitter as Reply-To); honeypot field for spam; rack-attack throttle 5/hr/IP on POST/contactMarketingHelper#holiday_menu_linksurfaces a nav link toMenu.current_holidaywhen active — replaces the old Wix → motzibread.square.site flow with an in-app link to/menus/:ids3://motzi/public/marketing/via one-shotrake marketing:fetch_assets; map atdocs/superpowers/specs/marketing-assets-map.mdtest/visual/marketing-screenshots.spec.ts(manual, not CI)Spec:
docs/superpowers/specs/2026-05-12-wix-cms-migration.mdPlan:
docs/superpowers/plans/2026-05-12-wix-cms-migration.mdBefore merging
CONTACT_INBOXon Heroku (defaults toinfo@motzibread.comif unset; confirm with Maya/Russell)marketing.scssfor page-body classes (.hero,.cta-primary,.field,.find-us, etc.) — current SCSS only styles the layout chrome, so CTA buttons and form fields render browser-defaultTest plan
/,/about,/subscribe,/contacton the deployed Heroku app and confirm each renders/admin/contact_messagesand that the bakery inbox receives the email with the submitter as Reply-To/menu(existing menu) and/admin(existing admin) still work — marketing layout shouldn't leak/— confirm "Admin" link appears in the marketing nav/signout— confirm redirect back to/(now the marketing home)/menu(verified: all order/reminder mailers usecurrent_menu_url(uid: ...))bunx playwright test test/visual/marketing-screenshots.spec.tsagainst this branch with Rails onlocalhost:3000Follow-ups (separate work, not in this PR)
motzibread.comat Heroku, retire Wix subscriptionmotzibread.square.siteonce holiday menus run through the in-app flow