From 00c6692c7a03cc8efcd72444c08167540294a69a Mon Sep 17 00:00:00 2001 From: Marco Sadjadi Date: Tue, 26 May 2026 06:43:56 +0200 Subject: [PATCH] feat(web): mobile-responsive /templates + drop pre-launch SiteBanner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two related polish items: 1. Remove the global blue Preview banner from app/layout.tsx and delete the SiteBanner component. The component's own comment said "Remove once the service is open for production use" — Stripe live billing, OAuth, and per-runner TLS are all wired now, so the pre-launch notice is misleading. 2. Mobile-responsive treatment for the standalone /templates page (it lives outside (dashboard) layout, so it didn't inherit the new mobile chrome from the dashboard pass): - Top header tightened: "/templates" breadcrumb + Dashboard link + "+ New server" pill all hidden on mobile (the avatar UserMenu + bottom MobileActionBar cover those paths). - Logged-in users now get the same MobileActionBar tab-bar at the bottom (Market tab active), giving consistent app-shell across dashboard pages. - Filter row stacks vertically on mobile with search on top (thumb reach), then a horizontally-scrollable chip row for scope / sort / category so segmented controls don't squeeze below their min-width. - h1 scales 32px → 24px on mobile; padding tightened to px-4 py-8. - main gets pb-24 when logged in so cards clear the tab bar. Logged-out marketplace browsing keeps the simpler marketing chrome (Logo + "Start building" CTA) — no tab-bar, since visitors don't have a dashboard to navigate into yet. Co-Authored-By: Claude Opus 4.7 (1M context) --- apps/web/app/layout.tsx | 2 - apps/web/app/templates/page.tsx | 177 ++++++++++++++++------------ apps/web/components/site-banner.tsx | 17 --- 3 files changed, 103 insertions(+), 93 deletions(-) delete mode 100644 apps/web/components/site-banner.tsx diff --git a/apps/web/app/layout.tsx b/apps/web/app/layout.tsx index e6b8402..cda63ca 100644 --- a/apps/web/app/layout.tsx +++ b/apps/web/app/layout.tsx @@ -1,5 +1,4 @@ import { JsonLd } from '@/components/json-ld'; -import { SiteBanner } from '@/components/site-banner'; import { SEO_KEYWORDS, SITE_DESCRIPTION, @@ -63,7 +62,6 @@ export default function RootLayout({ children }: { children: React.ReactNode }) > - {children} diff --git a/apps/web/app/templates/page.tsx b/apps/web/app/templates/page.tsx index 462f660..12879cd 100644 --- a/apps/web/app/templates/page.tsx +++ b/apps/web/app/templates/page.tsx @@ -7,6 +7,8 @@ import { apiFetch } from '@/lib/api'; import { cn } from '@/lib/cn'; import { Logo } from '@/components/logo'; import { Input } from '@/components/input'; +import { MobileActionBar } from '@/components/mobile-action-bar'; +import { UserMenu } from '@/components/user-menu'; interface Template { id: string; @@ -89,38 +91,46 @@ export default function TemplatesMarketplace() { return (
-
-
+
+
- / templates + {/* "/ templates" subtitle is redundant on mobile — h1 below + already names the page. Keep on desktop as breadcrumb. */} + + / templates +
-
-
-
+
+
Marketplace
-

+

MCP server templates

-

+

Pre-built MCP servers from the community. Fork in one click — your own container, your own credentials, fully isolated. The template author never sees your data.

-
- {loggedIn && ( - <> -
- {(['all', 'mine'] as Scope[]).map((s) => ( - - ))} -
-
- - )} - - {scope === 'all' && ( - <> -
- {(['trending', 'top', 'newest'] as Sort[]).map((s) => ( - - ))} -
-
- - )} - - -
+ {/* Filter row: stacks vertically on mobile (search on top for thumb + reach), inline on desktop. The order utility on the Input flips + it to the right side at sm: while filters wrap normally. */} +
setSearch(e.target.value)} placeholder="Search…" - className="w-60" + className="order-first w-full sm:order-last sm:ml-auto sm:w-60" /> + + {/* Chips row — horizontally scrollable on narrow mobile so the + segmented controls never get squeezed below their min-width. */} +
+ {loggedIn && ( + <> +
+ {(['all', 'mine'] as Scope[]).map((s) => ( + + ))} +
+
+ + )} + + {scope === 'all' && ( + <> +
+ {(['trending', 'top', 'newest'] as Sort[]).map((s) => ( + + ))} +
+
+ + )} + + +
{!visible &&

Loading…

} @@ -245,10 +270,14 @@ export default function TemplatesMarketplace() {
-
+
Every template is isolated: forking creates your own container with your own secrets.
+ + {/* Mobile tab-bar — only when signed in. Logged-out marketplace + browsing keeps the simple marketing chrome (login CTA in header). */} + {loggedIn && }
); } diff --git a/apps/web/components/site-banner.tsx b/apps/web/components/site-banner.tsx deleted file mode 100644 index a8dd917..0000000 --- a/apps/web/components/site-banner.tsx +++ /dev/null @@ -1,17 +0,0 @@ -// Temporary pre-launch notice. Remove this component and its import in -// app/layout.tsx once the service is open for production use. -// Background is #4f46e5 (not the #6366f1 accent) so white text clears the -// WCAG AA 4.5:1 contrast ratio for this small text — #6366f1 fell just short. -export function SiteBanner() { - return ( -
- Preview - · - BuildMyMCPServer is not yet open for production use — sign-ups, server generation and billing - are still being finalised, and data may be reset. -
- ); -}