BMJ Claude Code Prompts

assetactive

Provenance

Ingested from C:\Users\mesha\Downloads\Identity_Design\BMJ_CLAUDE_CODE_PROMPTS.md on 2026-03-28. Original file ~37KB. Full content included below.


THE BLACK MALE JOURNAL — CLAUDE CODE IMPLEMENTATION PROMPTS

Copy-paste these directly into Claude Code CLI sessions

Each prompt is one session. Go in order. Don't skip.


HOW TO USE THIS FILE

  1. Open your terminal, cd C:\Projects\blackmalejournal, run claude
  2. Copy the entire prompt block for the session you're on
  3. Paste it into Claude Code
  4. Claude will write a /plan first — read it, approve it, then say "build it"
  5. When done, run /project:deploy-check before committing
  6. git add . && git commit -m "[message]" && git push
  7. /clear context, then move to the next session

PRE-FLIGHT: VERIFY CLAUDE.md IS LOADED

Before Session 1, paste this to confirm Claude has your project memory:

Show me what you know about this project from CLAUDE.md. List the brand colors,
fonts, architecture rules, and content model. If you can't find CLAUDE.md, tell
me — I need to create it before we start.

✅ If Claude recites your brand system back to you, you're good. ❌ If Claude doesn't know, create CLAUDE.md from the Master Plan first.


SESSION 1: DESIGN SYSTEM + ROOT LAYOUT + NAVIGATION

/plan Build the complete design foundation for The Black Male Journal.

This is Session 1 of 14. Nothing exists yet except the Next.js scaffold and
dependencies from package.json. Everything you build here is the foundation
every other page depends on — get it perfect.

Here's exactly what I need built, in this order:

1. BRAND CSS (src/styles/brand.css)
   - All 7 --bmj-* CSS custom properties exactly as defined in CLAUDE.md
   - Font family variables: --font-display, --font-body, --font-label, --font-mono
   - Grain overlay variables: --grain-opacity (0.04), --texture-url
   - Spacing scale variables (xs through 2xl)
   - Content max-width variables (content: 1200px, article: 720px, wide: 1440px)

2. GLOBALS CSS (src/styles/globals.css)
   - Import brand.css BEFORE Tailwind directives
   - Base layer: body background --bmj-black, color --bmj-cream, font --font-body
   - Headings: font-display, uppercase, letter-spacing 0.05em, color --bmj-white
   - Links: color --bmj-red, no underline, opacity hover
   - Selection: --bmj-red background, --bmj-white text
   - .grain::after pseudo-element for film grain overlay (fixed, full viewport, z-9999)
   - .halftone class for image treatment (contrast 1.2, grayscale 0.3, multiply blend)
   - .accent-border-top and .accent-border-bottom with 3px solid --bmj-red
   - Lens color utility classes: .lens-health, .lens-philosophy, .lens-politics

3. TAILWIND CONFIG (tailwind.config.ts)
   - Extend colors with bmj.black, bmj.cream, bmj.red, bmj.amber, bmj.brown, bmj.tan, bmj.white
   - Extend fontFamily with display, body, label, mono using CSS variables
   - Extend maxWidth with content, article, wide
   - Extend backgroundImage with grain texture

4. FONT LOADING (src/app/layout.tsx)
   - Load ALL 4 fonts via next/font/google: Bebas_Neue, Libre_Baskerville, Oswald, IBM_Plex_Mono
   - Subset to 'latin' for performance
   - Apply CSS variables to <html> element via className
   - Set up proper <html lang="en"> and viewport meta

5. ROOT LAYOUT (src/app/layout.tsx)
   - Import globals.css
   - Wrap children in a flex column min-h-screen structure
   - Include <Navbar /> at top, <Footer /> at bottom, {children} in flex-grow main
   - Apply .grain class to root container for global film grain overlay
   - Add Plausible analytics Script tag (commented out until domain is live)
   - Metadata export with default title "The Black Male Journal" and description

6. NAVBAR (src/components/layout/Navbar.tsx)
   - Client component (needs mobile menu state)
   - Logo/wordmark on the left (placeholder SVG until Chairman provides files)
   - Desktop nav links: Home, About, Academy, Resources, Video, Blog, Contact
   - "Resources" should be a dropdown or distinct item — NOT combined with articles
   - Active link indicator: red bottom border, 2px, on current route
   - Mobile: hamburger icon (lucide Menu/X), full-screen overlay menu
   - Background: --bmj-black with slight opacity on scroll (add scroll listener)
   - Sticky top, z-50
   - "JOIN" button on the right — bmj-red background, links to /signup
   - The entire navbar should feel like a newspaper masthead — bold, editorial, no-nonsense

7. MOBILE MENU (src/components/layout/MobileMenu.tsx)
   - Full viewport overlay, --bmj-black background
   - Large nav links stacked vertically, font-display, uppercase
   - Close button (X icon) top right
   - Framer Motion: slide in from right, fade overlay
   - Social links at bottom of mobile menu

8. FOOTER (src/components/layout/Footer.tsx)
   - Three column layout: Brand (logo + tagline), Navigation links, Connect (socials + newsletter)
   - Newsletter email signup input + "Subscribe" button (wired to API later)
   - Social media icons row (Instagram, YouTube, LinkedIn, Twitter/X — use lucide icons)
   - Support links: Patreon, PayPal, CashApp placeholders
   - Copyright line: "© 2026 The Black Male Journal. All rights reserved."
   - Legal links: Privacy Policy, Terms of Service
   - Red accent border on top of footer
   - Background slightly lighter than page: --bmj-brown

9. STAR DIVIDER (src/components/ui/StarDivider.tsx)
   - Horizontal rule replacement using the star motif
   - A thin line with a small red star centered in it
   - Use as section break throughout the site
   - SVG star icon, 16px, --bmj-red fill, centered on a 1px --bmj-tan line

10. GRAIN OVERLAY (src/components/ui/GrainOverlay.tsx)
    - Reusable component version of the .grain class
    - Can be applied per-section instead of globally if needed
    - Fixed position, pointer-events-none, z-9999

After planning all this, build every file. Make sure `npm run build` passes clean.
I want to see the site with the navbar, an empty main area, and the footer — all
perfectly styled in the BMJ brand — before we move on.

SESSION 2: HOME PAGE

/plan Build the Home page for The Black Male Journal.

This is Session 2. The design system, layout, navbar, and footer are done.
Now build the landing page that sets the tone for everything.

Reference: The IG posts at instagram.com/theblackmalejournal — dark backgrounds,
cream text, red accents, vintage propaganda poster energy. Every element should
feel like a printed document of historical record.

Build these sections top-to-bottom on src/app/page.tsx:

1. HERO BANNER (above the fold)
   - Full viewport height (100vh minus navbar)
   - Background: --bmj-black with subtle grain overlay
   - Large headline in Bebas Neue: "THE BLACK MALE JOURNAL" (or pull from a config)
   - Subheadline in Libre Baskerville: "Independent Media House · Revolutionary Masculinist Platform"
   - A short 2-3 sentence mission statement below in --bmj-cream
   - Subtle Framer Motion: headline fades up on load, subheadline follows 200ms later
   - Red horizontal accent line below the text block
   - "Read the Latest Briefing" CTA button — --bmj-red background, white text
   - Optional: the star logo mark large and centered behind the text at low opacity

2. THREE LENSES SECTION
   - Section heading: "THREE LENSES" in Oswald, tracking-wide
   - Three cards side-by-side (stacked on mobile):
     Card 1: Health 🫀 — "Body. Mind. Discipline." — brief description
     Card 2: Philosophy 🩷 — "Purpose. Identity. Truth." — brief description
     Card 3: Politics 🖤 — "Power. Systems. Community." — brief description
   - Each card: --bmj-brown background, cream text, red top border accent
   - Cards link to /articles?lens=[health|philosophy|politics]
   - Subtle hover: slight lift + border glow

3. LATEST WEEKEND BRIEFING PREVIEW
   - Section heading: "LATEST BRIEFING" with StarDivider above
   - Use the BriefingHeader component (already built or build now)
   - Show issue number, date, title
   - First 2-3 sentences of the briefing as preview text
   - "Read Full Briefing →" link in --bmj-red
   - This section has a slightly different background: --bmj-brown with paper texture feel
   - For now, use hardcoded placeholder data — we'll wire to Supabase in Session 3

4. FEATURED ARTICLES ROW
   - Section heading: "FEATURED" with StarDivider
   - 3-column grid showing one featured article per lens
   - ArticleCard component (build this now):
     - Cover image with halftone CSS treatment
     - Lens badge (colored dot + label)
     - Title in font-display
     - Excerpt (2 lines, truncated)
     - Reading time in font-mono, --bmj-tan color
     - Author: "The Chairman" in small text
   - Cards link to /articles/[slug]
   - Placeholder content for now — use realistic BMJ-voice titles

5. ROTATING QUOTE BLOCK
   - Centered section with --bmj-amber/cream background panel
   - Large quotation marks (decorative, in --bmj-red)
   - Quote text in Libre Baskerville italic, larger size
   - Attribution below the quote
   - Auto-rotates every 8 seconds with crossfade animation
   - 5 hardcoded quotes — themes: discipline, self-knowledge, resistance, purpose, legacy
   - Framer Motion AnimatePresence for smooth transitions

6. CTA / JOIN SECTION (above footer)
   - "JOIN THE MOVEMENT" headline in Bebas Neue
   - Brief paragraph about what members get
   - Two buttons side by side:
     "Subscribe Free" (outlined, links to /signup)
     "Go Premium" (filled --bmj-red, links to /signup?tier=premium)
   - Background: --bmj-black with red accent borders top and bottom

Every section should have generous vertical padding (py-16 to py-24).
Use StarDivider between sections where it feels natural.
Mobile responsive: everything stacks cleanly, hero text scales down,
cards go single column, quote block stays readable.

Build it all. Run `npm run build` at the end to verify.

SESSION 3: SUPABASE CLIENT + QUERY LAYER

/plan Set up the Supabase data layer for The Black Male Journal.

This is Session 3. Design system and home page are done with placeholder data.
Now build the database client and typed query helpers so every future page
can pull real content.

Assumes: Supabase project is created, schema from the Master Plan is already
run in the SQL editor, and .env.local has the Supabase URL + keys.

Build in this order:

1. SUPABASE BROWSER CLIENT (src/lib/supabase/client.ts)
   - createBrowserClient using @supabase/supabase-js
   - Uses NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY
   - Export a singleton instance

2. SUPABASE SERVER CLIENT (src/lib/supabase/server.ts)
   - createServerClient for use in Server Components and API routes
   - Uses cookies() from next/headers for auth session
   - This is the client most pages will use (Server Components by default)

3. MIDDLEWARE (src/middleware.ts)
   - Refreshes Supabase auth session on every request
   - Prevents stale sessions from breaking protected routes
   - Matcher config: exclude static files, images, favicon

4. TYPE DEFINITIONS (src/lib/supabase/types.ts)
   - TypeScript interfaces matching every table:
     Article, Briefing, Member, NewsletterSubscriber, ContactSubmission, Course
   - Lens type: 'health' | 'philosophy' | 'politics'
   - AccessTier type: 'free' | 'basic' | 'premium'
   - MemberTier type: 'free' | 'basic' | 'premium'
   - BriefingSection type: { title: string; body: string }

5. QUERY HELPERS (src/lib/supabase/queries.ts)
   - All functions use the server client by default
   - All functions are typed with return types

   Articles:
   - getArticles(options?: { lens?: Lens; tag?: string; limit?: number; offset?: number; tier?: AccessTier }) → Article[]
   - getArticleBySlug(slug: string) → Article | null
   - getFeaturedArticles(limit?: number) → Article[]
   - getLatestArticles(limit?: number) → Article[]

   Briefings:
   - getBriefings(options?: { limit?: number; offset?: number }) → Briefing[]
   - getBriefingBySlug(slug: string) → Briefing | null
   - getLatestBriefing() → Briefing | null
   - getBriefingByIssue(issueNumber: number) → Briefing | null

   Members:
   - getMemberById(userId: string) → Member | null
   - getMemberByEmail(email: string) → Member | null
   - updateMemberTier(userId: string, tier: MemberTier, stripeData?: { customerId: string; subscriptionId: string }) → void

   Courses:
   - getCourses(options?: { category?: string; published?: boolean }) → Course[]
   - getCourseBySlug(slug: string) → Course | null

   Newsletter:
   - subscribeToNewsletter(email: string, source?: string) → void
   - unsubscribeFromNewsletter(email: string) → void

   Contact:
   - submitContactForm(data: { name: string; email: string; subject?: string; message: string }) → void

6. UTILITY HELPERS (src/lib/utils.ts)
   - cn() function using clsx + tailwind-merge for conditional class names
   - formatDate(date: string | Date) → string (e.g., "MARCH 15, 2026")
   - generateSlug(title: string) → string
   - truncateText(text: string, maxLength: number) → string
   - calculateReadingTime(text: string) → number (minutes)
   - getLensColor(lens: Lens) → string (returns the CSS class)
   - getLensEmoji(lens: Lens) → string (returns 🫀, 🩷, or 🖤)

7. SEED SCRIPT (scripts/seed.ts)
   - Run with: npx tsx scripts/seed.ts
   - Inserts 9 articles (3 per lens), mix of free/basic/premium
   - Inserts 3 Weekend Briefings (issues 1-3)
   - Inserts 5 courses across categories
   - Content should sound like it belongs on the BMJ — strong, direct,
     historically grounded. Reference real themes: stoicism, physical training,
     political organizing, mental resilience, community building, Black history.
   - 2 articles marked as featured
   - Use realistic titles like:
     "The Discipline of Iron: Why Every Man Needs a Physical Practice"
     "Marcus Aurelius Had It Right: Stoic Principles for the Modern Black Man"
     "Understanding Power: A Framework for Community Organizing"

8. UPDATE HOME PAGE
   - Replace all placeholder/hardcoded data on page.tsx with real Supabase queries
   - Latest briefing section pulls from getLatestBriefing()
   - Featured articles pull from getFeaturedArticles(3)
   - If no data exists yet, show graceful empty states (not broken page)

After building everything, run the seed script and verify the home page
renders with real data. Then run `npm run build` to confirm clean build.

SESSION 4: ARTICLES SYSTEM

/plan Build the complete articles system for The Black Male Journal.

This is Session 4. Design system, home page, and Supabase data layer are done.
Seed data is in the database. Now build the article browsing and reading experience.

This is a content-first platform — articles are the core product. The reading
experience must feel like a beautifully typeset magazine, not a blog.

Build these:

1. ARTICLE ARCHIVE PAGE (src/app/(public)/articles/page.tsx)
   - Server Component — fetches articles on the server
   - Page title: "ARTICLES" in Bebas Neue, with StarDivider below
   - LENS FILTER TABS at the top:
     [All] [Health 🫀] [Philosophy 🩷] [Politics 🖤]
     - "All" selected by default
     - Tabs styled as editorial labels: font-label (Oswald), uppercase, tracking-wide
     - Active tab: --bmj-red bottom border, --bmj-white text
     - Inactive: --bmj-tan text, no border
     - Use URL search params for filter state (?lens=health) so it's shareable/bookmarkable
   - TAG FILTER: horizontal scrollable row of tag pills below lens tabs
     - Pills: small, --bmj-brown background, --bmj-cream text, rounded-sm (max 4px!)
     - Active tag: --bmj-red background
   - ARTICLE GRID: 3 columns desktop, 2 tablet, 1 mobile
     - Uses ArticleCard component from Session 2
     - Cards show: cover image (halftone), lens badge, title, excerpt (2 lines), reading time, date
     - Premium articles show a small lock icon on the card
   - PAGINATION: "Load More" button at bottom (not numbered pages — feels more editorial)
     - Loads 9 articles at a time
   - EMPTY STATE: if no articles match the filter, show "No articles found" with suggestion to try another lens

2. INDIVIDUAL ARTICLE PAGE (src/app/(public)/articles/[slug]/page.tsx)
   - Server Component with generateMetadata for SEO
   - Fetch article by slug — if not found, return notFound()
   - ARTICLE HEADER:
     - Lens badge at top (e.g., "HEALTH" in red)
     - Title in Bebas Neue, large (text-4xl to text-6xl responsive)
     - Subtitle/excerpt in Libre Baskerville italic, --bmj-tan
     - Author: "By The Chairman" in font-label
     - Date + reading time in font-mono, --bmj-tan
     - Cover image: full width, halftone treatment, max-height constraint
     - Red accent border below header
   - ARTICLE BODY:
     - Max-width: 720px, centered (--max-article)
     - Rendered from MDX or markdown body field
     - Typography: Libre Baskerville, 18px, 1.8 line-height, --bmj-cream
     - Headings within article: Bebas Neue, --bmj-white
     - Block quotes: left border --bmj-red, italic, --bmj-amber background panel
     - Code blocks: font-mono, --bmj-brown background
     - Images: full article width, halftone treatment
     - Links: --bmj-red, underline on hover
   - PAYWALL GATE (src/components/content/PaywallGate.tsx):
     - If article.access_tier !== 'free' AND user is not logged in or tier is insufficient:
       Show first ~300 characters of body text
       Then blur/fade overlay gradient
       CTA card: "This article is for [Basic/Premium] members"
       "Subscribe" button → /signup?tier=[required tier]
       "Already a member? Log in" link → /login
     - If user has correct tier: show full article, no gate
   - SIDEBAR or BOTTOM SECTION:
     - "More from [lens]" — 3 related article cards
     - Share buttons (copy link, Twitter/X)
   - BACK LINK: "← Back to Articles" at top

3. ARTICLE CARD COMPONENT (update src/components/content/ArticleCard.tsx if needed)
   - Make sure it handles:
     - Missing cover image (show gradient placeholder with lens color)
     - Long titles (truncate at 2 lines)
     - Premium indicator (small lock icon)
     - Hover state: subtle lift, border color change
     - Responsive: card scales properly at all breakpoints

4. LENS BADGE COMPONENT (src/components/brand/LensBadge.tsx)
   - Small pill-style badge (rounded-sm, NOT rounded-full)
   - Color coded: health = --bmj-red, philosophy = --bmj-amber, politics = --bmj-white on --bmj-brown
   - Uppercase, font-label, small text, tracking-wide
   - Used on ArticleCard, article page header, and filter tabs

5. SEO for articles:
   - generateMetadata in [slug]/page.tsx:
     title: "[Article Title] | The Black Male Journal"
     description: article.excerpt
     openGraph: title, description, image (cover_image or default OG)
     twitter: card = "summary_large_image"

Build everything. Seed data should populate the archive. Test the lens filters.
Test the paywall gate with a premium article (should show blurred content for
non-logged-in users). Run `npm run build`.

SESSION 5: WEEKEND BRIEFING SYSTEM

/plan Build the Weekend Briefing system for The Black Male Journal.

This is Session 5. The Weekend Briefing is the FLAGSHIP content format — it gets
special design treatment. Think of it as the front page of a revolutionary newspaper.
Every briefing should feel like a printed pamphlet you'd find at a movement meeting.

Reference the IG posts: "WEEKEND BRIEFING" header with red book icon, date in
monospace, clean sectioned layout.

Build these:

1. BRIEFING ARCHIVE PAGE (src/app/(public)/briefing/page.tsx)
   - Server Component
   - Page title: "WEEKEND BRIEFING" in Bebas Neue with the red book icon from BriefingHeader
   - Subtitle: "A weekly dispatch on the politics, philosophy, and health of the Black male experience."
   - BRIEFING LIST: vertical stack, not a grid — each entry is a wide editorial card:
     - Issue number (font-mono, --bmj-tan): "No. 001"
     - Date (font-mono): "MARCH 8, 2026"
     - Title in font-display, large
     - First section title as preview text
     - Access tier badge if not free (lock icon)
     - Red left border accent on each card
   - Reverse chronological order (newest first)
   - "Load More" pagination
   - Empty state if no briefings

2. INDIVIDUAL BRIEFING PAGE (src/app/(public)/briefing/[slug]/page.tsx)
   - Server Component with generateMetadata
   - BRIEFING HEADER (use BriefingHeader component):
     - Red book icon + "WEEKEND BRIEFING" in Oswald
     - Date in IBM Plex Mono
     - Issue number: "No. 003"
   - BRIEFING TITLE: Bebas Neue, large, --bmj-white
   - Cover image if available: full width with halftone treatment
   - SECTIONS:
     - Each section from the sections JSONB array rendered as a distinct editorial block
     - Section title: Bebas Neue, --bmj-white, with red accent border above
     - Section body: Libre Baskerville, comfortable reading width (720px)
     - StarDivider between sections
     - Sections should feel like distinct newspaper columns — clear visual separation
   - PAYWALL: same PaywallGate logic as articles
     - Free briefings: show all sections
     - Premium briefings: show first section only, then paywall gate
   - NAVIGATION: "← Previous Issue" and "Next Issue →" links at bottom
   - SHARE: copy link button

3. BRIEFING CARD COMPONENT (src/components/content/BriefingCard.tsx)
   - For use on the archive page and home page
   - Shows: issue number, date, title, preview text, tier badge
   - Distinct from ArticleCard — wider format, more editorial feel
   - Red left border accent
   - Hover: subtle background shift

4. SEO for briefings:
   - generateMetadata: title includes issue number
   - OG image: cover_image or default

5. UPDATE HOME PAGE:
   - Wire the "Latest Briefing" section to use BriefingCard with real data
   - Link to the full briefing page

Build all of it. Test with seed briefing data. Verify premium briefings
show the paywall correctly. Run `npm run build`.

SESSION 6: ACADEMY PAGE

/plan Build the Academy page for The Black Male Journal.

This is Session 6. Academy is the structured learning hub — martial arts,
mental health, relationships, purpose, branding. It's distinct from Resources
(which is passive reference). Academy = active learning paths.

Keep it simple for v1 — course cards grid with descriptions. Video content
and full course pages come later.

Build:

1. ACADEMY PAGE (src/app/(public)/academy/page.tsx)
   - Page title: "THE ACADEMY" in Bebas Neue
   - Subtitle: "Structured learning for the disciplined man. Master your body, mind, and mission."
   - CATEGORY FILTER (optional for v1 — can just show all):
     [All] [Martial Arts] [Mental Health] [Relationships] [Purpose] [Branding]
   - COURSE GRID: 3 columns desktop, 2 tablet, 1 mobile

2. COURSE CARD (src/components/content/CourseCard.tsx)
   - Thumbnail/image area with category color accent
   - Category badge (like lens badge but for course categories)
   - Course title in font-display
   - Description (2-3 lines)
   - Access tier: "FREE" in --bmj-cream or "PREMIUM 🔒" in --bmj-amber
   - Subtle: "Coming Soon" state for courses not yet published
   - Links to individual course page (placeholder for now)

3. INDIVIDUAL COURSE PAGE (src/app/(public)/academy/[slug]/page.tsx)
   - Placeholder for now — title, description, "Content coming soon" message
   - Will eventually hold embedded video lessons

4. Seed data should populate courses. Run `npm run build`.

SESSION 7: VIDEO GALLERY

/plan Build the Video Gallery page pulling from YouTube.

This is Session 7. This page showcases the Chairman's YouTube content
directly on the BMJ site.

Build:

1. VIDEO PAGE (src/app/(public)/video/page.tsx)
   - Page title: "VIDEO" in Bebas Neue
   - Subtitle: "Watch. Learn. Build."
   - Grid: 3 columns desktop, 2 tablet, 1 mobile

2. YOUTUBE INTEGRATION:
   - Option A (simpler): Hardcoded video list in a config file (src/lib/content/videos.ts)
     with title, youtube_id, thumbnail URL, publish date, description
   - Option B (dynamic): Fetch from YouTube RSS feed at build time (ISR)
     Feed URL: https://www.youtube.com/feeds/videos.xml?channel_id=[CHANNEL_ID]
   - For now, use Option A with 6-9 placeholder entries. We'll switch to dynamic later.

3. VIDEO CARD (src/components/content/VideoCard.tsx)
   - YouTube thumbnail image
   - Play button overlay (red circle with white triangle, centered)
   - Title below in font-display
   - Date in font-mono, --bmj-tan
   - Click opens a modal with YouTube embed OR navigates to detail page

4. VIDEO MODAL or DETAIL PAGE:
   - Responsive YouTube iframe embed (16:9 aspect ratio)
   - Title and description below
   - "More Videos" section

Build it. Run `npm run build`.

SESSION 8: BLOG

/plan Build the Blog section for The Black Male Journal.

This is Session 8. Blog is for shorter posts, updates, announcements,
and commentary. Lighter weight than full articles — think quick dispatches.

For v1, blog posts can live in the articles table with a "blog" type flag,
or as a separate content type. Your call on architecture — tell me your plan
and I'll approve before you build.

Build:

1. BLOG PAGE (src/app/(public)/blog/page.tsx)
   - Page title: "DISPATCHES" (more on-brand than "Blog")
   - Chronological feed, newest first
   - Simpler cards than articles: title, date, excerpt, lens tag
   - No cover images required (but supported)
   - Paginated: "Older Posts →" link

2. INDIVIDUAL BLOG POST (src/app/(public)/blog/[slug]/page.tsx)
   - Simpler layout than full articles
   - Title, date, lens badge, body text
   - No sidebar, no related posts (keep it clean)
   - Share link at bottom

3. Build and verify. Run `npm run build`.

SESSION 9: AUTHENTICATION + MEMBER PORTAL

/plan Build the authentication system and member portal for The Black Male Journal.

This is Session 9. This unlocks the paid tier system — members log in,
see their dashboard, access premium content.

Build:

1. AUTH PAGES:
   - LOGIN (src/app/(auth)/login/page.tsx):
     - Email + password form
     - "Or sign in with magic link" option
     - Link to signup: "Don't have an account? Join the movement →"
     - Styled in BMJ brand — NOT default white auth forms
     - Dark background, cream text, red accent button
   - SIGNUP (src/app/(auth)/signup/page.tsx):
     - Name, email, password fields
     - Optional: tier selection if ?tier= query param is present
     - "Create Account" button in --bmj-red
     - Link to login: "Already a member? Log in →"
   - Supabase Auth handles the actual auth — these are just the UI

2. AUTH UTILITIES:
   - src/lib/supabase/auth.ts:
     - signUp(email, password, displayName)
     - signIn(email, password)
     - signInWithMagicLink(email)
     - signOut()
     - getSession() — returns current user session
     - getUser() — returns current user or null
   - Middleware already refreshes sessions (built in Session 3)

3. MEMBER PORTAL DASHBOARD (src/app/(auth)/portal/page.tsx)
   - Protected route — redirect to /login if not authenticated
   - Welcome: "Welcome back, [name or email]"
   - TIER BADGE (src/components/portal/TierBadge.tsx):
     - Visual indicator: FREE (--bmj-tan), BASIC (--bmj-amber), PREMIUM (--bmj-red)
     - Styled like a membership card or credential
   - QUICK STATS: member since date, current tier, subscription status
   - CONTENT SECTIONS:
     - "Your Access" — what the current tier unlocks
     - "Premium Content" — teaser cards for content above current tier with upgrade CTA
     - "Latest for You" — recent content within their tier
   - NAVIGATION: links to Handbooks, Settings, and Manage Subscription
   - The portal should feel exclusive — slightly different background
     treatment, more refined typography

4. MEMBER SETTINGS (src/app/(auth)/portal/settings/page.tsx)
   - Display name edit
   - Email (read-only, shows current)
   - Change password
   - "Manage Subscription" button → Stripe billing portal (built in Session 10)
   - "Log Out" button

5. AUTH-AWARE NAVBAR UPDATE:
   - If logged in: replace "JOIN" button with user avatar/initial + dropdown
   - Dropdown: Portal, Settings, Log Out
   - If not logged in: show "JOIN" and "LOG IN" buttons

6. AUTH-AWARE CONTENT:
   - Update PaywallGate to check actual user session and tier
   - If logged in with sufficient tier → show content
   - If logged in with insufficient tier → show upgrade prompt
   - If not logged in → show login/signup prompt

Build everything. Test: sign up → log in → see portal → log out → see paywall.
Run `npm run build`.

SESSION 10: STRIPE SUBSCRIPTIONS

/plan Build the Stripe subscription and payment system for The Black Male Journal.

This is Session 10. This is how the platform makes money. Get it right.

Assumes: Stripe account exists, products and prices created in Stripe dashboard,
keys in .env.local.

Build:

1. STRIPE CONFIG (src/lib/stripe/config.ts)
   - Stripe instance initialized with STRIPE_SECRET_KEY
   - Tier-to-price mapping:
     basic: STRIPE_BASIC_PRICE_ID
     premium: STRIPE_PREMIUM_PRICE_ID
   - Helper: getTierFromPriceId(priceId) → 'basic' | 'premium'

2. STRIPE HELPERS (src/lib/stripe/helpers.ts)
   - createCheckoutSession(userId, userEmail, tier) → returns session URL
     - mode: 'subscription'
     - success_url: /portal?checkout=success
     - cancel_url: /portal?checkout=cancelled
     - customer_email: userEmail
     - metadata: { userId, tier }
   - createBillingPortalSession(stripeCustomerId) → returns portal URL
     - For managing/canceling subscriptions
   - getSubscriptionStatus(subscriptionId) → active | canceled | past_due | etc.

3. CHECKOUT API ROUTE (src/app/api/stripe/checkout/route.ts)
   - POST handler
   - Validates: user must be authenticated
   - Creates Stripe Checkout session for the requested tier
   - Returns { url: session.url } for redirect

4. WEBHOOK HANDLER (src/app/api/stripe/webhook/route.ts)
   - POST handler, verifies Stripe signature using STRIPE_WEBHOOK_SECRET
   - Handles these events:
     checkout.session.completed → create/update member tier, store stripe_customer_id and stripe_subscription_id
     customer.subscription.updated → update tier if plan changed
     customer.subscription.deleted → downgrade member to 'free'
     invoice.payment_failed → (optional) send warning email or flag account
   - Each event handler updates the members table in Supabase via service role client
   - Log all events for debugging

5. SUBSCRIPTION UI:
   - PRICING SECTION (can live on home page or a dedicated /pricing page):
     - Two tier cards side by side: Basic ($X/mo) and Premium ($X/mo)
     - Feature comparison list for each tier
     - "Subscribe" buttons that hit the checkout API
     - "Current Plan" badge if user is on that tier
   - SUBSCRIPTION MANAGER (src/components/portal/SubscriptionManager.tsx):
     - Shows current plan and billing cycle
     - "Manage Billing" button → Stripe billing portal
     - "Upgrade" button if on Basic
     - "Cancel" indication (handled via Stripe portal)
   - Update portal page to include SubscriptionManager

6. UPGRADE FLOW:
   - User clicks "Go Premium" anywhere on site
   - If not logged in → redirect to /signup?tier=premium
   - If logged in → POST to /api/stripe/checkout with tier
   - Redirect to Stripe Checkout
   - On success → webhook fires → tier updated → redirect to portal
   - Portal shows "Welcome to Premium!" message if ?checkout=success

Build and test the full flow. Use Stripe test mode. Verify webhook
updates the database correctly. Run `npm run build`.

SESSION 11: CONTACT + NEWSLETTER

/plan Build the Contact page and newsletter system for The Black Male Journal.

Session 11. Communication channels — how people reach the Chairman and
join the mailing list.

Build:

1. CONTACT PAGE (src/app/(public)/contact/page.tsx)
   - Page title: "CONNECT" in Bebas Neue
   - Two-column layout (stacked on mobile):
     LEFT: Contact form (name, email, subject dropdown, message textarea)
     RIGHT: Direct contact info
       - Email: chairman@blackmalejournal.com
       - WhatsApp: link to dedicated number (wa.me/[number])
       - Social links: IG, YouTube, LinkedIn, X
       - Support: Patreon, PayPal, CashApp links
   - Form submits to /api/contact which uses Resend to send email
   - Success toast: "Message sent. The Chairman will respond."
   - Error handling with user-friendly messages

2. CONTACT API (src/app/api/contact/route.ts)
   - Validates input with Zod schema
   - Sends email via Resend to chairman@blackmalejournal.com
   - Also inserts into contact_submissions table
   - Rate limiting: basic check to prevent spam (optional for v1)

3. NEWSLETTER SIGNUP (src/app/api/newsletter/subscribe/route.ts)
   - POST handler: takes email, validates, inserts into newsletter_subscribers
   - Duplicate email handling (upsert or friendly error)
   - Optional: send welcome email via Resend
   - Returns success/error JSON

4. NEWSLETTER COMPONENTS:
   - Inline signup form (email input + submit button) — used in Footer and CTA sections
   - Full signup page at /newsletter (optional) or modal
   - Style: --bmj-red submit button, dark input field with cream text/placeholder

5. UPDATE FOOTER: wire the newsletter signup form to the actual API endpoint.

Build and test. Verify emails send via Resend. Run `npm run build`.

SESSION 12: LEGAL PAGES

/plan Build the Privacy Policy and Terms of Service pages.

Session 12. Required before collecting any data or payments.

Build:

1. PRIVACY POLICY (src/app/(public)/privacy/page.tsx)
   - Styled as an editorial document — NOT boilerplate legalese
   - Sections: what data we collect, how we use it, email communications,
     payment processing (Stripe), analytics (Plausible), third-party services,
     data retention, your rights, contact for privacy concerns
   - Last updated date at top

2. TERMS OF SERVICE (src/app/(public)/terms/page.tsx)
   - Sections: account terms, subscription and billing, content ownership,
     acceptable use, termination, disclaimers, contact
   - Reference Stripe for payment terms

3. Both pages: max-width 720px, comfortable reading typography,
   proper heading hierarchy, BMJ brand styling throughout.

4. UPDATE FOOTER: link to both pages.

Build. Run `npm run build`.

SESSION 13: SEO + PERFORMANCE

/plan Comprehensive SEO and performance optimization.

Session 13. Make sure Google and social platforms see the site properly.

Build:

1. METADATA FRAMEWORK:
   - Root layout: default metadata (title template, description, OG image)
   - Every page: generateMetadata with page-specific title and description
   - Articles: dynamic OG with title, excerpt, cover image
   - Briefings: dynamic OG with issue number and title

2. SITEMAP (src/app/sitemap.ts)
   - Dynamic sitemap.xml generated at build time
   - Includes all public pages, articles, briefings, courses
   - Proper lastmod dates, changefreq, priority

3. ROBOTS (src/app/robots.ts)
   - Allow all crawlers
   - Point to sitemap URL

4. STRUCTURED DATA:
   - JSON-LD on article pages: Article schema (headline, author, datePublished, image, publisher)
   - JSON-LD on root layout: Organization schema (name, url, logo, sameAs social URLs)

5. PERFORMANCE:
   - Verify all images use next/image with proper sizes/priority
   - Lazy load below-fold images
   - Font display: swap on all Google Fonts
   - Check bundle size with `npx next build` — flag any page over 200kb JS

6. ACCESSIBILITY:
   - Proper heading hierarchy (h1 → h2 → h3, no skips)
   - Alt text on all images
   - Keyboard navigable menu
   - Focus visible styles using --bmj-red ring
   - ARIA labels on icon-only buttons

Build. Final `npm run build`. Run Lighthouse if possible.

SESSION 14: DEPLOY TO PRODUCTION

/plan Final pre-deployment checklist and Vercel production deploy.

Session 14. The last session. Make it count.

Do these in order:

1. PRE-DEPLOY AUDIT:
   - Run /project:deploy-check (types + lint + build)
   - Run /project:brand-check (no off-brand colors/fonts)
   - Verify every page renders at 375px mobile and 1440px desktop
   - Check all internal links work (no 404s)
   - Verify PaywallGate works for premium content
   - Verify Stripe checkout flow in test mode
   - Verify contact form sends email
   - Verify newsletter signup works

2. ENVIRONMENT CHECK:
   - List all required env vars
   - Verify they're set in Vercel Dashboard (Production + Preview)
   - Double check NEXT_PUBLIC_ prefix on client-side vars

3. FINAL FILES:
   - .gitignore includes: .env.local, node_modules, .next, .vercel
   - README.md with project overview and setup instructions
   - No console.log() statements left in production code
   - No TODO comments that block functionality

4. DEPLOY:
   - git add . && git commit -m "feat: production ready v1.0"
   - git push origin main
   - Verify Vercel auto-deploys (or run vercel --prod)
   - Check production URL loads correctly

5. POST-DEPLOY:
   - Add custom domain in Vercel if not done
   - Verify SSL certificate provisioned
   - Set Stripe webhook URL to production domain
   - Test one full flow: visit site → browse → sign up → subscribe → access premium
   - Submit sitemap to Google Search Console

Report the final status. We're live.

BONUS: AD-HOC PROMPT TEMPLATES

Use these anytime during development for one-off tasks:

Fix a bug

There's a [describe bug] on [page/component]. Here's what I expect vs what's
happening. Look at [file path] and fix it. Run the build after to make sure
nothing else broke.

Add a new feature

/plan Add [feature description] to [page or component]. It should match the
BMJ brand system from CLAUDE.md. Here's exactly what I want: [details].
Build it, then run /project:deploy-check.

Content update

/project:new-article
[then follow the prompts to create a new article]

Refactor

/review src/[file path]
[Claude reviews the code, then:]
Apply the improvements you suggested. Keep all existing functionality. Run build after.

Check brand compliance

/project:brand-check
[Claude audits everything, then:]
Fix all the violations you found. Show me what you changed.

These prompts are designed for Claude Code CLI with the BMJ Master Plan v2.0. Each session builds on the previous. Don't skip sessions. Don't rush. Trust the /plan → review → build → verify cycle.