diff --git a/apps/frontend/src/components/MechanizeBanner.tsx b/apps/frontend/src/components/MechanizeBanner.tsx
new file mode 100644
index 0000000..bb2452c
--- /dev/null
+++ b/apps/frontend/src/components/MechanizeBanner.tsx
@@ -0,0 +1,71 @@
+"use client";
+
+import { useEffect, useState, type ReactElement } from "react";
+import { ArrowUpRightIcon, XMarkIcon } from "@heroicons/react/24/solid";
+import Link from "./Link";
+
+const DISMISS_KEY = "cmucourses-mechanize-banner-dismissed";
+
+const PROMPTS = [
+ "Mechanize is hiring junior SWEs. $300K base + equity.",
+ "Better at coding than AI? Prove it.",
+ "We hire engineers to outsmart AI. It’s harder than you think. 300k + equity.",
+ "Most engineers can’t beat Claude on our take-home. Think you can? 300k + equity for Jr SWEs at Mechanize.",
+];
+const MECHANIZE_APPLY_URL = "https://jobs.ashbyhq.com/mechanize?utm_source=CMU";
+
+function pickPrompt(): string {
+ return PROMPTS[Math.floor(Math.random() * PROMPTS.length)]!;
+}
+
+export default function MechanizeBanner(): ReactElement | null {
+ const [prompt, setPrompt] = useState
(null);
+
+ useEffect(() => {
+ try {
+ if (sessionStorage.getItem(DISMISS_KEY) === "1") {
+ return;
+ }
+ } catch {
+ /* sessionStorage unavailable (e.g. private mode restrictions) */
+ }
+ setPrompt(pickPrompt());
+ }, []);
+
+ const handleDismiss = () => {
+ try {
+ sessionStorage.setItem(DISMISS_KEY, "1");
+ } catch {
+ /* ignore */
+ }
+ setPrompt(null);
+ };
+
+ if (prompt == null) {
+ return null;
+ }
+
+ return (
+
+
+
+
{prompt}
+
+ Apply now
+
+
+
+
+ );
+}