/* global React, Icons, ResumePaper, SAMPLE_RESUME, ScaleDots, ScaleSegs, ScaleSignal */ // ============================================================ // Landing — bright, conversion-style marketing page // ============================================================ const { useState, useEffect, useRef } = React; // count-up animation (runs once when mounted / scrolled into view) function CountUp({ to, dur = 1500, suffix = "" }) { const [n, setN] = useState(0); const ref = useRef(null); const done = useRef(false); useEffect(() => { const run = () => { if (done.current) return;done.current = true; let start; const ease = (x) => 1 - Math.pow(1 - x, 3); const tick = (t) => { if (!start) start = t; const p = Math.min(1, (t - start) / dur); setN(Math.round(ease(p) * to)); if (p < 1) requestAnimationFrame(tick); }; requestAnimationFrame(tick); }; const node = ref.current; let io; if (node && "IntersectionObserver" in window) { io = new IntersectionObserver((es) => {es.forEach((e) => e.isIntersecting && run());}, { threshold: 0.3 }); io.observe(node); } // fallback so counters always animate even if the observer never fires const t = setTimeout(run, 900); // safety snap: guarantee the final value shows even if rAF is throttled const snap = setTimeout(() => setN(to), 2600); return () => {if (io) io.disconnect();clearTimeout(t);clearTimeout(snap);}; }, [to, dur]); return {n.toLocaleString()}{suffix}; } // little gradient score ring for the hero float card function MiniScore({ score = 92, size = 40 }) { const R = 16,C = 2 * Math.PI * R; return ( {score} ); } const STARS = (n = 5) => [...Array(n)].map((_, i) => ); // testimonial avatar — self-contained striped photo placeholder (tinted per person) function Avatar({ name, c }) { return ( ); } // typewriter that types each phrase, holds, deletes, advances — used in the AI demo function Typewriter({ phrases, speed = 34, hold = 1700 }) { const [txt, setTxt] = useState(""); const [idx, setIdx] = useState(0); const [del, setDel] = useState(false); useEffect(() => { const cur = phrases[idx % phrases.length]; let t; if (!del && txt === cur) t = setTimeout(() => setDel(true), hold);else if (del && txt === "") {setDel(false);setIdx((i) => i + 1);} else t = setTimeout(() => setTxt(del ? cur.slice(0, txt.length - 1) : cur.slice(0, txt.length + 1)), del ? 18 : speed); return () => clearTimeout(t); }, [txt, del, idx, phrases, speed, hold]); return {txt}; } // "hired at" logo wall — real monochrome brand marks via Simple Icons CDN, // with a graceful fallback to the wordmark if a logo isn't available. const LOGOS = [ { slug: "google", name: "Google" }, { slug: "airbnb", name: "Airbnb" }, { slug: "spotify", name: "Spotify" }, { slug: "stripe", name: "Stripe" }, { slug: "figma", name: "Figma" }, { slug: "notion", name: "Notion" }, { slug: "dropbox", name: "Dropbox" }, { slug: "github", name: "GitHub" }, { slug: "slack", name: "Slack" }, { slug: "uber", name: "Uber" }, { slug: "netflix", name: "Netflix" }, { slug: "amazon", name: "Amazon" }, { slug: "adobe", name: "Adobe" }, { slug: "salesforce", name: "Salesforce" }, { slug: "atlassian", name: "Atlassian" }, { slug: "shopify", name: "Shopify" }, { slug: "coinbase", name: "Coinbase" }, { slug: "linkedin", name: "LinkedIn" }]; function BrandLogo({ slug, name }) { const [err, setErr] = useState(false); if (err) return {name}; return ( {name} setErr(true)} />); } function Landing({ onStart, onGallery, onCovers, onPrivacy, onRefund, onContact }) { const [demoTpl, setDemoTpl] = useState("meridian"); const tpls = window.TEMPLATES; useEffect(() => { const order = ["meridian", "spectrum", "helix", "ember", "veritas", "onyx", "marigold", "quill"]; let i = 0; const id = setInterval(() => {i = (i + 1) % order.length;setDemoTpl(order[i]);}, 3000); return () => clearInterval(id); }, []); // reveal section headers with motion as they scroll into view (scroll-based — // robust across embedded/scaled contexts where IntersectionObserver misbehaves) useEffect(() => { const els = [...document.querySelectorAll(".landing .sec-head, .landing .eyebrow")]; els.forEach((el) => el.classList.add("reveal-init")); let ticking = false; const check = () => { ticking = false; const vh = window.innerHeight || document.documentElement.clientHeight; els.forEach((el) => { if (!el.classList.contains("reveal-init")) return; const r = el.getBoundingClientRect(); if (r.top < vh * 0.9 && r.bottom > 0) {el.classList.add("reveal-in");el.classList.remove("reveal-init");} }); }; const onScroll = () => {if (!ticking) {ticking = true;requestAnimationFrame(check);}}; check(); window.addEventListener("scroll", onScroll, { passive: true }); window.addEventListener("resize", onScroll); // safety: reveal everything shortly after load even if no scroll happens const t = setTimeout(() => els.forEach((el) => {el.classList.add("reveal-in");el.classList.remove("reveal-init");}), 2500); return () => {window.removeEventListener("scroll", onScroll);window.removeEventListener("resize", onScroll);clearTimeout(t);}; }, []); return (
{/* ===== hero ===== */}
Free AI résumé builder

Build a résumé that
gets you hired.

Pick a design, add your details, and let AI write every line for you. Your résumé is ready in minutes — free to start, and built to get past screening bots and impress real recruiters.

Free to build, edit & copy as text — no sign-up. PDF downloads with Pro.

Excellent{STARS(5)} 4.8 / 5 · reviews
{["meridian", "spectrum", "helix", "ember", "veritas", "onyx", "marigold", "quill"].map((id) =>
Résumé score 92Strong · recruiter-ready
ATS-perfectParsed by every tracker
Skills
Figma
React
Motion
{/* ===== logos ===== */}
People here got hired at
{[0, 1].map((g) =>
{LOGOS.map((l, i) => )}
)}
{/* ===== build-mode chooser ===== */}
Get started

Two easy ways to begin.

{/* ===== AI layer highlight ===== */}
Writes it for you

Not sure what to write? AI does it.

Just type what you did in plain words. AI turns it into polished, impressive lines that sound like a pro wrote them — matched to the job you want. No more staring at a blank page.

  • Fix, shorten, or punch up any line in one click
  • Writes your summary and bullet points from scratch
  • Tuned to the exact job you're applying for
AI rewrite live
Your note

“managed social media and grew the following”

Rewrite with impact
AI suggestion

Ask AI to make it stronger…
{/* ===== proficiency scale highlight (new feature) ===== */}
Stand out

Show how good you are — not just what you know.

Rate your skills on a simple 1-to-5 scale. Recruiters instantly see where you shine, and your résumé looks like an expert made it. Pick the style you like: subtle dots, bold bars, or equalizer signals.

  • Per-skill levels, edited with a tap
  • Auto-styled to match your template
  • Languages rated the same way
Skills
{[["Figma", 5], ["Prototyping", 5], ["React", 4], ["TypeScript", 3]].map(([n, l]) =>
{n}
)}
Dots
Segments
Signal
{/* ===== feature trio ===== */}
{[ { ic: Icons.magic, t: "AI writes it for you", d: "Type what you did in plain words. AI turns it into polished, impressive lines in one click.", ai: true, c: "#7deb00" }, { ic: Icons.layers, t: "50+ designs you'll love", d: "Beautiful layouts for every field — modern, classic, minimal. Switch anytime without losing a word.", c: "#4f9dff" }, { ic: Icons.bolt, t: "A score that guides you", d: "A live score shows exactly what to add or fix — so you send something that gets noticed.", c: "#ffb43d" }]. map((f, i) =>
{f.ai && AI-powered}

{f.t}

{f.d}

)}
{/* ===== bento grid ===== */}
Everything in one studio

More ways to land the role.

AI that writes for you

Turn rough notes into crisp, quantified bullets. Rewrite, shorten, or punch up any line — in your voice.

Rewrite Quantify Shorten

Beats the robots

Reads cleanly in every hiring system.

92

Live strength score

Know exactly what to fix.

50

designs for every field

Modern, classic, minimal, bold — switch anytime without losing a word.

Skill scales

Cover letters

Matched to your field, in a click.

Browse templates

One-click PDF

Pixel-perfect, print-ready.

See who's looking

Know when an employer opens it.

Made for the job you want

Paste the job post — we match the keywords and tune every line so you fit the role.

Keyword match Role-tuned
4.8

Maker rating

12,480 reviews.

Live preview

Every edit, instantly.

{/* ===== step-by-step showcase ===== */}
Your résumé3 of 5 done
{[ ["Personal details", true], ["Professional summary", true], ["Skills & levels", "active"], ["Experience", false], ["Education", false]]. map(([t, st], i) =>
{st === true ? : i + 1} {t} {st === "active" && }
)}
How it works

Guided, section by section.

No blank-page stress. We walk you through each part, show you exactly what to add, and check it off as you go. Stuck on wording? AI suggests lines that sound professional.

01

Choose a template

Pick a layout that fits your field.

02

Add your story

Fill sections or paste an old résumé.

03

Polish & export

Sharpen with AI, download a clean PDF.

{/* ===== testimonials ===== */}
Loved by job seekers

People get hired with this.

{[ { q: "Switched careers in six weeks. The strength score told me exactly what was missing before I hit send.", n: "Priya Nair", r: "Product Designer", c: "#6a4dff", img: 47 }, { q: "The skill scales made my résumé look senior. Three callbacks in the first week.", n: "Marcus Lee", r: "Frontend Engineer", c: "#0e9f8e", img: 12 }, { q: "Pasted my old PDF, picked a template, done. It finally looks like I take myself seriously.", n: "Sofía Ramírez", r: "Marketing Lead", c: "#e23d7a", img: 45 }]. map((t, i) =>
{STARS(5)}

“{t.q}”

{t.n}{t.r}
)}
{/* ===== CTA ===== */}

Your next role starts
with a better résumé.

Free to build. Beautiful by default. Ready in minutes.

); } window.Landing = Landing;