import { useState, useCallback } from "react";
const DISCIPLINES = ["Cloud", "DevOps", "Security", "Data", "AI", "Platform", "Software", "Infrastructure"];
const ACCENT = "#FF6B35";
const ACCENT_LIGHT = "#FFF3EF";
const ACCENT_DARK = "#CC5529";
const TEAL = "#0A7EA4";
const TEAL_LIGHT = "#E6F4FA";
const SYSTEM_PROMPT = `You are the YoungOrange GTM Enrichment Engine — an AI commercial intelligence layer that analyzes companies for IT hiring pain.
YoungOrange is a specialized IT staffing company with two propositions:
- OrangeBoost: acute IT capacity — fast deployment of DevOps, Cloud, Security, Data Engineers
- OrangeElevate: structural talent building — select, train, grow IT talent within client organizations
Your job: analyze a company name and produce a structured GTM analysis in VALID JSON only (no markdown, no preamble, no explanation outside the JSON).
Respond ONLY with this exact JSON structure:
{
"company": "company name",
"sector": "inferred sector",
"hiring_overview": {
"total_it_vacancies": ,
"disciplines": {
"Cloud": ,
"DevOps": ,
"Security": ,
"Data": ,
"AI": ,
"Platform": ,
"Software": ,
"Infrastructure":
},
"time_to_hire_signal": "short|medium|long",
"growth_signal": "stable|growing|accelerating",
"seniority_mix": "junior-heavy|balanced|senior-heavy"
},
"pain_score": ,
"pain_drivers": ["driver 1", "driver 2", "driver 3"],
"pain_suppressors": ["suppressor 1"],
"analysis": "2-3 sentence substantive commercial analysis of why this company has or lacks hiring pain, referencing their known tech stack, growth stage, sector dynamics, and IT complexity",
"proposition": "OrangeBoost|OrangeElevate|Both",
"proposition_rationale": "1-2 sentence rationale for the chosen proposition",
"urgency": "low|medium|high|critical",
"sales_summary": "3-4 sentence SDR-ready commercial summary with specific hooks relevant to this company's situation",
"outreach_suggestion": "A specific, personalized first outreach message (LinkedIn or email opening) for an SDR to use, referencing real signals about this company",
"best_contact_role": "e.g. CTO, VP Engineering, Head of Platform",
"timing_signal": "e.g. Q1 budget cycle, post-funding, digital transformation phase"
}
Base your analysis on:
- Known public information about the company (sector, size, tech stack, growth phase)
- Typical IT hiring patterns for companies of this type
- Industry benchmarks for IT vacancy duration
- Digital transformation signals in their sector
- Company growth stage and funding status if known
Be specific and commercially sharp. Avoid generic statements. If you don't know the company, make reasonable inferences from the name and estimate accordingly, but flag uncertainty in the analysis field.`;
function ScoreGauge({ score }) {
const color = score >= 70 ? "#E34948" : score >= 45 ? "#EDA100" : "#1BAF7A";
const label = score >= 70 ? "High pain" : score >= 45 ? "Medium pain" : "Low pain";
const r = 54;
const circ = 2 * Math.PI * r;
const dash = (score / 100) * circ;
return (
;
}
function PropBadge({ prop }) {
if (prop === "OrangeBoost") return ;
if (prop === "OrangeElevate") return ;
return (
);
}
function Card({ children, style = {} }) {
return (
);
}
const EXAMPLES = ["ASML", "Coolblue", "Jumbo", "ING Bank", "bol.com", "NS", "Philips", "VodafoneZiggo", "TomTom", "Boskalis"];
export default function App() {
const [company, setCompany] = useState("");
const [loading, setLoading] = useState(false);
const [result, setResult] = useState(null);
const [error, setError] = useState(null);
const analyze = useCallback(async (name) => {
const target = name || company;
if (!target.trim()) return;
setLoading(true);
setError(null);
setResult(null);
try {
const response = await fetch("https://api.anthropic.com/v1/messages", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
model: "claude-sonnet-4-6",
max_tokens: 1000,
system: SYSTEM_PROMPT,
messages: [{ role: "user", content: `Analyze this company for IT hiring pain and YoungOrange GTM fit: ${target}` }],
}),
});
const data = await response.json();
const text = data.content?.find(b => b.type === "text")?.text || "";
const clean = text.replace(/```json|```/g, "").trim();
const parsed = JSON.parse(clean);
setResult(parsed);
} catch (e) {
setError("Analysis failed. Check your connection and try again.");
} finally {
setLoading(false);
}
}, [company]);
const handleKey = (e) => { if (e.key === "Enter") analyze(); };
return (
{!result && !loading && (
<>
{/* Input */}
Company name
{/* Quick examples */}
{/* How it works */}
}
{result && !loading && (
{ setResult(null); setCompany(""); setError(null); }} />
)}
);
}
{label}
);
}
function DisciplineBar({ name, count, max }) {
const pct = max > 0 ? Math.round((count / max) * 100) : 0;
const colors = {
Cloud: "#2a78d6", DevOps: "#1baf7a", Security: "#e34948",
Data: "#eda100", AI: "#4a3aa7", Platform: "#eb6834",
Software: "#1baf7a", Infrastructure: "#73726c"
};
if (count === 0) return null;
return (
{name}
{count}
);
}
function Badge({ label, color = "var(--bg-accent)", textColor = "var(--text-accent)" }) {
return (
{label}
);
}
function UrgencyBadge({ urgency }) {
const map = {
low: { bg: "#EAF3DE", text: "#3B6D11", label: "Low urgency" },
medium: { bg: "#FAEEDA", text: "#854F0B", label: "Medium urgency" },
high: { bg: "#FCEBEB", text: "#A32D2D", label: "High urgency" },
critical: { bg: "#E34948", text: "#fff", label: "Critical" },
};
const c = map[urgency] || map.medium;
return
{children}
);
}
function SectionLabel({ children }) {
return {children}
; } function ResultView({ data, onReset }) { const disc = data.hiring_overview?.disciplines || {}; const maxDisc = Math.max(...Object.values(disc)); return (
{/* Header */}
{/* Score + Overview row */}
Hiring Pain Score
Hiring signals
Timing context
{/* Discipline breakdown */}
Discipline breakdown
{DISCIPLINES.map(d => (
))}
{Object.values(disc).every(v => v === 0) && (
{/* Pain drivers / suppressors */}
Pain drivers
{(data.pain_drivers || []).map((d, i) => (
Pain suppressors
{(data.pain_suppressors || []).length > 0 ? (data.pain_suppressors || []).map((s, i) => (
{/* Analysis */}
Commercial analysis
{/* Proposition */}
Aanbevolen YoungOrange propositie
{/* Sales summary */}
Sales summary (SDR-ready)
{/* Outreach suggestion */}
Outreach suggestie
);
}
function LoadingState({ company }) {
const steps = [
{ icon: "ti-world-search", label: `Analyzing ${company}...` },
{ icon: "ti-building", label: "Checking tech stack & growth signals..." },
{ icon: "ti-briefcase", label: "Estimating hiring patterns..." },
{ icon: "ti-chart-bar", label: "Calculating Hiring Pain Score..." },
{ icon: "ti-bulb", label: "Generating GTM advice..." },
];
const [step, setStep] = useState(0);
useState(() => {
const interval = setInterval(() => setStep(s => Math.min(s + 1, steps.length - 1)), 1400);
return () => clearInterval(interval);
});
return (
{data.company}
{data.sector}
{[
{ label: "IT vacancies", value: data.hiring_overview?.total_it_vacancies ?? "–" },
{ label: "Time to hire", value: { short: "Short", medium: "Medium", long: "Long" }[data.hiring_overview?.time_to_hire_signal] || "–" },
{ label: "Team growth", value: { stable: "Stable", growing: "Growing", accelerating: "Accelerating" }[data.hiring_overview?.growth_signal] || "–" },
{ label: "Seniority mix", value: { "junior-heavy": "Junior-heavy", balanced: "Balanced", "senior-heavy": "Senior-heavy" }[data.hiring_overview?.seniority_mix] || "–" },
].map(({ label, value }) => (
))}
{label}
{value}
{data.timing_signal || "–"}
Best contact: {data.best_contact_role || "–"}
No discipline data available
)}
{d}
))}
{s}
)) : None identified
}{data.analysis}
{data.proposition_rationale}
{data.sales_summary}
"{data.outreach_suggestion}"
{steps.map((s, i) => (
{s.label}
{i < step && }
))}
YoungOrange GTM Enrichment Engine — Hiring Pain Analyzer
{/* Header */}YoungOrange
GTM Enrichment Engine
setCompany(e.target.value)}
onKeyDown={handleKey}
placeholder="e.g. ASML, ING Bank, Coolblue..."
style={{ flex: 1, fontSize: 15 }}
autoFocus
/>
Quick examples
{EXAMPLES.map(ex => (
))}
{[
{ icon: "ti-world-search", title: "Signal enrichment", desc: "External data added to intent signals" },
{ icon: "ti-chart-bar", title: "Pain scoring", desc: "0–100 Hiring Pain Score calculated" },
{ icon: "ti-target", title: "Proposition match", desc: "OrangeBoost or OrangeElevate" },
{ icon: "ti-mail", title: "Outreach ready", desc: "Personalized first message generated" },
].map(({ icon, title, desc }) => (
))}
{error && (
{title}
{desc}
{error}
)}
>
)}
{loading && 