From a795900e5f36a8d29797a71d1a90d80804ce8ca6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Guti=C3=A9rrez?= <35082514+alezmad@users.noreply.github.com> Date: Sun, 5 Apr 2026 16:03:11 +0100 Subject: [PATCH] fix(web): footer rebrand + disable unbuilt paid-tier cta MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two launch-day cleanups: **Footer rebrand** — full rewrite of modules/marketing/layout/footer.tsx from TurboStarter boilerplate (Twitter/Facebook/LinkedIn socials, Chrome/Firefox/Edge extension links, turbostarter repo links, broken /legal routes) to lean claudemesh structure: - claudemesh wordmark (mesh glyph + serif) + tagline - 2 columns: Product (Docs / Pricing / Changelog / Contact) + Protocol (GitHub / claude-intercom OSS / Protocol spec / Self-host broker) - GitHub social icon linking to github.com/alezmad/claudemesh - I18n controls - Bottom bar: "© 2026 claudemesh · MIT licensed" + the existing BuiltWith credit pointing at claude-intercom (from cdd7931) No trash links. No turbostarter refs. Matches landing design tokens (--cm-*). **Manage-plan CTA guard** — settings/billing → ManagePlan previously always rendered an active "Visit billing portal" button that would 500 on launch day because Stripe isn't set up. For FREE-tier users (everyone at v0.1.0) the button is now disabled + labelled "Paid tiers coming soon". When someone is on a paid tier (future) the real portal flow re-engages. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../src/modules/marketing/layout/footer.tsx | 262 +++++++----------- .../user/settings/billing/manage-plan.tsx | 51 ++-- 2 files changed, 140 insertions(+), 173 deletions(-) diff --git a/apps/web/src/modules/marketing/layout/footer.tsx b/apps/web/src/modules/marketing/layout/footer.tsx index a204054..6844319 100644 --- a/apps/web/src/modules/marketing/layout/footer.tsx +++ b/apps/web/src/modules/marketing/layout/footer.tsx @@ -1,189 +1,141 @@ -import { getTranslation } from "@turbostarter/i18n/server"; -import { isExternal } from "@turbostarter/shared/utils"; +import Link from "next/link"; + import { BuiltWith } from "@turbostarter/ui-web/built-with"; import { Icons } from "@turbostarter/ui-web/icons"; import { appConfig } from "~/config/app"; import { pathsConfig } from "~/config/paths"; import { I18nControls } from "~/modules/common/i18n/controls"; -import { TurboLink } from "~/modules/common/turbo-link"; -const socials = [ - { - id: "x", - href: "https://x.com/turbostarter_", - icon: Icons.Twitter, - }, - { - id: "github", - href: "https://github.com/turbostarter", - icon: Icons.Github, - }, +const REPO_URL = "https://github.com/alezmad/claudemesh"; +const OSS_URL = "https://github.com/alezmad/claude-intercom"; +const columns = [ { - id: "facebook", - href: "#", - icon: Icons.Facebook, + label: "product", + items: [ + { title: "Docs", href: "#docs" }, + { title: "Pricing", href: pathsConfig.marketing.pricing }, + { title: "Changelog", href: "#changelog" }, + { title: "Contact", href: pathsConfig.marketing.contact }, + ], }, { - id: "linkedin", - href: "#", - icon: Icons.Linkedin, + label: "protocol", + items: [ + { title: "GitHub", href: REPO_URL }, + { title: "claude-intercom (OSS)", href: OSS_URL }, + { title: "Protocol spec", href: `${OSS_URL}#protocol` }, + { title: "Self-host broker", href: `${REPO_URL}#self-host` }, + ], }, ]; -const links = [ - { - label: "common:product", - items: [ - { - title: "marketing:product.mobile.ios.title", - href: "https://turbostarter.dev", - }, - { - title: "marketing:product.mobile.android.title", - href: "https://turbostarter.dev", - }, - { - title: "marketing:product.extension.chrome.title", - href: "https://chromewebstore.google.com/detail/bcjmonmlfbnngpkllpnpmnjajaciaboo", - }, - { - title: "marketing:product.extension.firefox.title", - href: "https://addons.mozilla.org/addon/turbostarter_", - }, - { - title: "marketing:product.extension.edge.title", - href: "https://microsoftedge.microsoft.com/addons/detail/turbostarter/ianbflanmmoeleokihabnmmcahhfijig", - }, - ], - }, - { - label: "resources", - items: [ - { - title: "marketing:contact.label", - href: pathsConfig.marketing.contact, - }, - { - title: "marketing:roadmap.title", - href: "https://github.com/orgs/turbostarter/projects/1", - }, - { - title: "marketing:docs.title", - href: "https://turbostarter.dev/docs/web", - }, - { - title: "marketing:api.title", - href: "#", - }, - ], - }, - { - label: "about", - items: [ - { - title: "billing:pricing.label", - href: pathsConfig.marketing.pricing, - }, - { - title: "marketing:blog.label", - href: pathsConfig.marketing.blog.index, - }, - ], - }, - { - label: "legal.label", - items: [ - { - title: "legal.privacy", - href: pathsConfig.marketing.legal("privacy-policy"), - }, - { - title: "legal.terms", - href: pathsConfig.marketing.legal("terms-and-conditions"), - }, - ], - }, -] as const; - -export const Footer = async () => { - const { t } = await getTranslation({ - ns: ["common", "marketing", "billing"], - }); - +export const Footer = () => { return ( - diff --git a/apps/web/src/modules/user/settings/billing/manage-plan.tsx b/apps/web/src/modules/user/settings/billing/manage-plan.tsx index 63004a9..28be8c0 100644 --- a/apps/web/src/modules/user/settings/billing/manage-plan.tsx +++ b/apps/web/src/modules/user/settings/billing/manage-plan.tsx @@ -48,24 +48,39 @@ export const ManagePlan = () => { - + {plan.id === PricingPlanType.FREE ? ( + // v0.1.0: only the free tier is live. Paid-tier checkout + + // Stripe customer portal land post-launch; surface that + // honestly instead of a button that would hit a 500. +
+ + + Paid tiers coming soon + +
+ ) : ( + + )}
);