Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions client/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ const CommunityAmplifierLanding = lazyWithRetry(() => import("@/pages/marketing/
// const CommunityLanding = lazyWithRetry(() => import("@/pages/marketing/CommunityLanding"));
const VideoHubLanding = lazyWithRetry(() => import("@/pages/marketing/VideoHubLanding"));

// ─── MadeScene landing page (public, no auth) ───
const MadeSceneLanding = lazyWithRetry(() => import("@/pages/madescene/MadeSceneLanding"));

// DEPRECATED: Replaced by /norman as primary front door (Meet Norman rebrand)
// const EverybodyNeedsNormanPage = lazyWithRetry(() => import("@/pages/marketing/EverybodyNeedsNormanPage"));
// DEPRECATED: /forward/norman removed — Norman chat is the front door
Expand Down Expand Up @@ -715,6 +718,7 @@ function Router() {
{/* CharacterX and Continuity landing pages are handled by their /*? routes below,
which conditionally render the landing page for unauthenticated users */}
<Route path="/funnel" component={FunnelLanding} />
<Route path="/madescene" component={MadeSceneLanding} />

<Route path="/enterprise/custom-branding" component={CustomBranding} />

Expand Down
10 changes: 10 additions & 0 deletions client/src/data/landingPageRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,16 @@ export const LANDING_PAGES: LandingPageEntry[] = [
description: 'AI-powered recruitment marketplace connecting candidates, agencies, and employers',
addedAt: '2025-02-09',
},
{
id: 'madescene',
name: 'MadeScene',
slug: '/madescene',
url: '/madescene',
type: 'module',
status: 'active',
description: 'Be Scene. Get Seen. Create your cinematic visual story.',
addedAt: '2026-03-03',
},
{
id: 'finance-director',
name: 'Finance Director',
Expand Down
33 changes: 33 additions & 0 deletions client/src/pages/madescene/MadeSceneLanding.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { useEffect } from "react";
import MadeSceneHero from "./components/MadeSceneHero";
import MadeSceneHowItWorks from "./components/MadeSceneHowItWorks";
import MadeSceneExamples from "./components/MadeSceneExamples";
import MadeSceneFooter from "./components/MadeSceneFooter";

export default function MadeSceneLanding() {
useEffect(() => {
document.title = "MadeScene — Be Scene. Get Seen.";

const existing = document.querySelector('meta[name="description"]');
const meta = existing ?? document.createElement("meta");
meta.setAttribute("name", "description");
meta.setAttribute(
"content",
"Upload your photo, choose your story, and watch yourself become the star of a cinematic visual narrative. Powered by AI."
);
if (!existing) document.head.appendChild(meta);

return () => {
document.title = "NextMonth";
};
}, []);

return (
<div className="min-h-screen bg-[#0a0a14]">
<MadeSceneHero />
<MadeSceneHowItWorks />
<MadeSceneExamples />
<MadeSceneFooter />
</div>
);
}
73 changes: 73 additions & 0 deletions client/src/pages/madescene/components/MadeSceneExamples.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
const examples = [
{
title: "The Last Detective",
style: "Noir",
gradient: "from-gray-800 via-gray-900 to-black",
accent: "border-gray-600",
},
{
title: "Rise of the Phoenix",
style: "Fantasy Epic",
gradient: "from-orange-900 via-red-900 to-amber-950",
accent: "border-orange-700",
},
{
title: "Day One",
style: "Business Origin",
gradient: "from-slate-800 via-blue-900 to-indigo-950",
accent: "border-blue-700",
},
{
title: "Neon Runner",
style: "Cyberpunk",
gradient: "from-purple-900 via-fuchsia-950 to-violet-950",
accent: "border-fuchsia-600",
},
] as const;

export default function MadeSceneExamples() {
return (
<section className="relative bg-[#0a0a14] py-24 sm:py-32">
<div className="mx-auto max-w-6xl px-6">
{/* Section header */}
<div className="mb-16 text-center">
<h2 className="text-3xl font-bold tracking-tight text-white sm:text-4xl">
Stories Waiting for You
</h2>
<p className="mt-3 text-gray-400">
Choose a genre. Become the lead.
</p>
</div>

{/* Cards — horizontal scroll on mobile, grid on desktop */}
<div className="flex gap-6 overflow-x-auto pb-4 sm:grid sm:grid-cols-2 sm:overflow-visible sm:pb-0 lg:grid-cols-4">
{examples.map((example) => (
<div
key={example.title}
className={`group relative flex min-w-[260px] flex-col overflow-hidden rounded-2xl border ${example.accent} border-opacity-30 bg-gradient-to-br ${example.gradient} sm:min-w-0`}
>
{/* Placeholder scene area */}
<div className="relative aspect-[3/4] w-full">
{/* Abstract cinematic overlay */}
<div className="absolute inset-0 bg-gradient-to-t from-black/80 via-transparent to-black/20" />
<div className="absolute inset-0 flex items-center justify-center opacity-10">
<div className="h-24 w-24 rounded-full border-2 border-white/30" />
</div>
</div>

{/* Card info */}
<div className="relative -mt-16 px-5 pb-5">
<h3 className="text-lg font-bold text-white">
{example.title}
</h3>
<span className="mt-1 inline-block rounded-full bg-white/10 px-3 py-0.5 text-xs font-medium text-gray-300">
{example.style}
</span>
</div>
</div>
))}
</div>
</div>
</section>
);
}
51 changes: 51 additions & 0 deletions client/src/pages/madescene/components/MadeSceneFooter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Link } from "wouter";
import { Button } from "@/components/ui/button";

export default function MadeSceneFooter() {
return (
<section className="relative bg-[#0a0a14] pb-16 pt-24 sm:pt-32">
{/* Divider glow */}
<div className="absolute top-0 left-1/2 -translate-x-1/2 h-px w-2/3 bg-gradient-to-r from-transparent via-amber-500/30 to-transparent" />

<div className="mx-auto max-w-2xl px-6 text-center">
{/* Pricing hook */}
<p className="mb-2 text-sm font-semibold uppercase tracking-widest text-amber-400">
Your first story is free
</p>

<h2 className="text-3xl font-bold tracking-tight text-white sm:text-4xl">
Ready to be the star?
</h2>

<p className="mx-auto mt-4 max-w-md text-gray-400">
No sign-up needed to get started. Upload a photo, pick a story, and
see yourself in a whole new light.
</p>

{/* CTA */}
<div className="mt-10">
<Link href="/madescene/create">
<Button
size="lg"
className="h-14 rounded-full bg-gradient-to-r from-amber-500 to-orange-500 px-10 text-lg font-bold text-black shadow-lg shadow-amber-500/25 transition-all hover:scale-105 hover:shadow-amber-500/40"
>
Make Your Scene
</Button>
</Link>
</div>

{/* Platform link */}
<p className="mt-8 text-xs text-gray-600">
Part of the{" "}
<Link
href="/"
className="text-gray-500 underline underline-offset-2 transition-colors hover:text-gray-400"
>
NextMonth
</Link>{" "}
platform
</p>
</div>
</section>
);
}
63 changes: 63 additions & 0 deletions client/src/pages/madescene/components/MadeSceneHero.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { Link } from "wouter";
import { Button } from "@/components/ui/button";
import { Clapperboard } from "lucide-react";

export default function MadeSceneHero() {
return (
<section className="relative min-h-screen flex items-center justify-center overflow-hidden bg-[#0a0a14]">
{/* Film grain overlay */}
<div
className="pointer-events-none absolute inset-0 opacity-[0.04]"
style={{
backgroundImage:
"url(\"data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)' opacity='1'/%3E%3C/svg%3E\")",
backgroundRepeat: "repeat",
}}
/>

{/* Cinematic gradient glow */}
<div className="absolute inset-0 bg-gradient-to-b from-amber-900/10 via-transparent to-[#0a0a14]" />
<div className="absolute top-1/3 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[600px] h-[400px] bg-amber-500/5 rounded-full blur-[120px]" />

<div className="relative z-10 mx-auto max-w-3xl px-6 text-center">
{/* Clapperboard icon */}
<div className="mb-8 inline-flex items-center justify-center rounded-full border border-amber-500/20 bg-amber-500/10 p-3">
<Clapperboard className="h-6 w-6 text-amber-400" />
</div>

{/* Headline */}
<h1 className="text-5xl font-extrabold tracking-tight text-white sm:text-6xl md:text-7xl lg:text-8xl">
<span className="block">Be Scene.</span>
<span className="block bg-gradient-to-r from-amber-300 via-amber-400 to-orange-400 bg-clip-text text-transparent">
Get Seen.
</span>
</h1>

{/* Subhead */}
<p className="mx-auto mt-6 max-w-xl text-lg text-gray-300 sm:text-xl">
Upload your photo. Choose your story. Watch yourself become the star.
</p>

{/* Primary CTA */}
<div className="mt-10">
<Link href="/madescene/create">
<Button
size="lg"
className="h-14 rounded-full bg-gradient-to-r from-amber-500 to-orange-500 px-10 text-lg font-bold text-black shadow-lg shadow-amber-500/25 transition-all hover:scale-105 hover:shadow-amber-500/40"
>
Make Your Scene
</Button>
</Link>
</div>

{/* Secondary text */}
<p className="mt-4 text-sm text-gray-500">
Free to try. No sign-up required.
</p>
</div>

{/* Bottom fade */}
<div className="absolute bottom-0 left-0 right-0 h-32 bg-gradient-to-t from-[#0a0a14] to-transparent" />
</section>
);
}
70 changes: 70 additions & 0 deletions client/src/pages/madescene/components/MadeSceneHowItWorks.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { Camera, BookOpen, Play } from "lucide-react";

const steps = [
{
number: "01",
title: "Create Your Star",
description:
"Upload a selfie or describe your look. Our AI creates your character in any style — graphic novel, anime, cinematic, illustrated.",
icon: Camera,
},
{
number: "02",
title: "Choose Your Story",
description:
"Pick from templates like 'Origin Story', 'Spy Thriller', or 'Fantasy Quest' — or write your own. The AI Director handles the rest.",
icon: BookOpen,
},
{
number: "03",
title: "Watch It Come Alive",
description:
"Your character appears in every scene, consistent and recognisable. Download, share, or go deeper in the full studio.",
icon: Play,
},
] as const;

export default function MadeSceneHowItWorks() {
return (
<section className="relative bg-[#0a0a14] py-24 sm:py-32">
<div className="mx-auto max-w-6xl px-6">
{/* Section header */}
<div className="mb-16 text-center">
<h2 className="text-3xl font-bold tracking-tight text-white sm:text-4xl">
How It Works
</h2>
<p className="mt-3 text-gray-400">
Three steps from selfie to cinematic story.
</p>
</div>

{/* Steps grid */}
<div className="grid gap-12 sm:grid-cols-3 sm:gap-8">
{steps.map((step) => (
<div key={step.number} className="group text-center">
{/* Icon circle */}
<div className="mx-auto mb-6 flex h-16 w-16 items-center justify-center rounded-2xl border border-amber-500/20 bg-amber-500/10 transition-colors group-hover:border-amber-500/40 group-hover:bg-amber-500/20">
<step.icon className="h-7 w-7 text-amber-400" />
</div>

{/* Step number */}
<span className="mb-2 block text-xs font-semibold uppercase tracking-widest text-amber-500/60">
Step {step.number}
</span>

{/* Title */}
<h3 className="mb-3 text-xl font-bold text-white">
{step.title}
</h3>

{/* Description */}
<p className="mx-auto max-w-xs text-sm leading-relaxed text-gray-400">
{step.description}
</p>
</div>
))}
</div>
</div>
</section>
);
}