Skip to content

[codex] Refresh Frontier AI Governance lander#2241

Merged
somepersonnamedjosh merged 1 commit into
masterfrom
codex/faigc-lander-updates
Apr 5, 2026
Merged

[codex] Refresh Frontier AI Governance lander#2241
somepersonnamedjosh merged 1 commit into
masterfrom
codex/faigc-lander-updates

Conversation

@somepersonnamedjosh

Copy link
Copy Markdown
Collaborator

Summary

  • refresh the Frontier AI Governance lander copy, section ordering, nav labels, and unit-linked curriculum cards
  • add the compact stacked "Help build the field" section and shared placement hooks needed to support the new FAIGC flow
  • update shared lander text/snapshots affected by the alumni count and shared component rendering changes

Validation

  • cd apps/website && npm test
  • npm audit --audit-level=high --omit=dev
  • manual secret-pattern scan over the committed diff

Security notes

  • npm audit reports existing vulnerabilities in the repo dependency tree, including critical/high advisories in fast-xml-parser, happy-dom, next, @trpc/server, axios, and parts of the AWS SDK tree
  • no secret-like strings were detected in the committed FAIGC diff

Notes

  • this PR is draft because the repo currently has pre-existing dependency audit findings that are unrelated to the FAIGC changes
  • gh auth status is currently invalid in the local environment, so the PR was opened through the GitHub connector instead of the CLI

@coderabbitai

coderabbitai Bot commented Apr 5, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

This pull request extends the course landing page system with flexible section placement and ordering capabilities. The CourseLanderContent type gains optional properties to control the placement of course outcomes and testimonials sections, and introduces a new fieldBuilding section. A new FieldBuildingSection component is added to render role-based content with descriptions and links. The CourseOutcome type now supports optional link URLs and text. The PathwaysSection types are updated to accept ReactNode instead of string for richer content, with an additional callout prop. The AI Governance course landing page content is substantially updated with revised course duration, restructured outcomes, expanded pathways, new field building roles, and updated FAQ entries.

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is largely incomplete against the required template; it lacks the Description section explaining reasoning, omits the Issue/Fixes reference, and provides no screenshots for visual changes. Complete the Description section with rationale, add the Issue/Fixes field, include before/after screenshots for visual changes, and fill out the Developer checklist as appropriate.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: refreshing the Frontier AI Governance course lander with updated content and components.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/faigc-lander-updates

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@render render Bot temporarily deployed to codex/faigc-lander-updates - bluedot-preview PR #2241 April 5, 2026 01:19 Destroyed
@somepersonnamedjosh

Copy link
Copy Markdown
Collaborator Author

@claude review please

@claude

claude Bot commented Apr 5, 2026

Copy link
Copy Markdown

Claude finished @somepersonnamedjosh's task —— View job


Code Review: Frontier AI Governance lander updates

Todo List:

  • Read repository guidelines (CLAUDE.md)
  • Review new FieldBuildingSection component
  • Examine modifications to existing lander components
  • Check CourseOutcomesSection and PathwaysSection changes
  • Review AiGovernanceContent updates
  • Verify snapshot updates are appropriate
  • Check for TypeScript/React best practices
  • Provide comprehensive review feedback

Overall Assessment

This is a well-structured PR that refreshes the Frontier AI Governance course lander with improved content organization and new functionality. The changes are primarily content updates and component enhancements, with good attention to TypeScript typing and React best practices.

✅ Strengths

New FieldBuildingSection Component

  • Clean, reusable design: Well-structured component with proper TypeScript interfaces
  • Accessibility: Uses aria-hidden="true" for decorative arrow icons
  • Responsive design: Comprehensive responsive styling with proper breakpoints
  • Good separation of concerns: Props interface clearly defines component API

Enhanced Component Flexibility

  • CourseOutcomesSection: Added optional link functionality (linkUrl/linkText) with proper fallback
  • PathwaysSection: Enhanced to accept ReactNode instead of just strings for descriptions, adds callout prop
  • Consistent styling: New components follow established design patterns

Content Updates

  • Updated alumni count: 6,000+ → 7,000+ in GraduateSection.tsx:27
  • Comprehensive curriculum: Detailed course structure with 6 units, each with clear learning objectives
  • Professional navigation: Updated section nav with relevant labels including "Teach with us"

⚠️ Areas for Improvement

1. Missing Import Validation

The new FieldBuildingSection component is imported in CourseLander.tsx:23 but should verify all its dependencies are properly typed:

// FieldBuildingSection.tsx
import Link from 'next/link';  // ✅ Used properly

2. Snapshot Updates

The snapshot changes look legitimate (alumni count update reflected properly), but consider:

  • Are all snapshot updates actually necessary?
  • The home page snapshot shows "7,000+" which matches the GraduateSection change

3. Component Consistency

In PathwaysSection.tsx:65, there's a mix of semantic HTML and custom styling:

<h3 className="...">  // Could use H3 from @bluedot/ui for consistency

4. Type Safety Enhancement

Consider stricter typing for the field building roles:

export type FieldBuildingRole = {
  title: string;
  description: React.ReactNode;
  linkText: string;
  linkUrl: string; // Could validate URL format
};

🔍 Detailed Code Analysis

apps/website/src/components/lander/components/FieldBuildingSection.tsx

  • Lines 36-63: Excellent responsive design with proper overflow handling
  • Lines 50-57: Good use of Next.js Link with proper hover states
  • Line 60: Smart divider logic (index < roles.length - 1)

apps/website/src/components/lander/CourseLander.tsx

  • Lines 240-245: Proper conditional rendering and placement of new FieldBuildingSection
  • Line 243: Good use of semantic ID help-build-field

AiGovernanceContent.tsx (Extensive Updates)

  • Lines 44-50: Updated navigation structure with relevant sections
  • Lines 129-187: Comprehensive course outcomes with proper unit linking
  • External links: Proper use of target="_blank" and rel="noopener noreferrer"

🚀 Performance Considerations

  • Bundle size: No significant impact from new component
  • Image loading: All images use proper alt text and fetchpriority
  • React rendering: Proper key props in map functions

🔒 Security Notes

  • External links: Properly secured with rel="noopener noreferrer"
  • No XSS vulnerabilities: All user content properly typed as ReactNode
  • URL validation: Direct string URLs (could be enhanced with validation)

📝 Recommendations

  1. Add URL validation for FieldBuildingRole.linkUrl
  2. Consider using H3 component consistently in PathwaysSection
  3. Add unit tests for the new FieldBuildingSection component
  4. Document the placement strategy for the fieldBuilding section in component docs

✅ Final Verdict

This is a high-quality PR that enhances the Frontier AI Governance lander with:

  • Well-architected new components
  • Proper TypeScript typing
  • Consistent design patterns
  • Comprehensive content updates
  • Good accessibility practices

The changes are ready for merge after addressing the minor consistency suggestions above.
| Branch: codex/faigc-lander-updates

@somepersonnamedjosh somepersonnamedjosh marked this pull request as ready for review April 5, 2026 01:24
@greptile-apps

greptile-apps Bot commented Apr 5, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR refreshes the Frontier AI Governance course lander with updated copy, reordered sections, and unit-linked curriculum cards. It also introduces a new FieldBuildingSection component and two placement-override props (courseOutcomesPlacement, testimonialsPlacement) on CourseLander to give per-lander control over section ordering without restructuring the shared layout component.

  • New FieldBuildingSection renders a compact stacked table of teaching/facilitation roles, each with a title, description, and mailto: CTA
  • courseOutcomesPlacement: 'beforeStructure' moves the outcomes grid to after alumni stories and before "How it works" on the FAIGC lander
  • testimonialsPlacement: 'beforeOutcomes' surfaces testimonials right after the Personas section on the FAIGC lander
  • Alumni count updated from 6,000+ to 7,000+ in the shared GraduateSection and affected snapshots
  • No Storybook stories or unit tests were added for FieldBuildingSection, and CourseOutcomesSection gained new per-card link functionality without any test coverage

Confidence Score: 4/5

Safe to merge; changes are content-heavy with well-scoped, low-risk layout refactoring

The placement-override logic uses mutually exclusive boolean checks that are straightforward to reason about, and existing snapshot tests confirm shared components render correctly. Score is 4 rather than 5 because the new FieldBuildingSection component and the modified CourseOutcomesSection link-rendering path have no automated test coverage.

apps/website/src/components/lander/components/FieldBuildingSection.tsx and apps/website/src/components/lander/components/CourseOutcomesSection.tsx lack test coverage

Important Files Changed

Filename Overview
apps/website/src/components/lander/components/FieldBuildingSection.tsx New compact stacked 'Help build the field' section component — no tests or Storybook stories present
apps/website/src/components/lander/CourseLander.tsx Adds optional placement overrides for testimonials and course-outcomes sections, extracts testimonials into a reusable variable, and wires in the new FieldBuildingSection
apps/website/src/components/lander/course-content/AiGovernanceContent.tsx Rewrites FAIGC lander content with new personas, six unit-linked curriculum cards, detailed pathways, and a field-building teaching section
apps/website/src/components/lander/components/CourseOutcomesSection.tsx Adds optional linkUrl/linkText to CourseOutcome type and renders per-card navigation links — no test coverage for new paths
apps/website/src/components/lander/components/PathwaysSection.tsx Minor read — no logic changes in this PR; pre-existing component used by FAIGC content
apps/website/src/components/lander/components/GraduateSection.tsx Updates alumni count from 6,000+ to 7,000+
apps/website/src/components/homepage/snapshots/HomeHeroContent.test.tsx.snap Snapshot updated to reflect the 7,000+ alumni count change in GraduateSection
apps/website/src/components/lander/snapshots/AgiStrategyLander.test.tsx.snap Snapshot updated to reflect shared component rendering changes
apps/website/src/components/lander/snapshots/FutureOfAiLander.test.tsx.snap Snapshot updated to reflect shared component rendering changes

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[CourseLander entry] --> B[HeroSection]
    B --> C{alumniLogos?}
    C -->|yes| D[AlumniLogosSection]
    C -->|no| E[GraduateSection]
    D & E --> F{personas?}
    F -->|yes| G[PersonasSection]
    F -->|no| H[WhoIsThisForSection?]
    G & H --> J{testimonialsPlacement\n=== 'beforeOutcomes'?}
    J -->|yes| K[TestimonialCarousel — early]
    J -->|no| L[skip]
    K & L --> M{courseOutcomes AND\nplacement != 'beforeStructure'?}
    M -->|yes| N[CourseOutcomesSection — default]
    M -->|no| O[skip]
    N & O --> P[PathwaysSection?]
    P --> Q[CourseBenefitsSection?]
    Q --> R[PrerequisitesSection?]
    R --> S[AlumniStoryCarousel?]
    S --> T[CaseStudiesSection?]
    T --> U{courseOutcomes AND\nplacement === 'beforeStructure'?}
    U -->|yes| V[CourseOutcomesSection — late]
    U -->|no| W[skip]
    V & W --> X[CourseInformationSection?]
    X --> Y{testimonialsPlacement\n!== 'beforeOutcomes'?}
    Y -->|yes| Z[TestimonialCarousel — default]
    Y -->|no| AA[skip]
    Z & AA --> AB[QuoteSection?]
    AB --> AC[PartnerSection?]
    AC --> AD[FieldBuildingSection? ← NEW]
    AD --> AE[FAQSection?]
    AE --> AF[LandingBanner]
Loading

Reviews (1): Last reviewed commit: "feat(website): refresh frontier ai gover..." | Re-trigger Greptile

Comment on lines +18 to +67
const FieldBuildingSection = ({
id,
title,
intro,
roles,
}: FieldBuildingSectionProps) => {
return (
<section id={id} className="w-full bg-white">
<div className="max-w-max-width mx-auto px-5 min-[680px]:px-8 min-[1024px]:px-12 min-[1280px]:px-44 xl:px-40 py-12 min-[680px]:py-16 min-[1280px]:py-24 xl:py-24 flex flex-col items-center gap-8 md:gap-10">
<div className="max-w-[840px] text-center">
<H2 className="text-[28px] min-[680px]:text-[32px] xl:text-[36px] font-semibold leading-[125%] text-bluedot-navy tracking-[-0.01em]">
{title}
</H2>
<P className="mt-4 text-[16px] min-[680px]:text-[17px] leading-[1.6] text-bluedot-navy/70">
{intro}
</P>
</div>

<div className="w-[calc(100vw-40px)] min-[680px]:w-[calc(100vw-64px)] lg:w-[928px] xl:w-[1120px] bg-white border border-bluedot-navy/10 rounded-xl flex flex-col overflow-hidden">
{roles.map((role, index) => (
<div key={role.title}>
<div className="flex flex-col md:flex-row gap-3 md:gap-8 px-5 md:px-8 py-5 md:py-6">
<div className="md:w-[160px] shrink-0">
<P className="text-[16px] font-semibold leading-[1.3] text-bluedot-navy">
{role.title}
</P>
</div>

<div className="flex-1 min-w-0">
<P className="text-[15px] leading-[1.65] text-bluedot-navy/80">
{role.description}
</P>
<Link
href={role.linkUrl}
className="mt-3 inline-flex items-center gap-1 text-[15px] font-medium text-bluedot-normal hover:underline"
>
{role.linkText}
<span aria-hidden="true">→</span>
</Link>
</div>
</div>

{index < roles.length - 1 && <div className="w-full h-px bg-bluedot-navy/10" />}
</div>
))}
</div>
</div>
</section>
);
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Missing tests for new component

The new FieldBuildingSection component has no corresponding test file. Every other component in this directory (CourseBenefitsSection, PersonasSection, WhoIsThisForSection, etc.) has a dedicated .test.tsx. Consider adding a FieldBuildingSection.test.tsx covering at least a snapshot render and the divider logic (index < roles.length - 1).

Rule Used: Consider adding tests for any new functionality in... (source)

Learnt From
bluedotimpact/bluedot#956
bluedotimpact/bluedot#969
bluedotimpact/bluedot#958

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Comment on lines +18 to +67
const FieldBuildingSection = ({
id,
title,
intro,
roles,
}: FieldBuildingSectionProps) => {
return (
<section id={id} className="w-full bg-white">
<div className="max-w-max-width mx-auto px-5 min-[680px]:px-8 min-[1024px]:px-12 min-[1280px]:px-44 xl:px-40 py-12 min-[680px]:py-16 min-[1280px]:py-24 xl:py-24 flex flex-col items-center gap-8 md:gap-10">
<div className="max-w-[840px] text-center">
<H2 className="text-[28px] min-[680px]:text-[32px] xl:text-[36px] font-semibold leading-[125%] text-bluedot-navy tracking-[-0.01em]">
{title}
</H2>
<P className="mt-4 text-[16px] min-[680px]:text-[17px] leading-[1.6] text-bluedot-navy/70">
{intro}
</P>
</div>

<div className="w-[calc(100vw-40px)] min-[680px]:w-[calc(100vw-64px)] lg:w-[928px] xl:w-[1120px] bg-white border border-bluedot-navy/10 rounded-xl flex flex-col overflow-hidden">
{roles.map((role, index) => (
<div key={role.title}>
<div className="flex flex-col md:flex-row gap-3 md:gap-8 px-5 md:px-8 py-5 md:py-6">
<div className="md:w-[160px] shrink-0">
<P className="text-[16px] font-semibold leading-[1.3] text-bluedot-navy">
{role.title}
</P>
</div>

<div className="flex-1 min-w-0">
<P className="text-[15px] leading-[1.65] text-bluedot-navy/80">
{role.description}
</P>
<Link
href={role.linkUrl}
className="mt-3 inline-flex items-center gap-1 text-[15px] font-medium text-bluedot-normal hover:underline"
>
{role.linkText}
<span aria-hidden="true">→</span>
</Link>
</div>
</div>

{index < roles.length - 1 && <div className="w-full h-px bg-bluedot-navy/10" />}
</div>
))}
</div>
</div>
</section>
);
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Missing Storybook story for new component

All other lander sub-components (CourseBenefitsSection, FAQSection, HeroSection, WhoIsThisForSection, etc.) have a .stories.tsx file. A FieldBuildingSection.stories.tsx would make the component discoverable in Storybook and allow visual verification of the stacked-role layout.

Rule Used: Consider adding Storybook stories for new componen... (source)

Learnt From
bluedotimpact/bluedot#956
bluedotimpact/bluedot#969
bluedotimpact/bluedot#958

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Comment on lines 8 to +13
export type CourseOutcome = {
icon: IconType;
title: string;
description: ReactNode;
linkUrl?: string;
linkText?: string;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 New linkUrl/linkText feature has no test coverage

CourseOutcomesSection was modified in this PR to add optional linkUrl and linkText fields to CourseOutcome and conditionally render a per-card navigation link. There is currently no CourseOutcomesSection.test.tsx, so neither the with-link nor the without-link rendering path is covered. Consider adding tests for both variants.

Rule Used: Consider adding tests for any new functionality in... (source)

Learnt From
bluedotimpact/bluedot#956
bluedotimpact/bluedot#969
bluedotimpact/bluedot#958

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
apps/website/src/components/lander/components/FieldBuildingSection.tsx (1)

37-38: Consider a more robust key for role items.

Using role.title as the React key assumes titles are unique. If two roles share the same title, React will encounter duplicate keys. Consider using a combination of title and index, or adding an id field to FieldBuildingRole.

💡 Alternative key approach
-          {roles.map((role, index) => (
-            <div key={role.title}>
+          {roles.map((role, index) => (
+            <div key={`${role.title}-${index}`}>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/website/src/components/lander/components/FieldBuildingSection.tsx`
around lines 37 - 38, The current map in FieldBuildingSection uses role.title as
the React key which can collide; update the key to be robust by using a stable
unique identifier (e.g., add an id to the FieldBuildingRole type and use
role.id) or combine title and index (e.g., `${role.title}-${index}`) in the
roles.map callback; locate the roles.map(...) block and change the key prop on
the enclosing <div key=...> accordingly, and if choosing an id approach, add the
id to FieldBuildingRole and populate it where roles are created.
apps/website/src/components/lander/components/PathwaysSection.tsx (1)

44-47: Consider semantic markup for the intro content.

The intro changed from <P> to a plain <div> to accommodate ReactNode. This is functionally correct, but if callers typically pass plain text, the text won't have paragraph semantics. Consider whether consumers should wrap their content in <P> or if this component should provide guidance via JSDoc.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/website/src/components/lander/components/PathwaysSection.tsx` around
lines 44 - 47, PathwaysSection currently renders the intro prop inside a bare
<div>, losing paragraph semantics for plain text; update the component to
preserve semantics by rendering a <p> (or wrapping the content in a <p>) when
intro is a string (e.g., if (typeof intro === 'string') return <p
className="...">{intro}</p>), otherwise render the ReactNode as-is, and add a
brief JSDoc on the intro prop describing that plain text will be wrapped in a
paragraph while consumers can pass custom nodes for full control.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/website/src/components/lander/components/FieldBuildingSection.tsx`:
- Around line 37-38: The current map in FieldBuildingSection uses role.title as
the React key which can collide; update the key to be robust by using a stable
unique identifier (e.g., add an id to the FieldBuildingRole type and use
role.id) or combine title and index (e.g., `${role.title}-${index}`) in the
roles.map callback; locate the roles.map(...) block and change the key prop on
the enclosing <div key=...> accordingly, and if choosing an id approach, add the
id to FieldBuildingRole and populate it where roles are created.

In `@apps/website/src/components/lander/components/PathwaysSection.tsx`:
- Around line 44-47: PathwaysSection currently renders the intro prop inside a
bare <div>, losing paragraph semantics for plain text; update the component to
preserve semantics by rendering a <p> (or wrapping the content in a <p>) when
intro is a string (e.g., if (typeof intro === 'string') return <p
className="...">{intro}</p>), otherwise render the ReactNode as-is, and add a
brief JSDoc on the intro prop describing that plain text will be wrapped in a
paragraph while consumers can pass custom nodes for full control.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d1af88a9-ea41-4185-9f3a-fe5528d5c70c

📥 Commits

Reviewing files that changed from the base of the PR and between 8be08d2 and 587ddbe.

⛔ Files ignored due to path filters (3)
  • apps/website/src/components/homepage/__snapshots__/HomeHeroContent.test.tsx.snap is excluded by !**/*.snap
  • apps/website/src/components/lander/__snapshots__/AgiStrategyLander.test.tsx.snap is excluded by !**/*.snap
  • apps/website/src/components/lander/__snapshots__/FutureOfAiLander.test.tsx.snap is excluded by !**/*.snap
📒 Files selected for processing (6)
  • apps/website/src/components/lander/CourseLander.tsx
  • apps/website/src/components/lander/components/CourseOutcomesSection.tsx
  • apps/website/src/components/lander/components/FieldBuildingSection.tsx
  • apps/website/src/components/lander/components/GraduateSection.tsx
  • apps/website/src/components/lander/components/PathwaysSection.tsx
  • apps/website/src/components/lander/course-content/AiGovernanceContent.tsx

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant