Commit Graph

7 Commits

Author SHA1 Message Date
Marco Sadjadi
fd147f9998 feat(web): Remotion hero video — Section 2 (prompt → server → connect)
All checks were successful
Deploy to Production / deploy (push) Successful in 1m13s
New @bmm/video workspace at remotion/. Renders an 8s 1920×1080 H.264
+ WebM + JPG poster sequence that visualises the three-step "How it
works" pitch literally:

- Beat 1 (0-2s): "Search our Notion workspace" word-by-word entrance
  with spring-in from below + brief indigo under-glow + monospace
  prompt.txt label. Blinking cursor bridges the loop seam.
- Beat 2 (2-5s): each prompt word detonates into ~9 particles per
  word; particles drift, then magnetically converge onto target slots
  along a server schematic that strokes itself on. Scan-line sweep +
  corner labels (mcp-notion, OAuth 2.1, search_pages, get_page_content)
  sell that this is a real artefact, not a placeholder.
- Beat 3 (5-8s): Claude Desktop client panel slides in from the right;
  a Bézier wire animates between server and client; three data-packet
  dots travel along the wire; 200-OK tag pops; green live-dot pulses
  on the server. Last 12 frames fade to black so frame 239 ≈ frame 0
  and browser <video loop> has no visible seam.

Brand palette is hard-coded in lib/colors.ts to match globals.css —
keeps the Remotion bundle self-contained (no Tailwind import needed).
springIn / softSpring / clampLerp / rand helpers in lib/easings.ts
power the motion vocabulary. Concurrency=1 + yuv420p in the config
gives a deterministic render that plays on every <video> tag.

File sizes: hero.mp4 449 KB, hero.webm 258 KB, hero-poster.jpg 33 KB —
all well under the 3 MB / 250 KB ceilings.

Section 2 ("How it works") now opens with the video in a
border-bordered aspect-video panel between the heading and the three
existing cards. autoPlay+muted+loop+playsInline satisfies every mobile
autoplay policy; motion-reduce:hidden swaps in the static poster for
prefers-reduced-motion users.

Scripts:
- pnpm --filter @bmm/video render:all  (mp4 + webm + poster)
- pnpm --filter @bmm/video to-web      (copy to apps/web/public/videos/)
- pnpm --filter @bmm/video build       (both, end-to-end)

`to-web` is the script name because `publish` collides with pnpm's
built-in npm-publish command which refused to run with an unclean tree.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 10:57:08 +02:00
Marco Sadjadi
2267daadd4 perf(web): server-only StaticCodeBlock for above-the-fold marketing
All checks were successful
Deploy to Production / deploy (push) Successful in 52s
PageSpeed Insights mobile reported LCP element render delay of 2.3s
on the hero — the largest visible element is the build.log <pre> with
"> Generating spec... OK ..." text. TTFB is 0ms (CF cache hit), so the
delay was pure client-side: Lighthouse waited for the JS bundle to
parse and the 'use client' CodeBlock boundary to hydrate before it
considered the element "rendered."

CodeBlock pulls in lucide-react (Copy/Check icons) plus a useState
boundary just for the copy button. Above the fold on marketing, none
of that is needed — the user just needs to see the snippet.

Split:
- New `static-code-block.tsx`: server component, no 'use client',
  no icons, no copy button. Pure SSR markup that paints with the HTML.
- Marketing landing now uses StaticCodeBlock for all three hero
  snippets (prompt.txt / build.log / claude_desktop_config.json).
- Interactive CodeBlock stays in use for dashboard pages where users
  actually want to copy snippets.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 23:30:41 +02:00
Marco Sadjadi
88c7262a08 fix(web): mobile-responsive hero, marketing site, docs and dashboard
All checks were successful
Deploy to Production / deploy (push) Successful in 1m13s
- Hero h1 was a fixed text-[44px] — overflowed narrow phones. Now
  text-[30px] sm:text-[40px] md:text-[56px].
- Hero grid children get min-w-0 so the code blocks' overflow-x-auto
  actually constrains instead of widening the page.
- Marketing nav: the inline links were hidden below md with no fallback.
  Added a hamburger MobileMenu; "Sign in" collapses into it on the
  smallest screens.
- Section vertical padding is now responsive (py-14 sm:py-20).
- globals.css: overflow-x: clip on <html> as a safety net.
- docs: the 240px sidebar is hidden below lg, article gets min-w-0.
- dashboard header: nav labels collapse to icons on small screens.

Verified: next build passes (40/40 pages).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 23:25:26 +02:00
Marco Sadjadi
b843394d0f feat(web): full SEO stack — metadata, JSON-LD, sitemap, robots, OG image
Some checks failed
Deploy to Production / deploy (push) Failing after 46s
Ported and adapted from the BuildMyDiscord SEO setup:

- lib/seo.ts — single source for site constants, the FAQ data (shared by
  the rendered FAQ and the FAQPage schema so they never drift) and JSON-LD
  builders.
- Rich root metadata: title template, keywords, Open Graph, Twitter card,
  robots directives, canonical.
- JSON-LD: Organization + WebSite + SoftwareApplication sitewide, FAQPage
  on the landing page. No AggregateRating — there are no real reviews yet.
- app/robots.ts — allow all, explicit allow-list for AI answer-engine
  crawlers (GPTBot, ClaudeBot, PerplexityBot, …), disallow private routes.
- app/sitemap.ts — every public marketing + docs route.
- app/opengraph-image.tsx — monochrome on-brand 1200x630 share card.
- app/manifest.ts + public/llms.txt.
- Per-page metadata for pricing, changelog, security, privacy, terms,
  docs, templates and status.
- opengraph-image + apple-icon pinned to the edge runtime — next/og
  crashes during a Node-runtime prerender.

Verified: next build passes; /robots.txt, /sitemap.xml,
/manifest.webmanifest and /opengraph-image all generate.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 19:16:40 +02:00
Marco Sadjadi
e46a9a1cf8 feat(web): surface the template marketplace on the landing page
The marketplace is the distribution channel — fork a working server or
publish your own — but it was absent from the landing page. Adds a
section between Examples and Pricing with a second conversion path into
/templates.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 00:37:06 +02:00
Marco Sadjadi
a189111782 feat(marketplace): default-on share in wizard + owner unshare anytime
Goal: maximize template volume without a dark pattern and without leaking data.

Wizard Done-page Share panel:
- 'Share as template in the marketplace (recommended)' checkbox, default ON,
  rendered inline in the build-success flow where every user lands.
- Honest copy — corrected a draft that claimed 'only abstracted code pattern is
  shared'. That is false: the FULL generated code becomes publicly viewable on
  the template detail page (by design, for pre-fork audit). The panel now says:
  'Your secrets stay private ... but your generated code becomes publicly
  viewable so others can audit it before forking. Unshare anytime.'
- When checked: inline minimal form — short description (prefilled from the
  spec), category select, optional per-secret credential hints. One 'Publish to
  marketplace' click. Not auto-published silently — that would be a consent dark
  pattern; one visible deliberate click keeps it clean.
- Forked servers don't show the panel (re-publishing a fork is an edge case).

Owner unshare/reshare:
- GET /v1/servers/:id/template — owner lookup, drives the Publish tab UI.
- PATCH /v1/templates/:slug/visibility { shared } — owner-only toggle between
  public and hidden. 403 for non-owners, 409 if an admin took it down (owner
  cannot resurrect an admin takedown). Audit-logged as template.unshare /
  template.reshare.
- Server-detail Publish tab now detects an existing template and shows the
  shared status (public/hidden/takedown badge), fork count, a marketplace link
  and an Unshare/Re-share button — instead of the publish form.

Why this is safe to default ON:
- Secrets are architecturally bound to mcp_servers, never copied into templates.
  Publish reads tools_schema + generated_code only; the secrets table is never
  touched. Data leak is structurally impossible, not policy-dependent.
- Publish re-scans the generated code for banned patterns AND hardcoded
  credentials (sovereign-audit hardening) before it can reach the marketplace.
- The user sees a visible, pre-ticked checkbox and reads one honest sentence
  before publishing. Privacy-conscious users untick; everyone else contributes
  volume. Informed consent, GDPR-clean.

Verified end-to-end via API:
  GET server/:id/template -> null (unpublished)
  POST /v1/templates -> published, slug share-test-server
  GET server/:id/template -> status public
  PATCH visibility {shared:false} -> hidden, drops out of public list
  PATCH visibility {shared:true} -> public again
UI: Publish tab renders the shared-status panel with View + Unshare (screenshot
confirmed).

Also: hero badge date set to 2026-05-20. Changed 'MCP spec 2025-11-25' to
'updated 2026-05-20' — claiming an MCP spec dated today would be factually wrong
(no such spec release exists); 'updated' is accurate and gives the requested
fresh date. The real spec date is still cited correctly in /docs.
2026-05-20 17:04:46 +02:00
Marco Sadjadi
f2238f2e6b feat(web): Next.js 15 shell — design tokens, landing, auth pages 2026-05-19 00:30:20 +02:00