// All sections for the morally pink Eve Riche site const { useState: useStateS, useEffect: useEffectS, useRef: useRefS, useMemo: useMemoS } = React; /* ============================================================ HEADER ============================================================ */ function Header({ onSignup, current = 'home' }) { const scrolled = useScrolled(40); const [menuOpen, setMenuOpen] = useStateS(false); // Lock body scroll when mobile menu open useEffectS(() => { if (menuOpen) { const prev = document.body.style.overflow; document.body.style.overflow = 'hidden'; return () => { document.body.style.overflow = prev; }; } }, [menuOpen]); // Each nav item: label, slug used both as href and for active state. // About and Bonuses each carry a sub-dropdown. const NAV = [ { slug: 'home', label: 'Home', href: 'index.html' }, { slug: 'about', label: 'About', href: 'about.html', children: [ { slug: 'about', label: 'About Eve Riche', href: 'about.html' }, { slug: 'media', label: 'Media contact', href: 'media.html' }, ] }, { slug: 'books', label: 'Books', href: 'books.html' }, { slug: 'bonuses', label: 'Bonuses', href: 'bonuses.html', children: [ { slug: 'bonuses', label: 'Bonus material', href: 'bonuses.html' }, { slug: 'reading-order', label: 'Reading order', href: 'reading-order.html' }, { slug: 'arc', label: 'ARC applications', href: 'arc.html' }, ] }, { slug: 'warnings', label: 'Warnings', href: 'warnings.html' }, ]; function handleSignup(e) { e.preventDefault(); setMenuOpen(false); if (current === 'home') { onSignup(); } else { // navigate to home and hash to newsletter window.location.href = 'index.html#newsletter'; } } return (
Eve Riche
Eve Riche
Unapologetically dark why choose romance
{menuOpen && (
{NAV.map((n) => ( {n.label} ))} RSVP to the Club
)}
); } /* ============================================================ HERO ============================================================ */ function Hero({ featured, seriesMode, onSignup, onOpenBook }) { return (
); } /* ============================================================ PITCH ============================================================ */ function Pitch({ seriesMode }) { return (

II  ·  The itch

For readers who want their romance bloody,
their heroes unrepentant, and their
happy endings earned in the dark.

— the kind of book your best friend texts you about at 2am

Why-choose that earns its structure. Explicit heat with consent baked in. Morally black heroes with real interiority. Honky-tonk banter, kill scene, vulnerability scene — all in the same chapter. And jokes. A lot of jokes. Dark romance is too funny to be relentlessly grim.

); } /* ============================================================ BOOKS — horizontal carousel + filters ============================================================ */ function Books({ seriesMode, onPickSeries, onOpenBook, homepage = false }) { const trackRef = useRefS(null); // On the homepage we show only the launch trilogy as a preview. // On the books page (homepage=false) we honor the filter. const list = useMemoS(() => { if (homepage) return BOOKS.filter((b) => b.seriesKey === 'hangmen'); // Until other series are announced, the "all books" view is just Hangmen. if (seriesMode === 'all') return BOOKS.filter((b) => b.seriesKey === 'hangmen'); return BOOKS.filter((b) => b.seriesKey === seriesMode); }, [seriesMode, homepage]); function scrollBy(dir) { const t = trackRef.current; if (!t) return; const card = t.querySelector('.er-card'); const w = card ? card.getBoundingClientRect().width + 28 : 320; t.scrollBy({ left: dir * w, behavior: 'smooth' }); } return (
{homepage && (
See all books
)}
{list.map((book, i) =>
onOpenBook(book)}> {book.cover ? {`${book.title} :
{book.title} cover · reveal · TBC
}
read more →
{book.series}

{book.title}

{book.date} {book.status}

{book.blurb}

{book.readUrl ? ( Read now on Amazon ) : book.preorderUrl ? ( Pre-order now on Amazon ) : ( )}
)}
← drag, scroll, or click any cover to read more →
); } /* ============================================================ SERIES — staggered rows ============================================================ */ function SeriesRows({ onPickSeries }) { const ornaments = { hangmen: , gods: , cuc: }; return (
The universe

One world. Three doors in.

Read in any order. They braid in the middle. They all end the same way — with someone happy and someone in the ground.

{SERIES.map((s, i) =>
{onPickSeries(s.key);scrollToId('books');}}>
{`0${i + 1}`}
{s.label}

{s.title}

{s.tagline}

{s.note}

Enter
    {s.books.map((b, j) =>
  • 0{j + 1} · {b} {i === 0 && j === 0 ? '8 Aug' : i === 0 && j === 1 ? '8 Sep' : i === 0 && j === 2 ? '8 Oct' : 'TBC'}
  • )}
  • Begins {s.starts}
{ornaments[s.key]}
)}
); } /* ============================================================ AUTHORS ============================================================ */ function Authors() { return (
Eve Riche
No headshot · not now · maybe not ever

Two voices. One heartbeat.

Eve Riche is two USA Today bestselling authors writing under one pen name. They write dark why-choose romance about people who kill together, love fiercely, and refuse to apologize for either.

Their books are explicit, darkly humorous, and emotionally unflinching. If you want morally grey characters and chaotic murder puppies — they’re your girls.

They won't confess their names. Snitches get stitches...

~ Eve Riche ~
); } /* ============================================================ QUIZ — "Read me first" ============================================================ */ function Quiz({ onOpenBook }) { const [step, setStep] = useStateS(0); const [scores, setScores] = useStateS({ hangmen: 0, gods: 0, cuc: 0 }); function choose(a) { const ns = { ...scores }; Object.keys(a.w || {}).forEach((k) => {ns[k] = (ns[k] || 0) + a.w[k];}); setScores(ns); setStep(step + 1); } function reset() { setStep(0); setScores({ hangmen: 0, gods: 0, cuc: 0 }); } const done = step >= QUIZ.length; const winner = done ? Object.keys(scores).reduce((a, b) => scores[a] >= scores[b] ? a : b, 'hangmen') : null; const result = winner ? QUIZ_RESULTS[winner] : null; const resultBook = result ? BOOKS.find((b) => b.id === result.bookId) : null; return (
Read me first

Three questions. One ruined night.

We don’t care where you start — they all braid — but if you want a recommendation, indulge us.

{QUIZ.map((_, i) => )}
{!done &&

{QUIZ[step].q}

{QUIZ[step].a.map((a, i) => )}
question {step + 1} of {QUIZ.length}
} {done && resultBook &&
{resultBook.cover ? {resultBook.title} :
{resultBook.title}
}
Your prescription

{result.title.split('.').map((p, i) => i === 0 ? {p}. : p).filter(Boolean)}

{result.sub}

Begin with {resultBook.title}.

}
); } /* ============================================================ NEWSLETTER ============================================================ */ function Newsletter() { const [email, setEmail] = useStateS(''); const [submitted, setSubmitted] = useStateS(false); const [error, setError] = useStateS(''); function submit(e) { e.preventDefault(); if (!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email)) { setError('That doesn’t look like an email, sweet thing. Try again.'); return; } setError(''); setSubmitted(true); } return (
Members only

Step inside the Club.

A velvet rope, a low-lit room, a list with your name on it. First chapters, cover reveals, bonus scenes and ARC drops — straight to your inbox before anyone else hears the door open.

The Menu

Hangmen Trilogy starts 8 August 2026

  • First chapter of What We Bury
  • Cover reveals before they go public
  • Bonus POVs & deleted scenes
  • Priority ARC consideration & members-only giveaways
{submitted ?
You’re on the list, sweetheart. The doorman saw you. The first chapter is on its way to {email}. If it’s in spam, you’re holding it wrong — drag us into the inbox.
:
setEmail(e.target.value)} aria-label="Email address" />
} {error &&
{error}
}

Members only · unsubscribe with one click · the velvet rope swings both ways

); } /* ============================================================ EVENTS ============================================================ */ function Events() { return (
The diary

Where you can find us.

Online unless noted. Always introvert-friendly. Sometimes lipstick required.

{EVENTS.map((e, i) =>
scrollToId('newsletter')}>
{e.date} {e.year}
{e.title}
{e.where}
{e.tag}
)}
); } /* ============================================================ BONUS ============================================================ */ function Bonus({ showHeader = true } = {}) { return (
{showHeader && (
Bonus material

Extras for the devoted.

Patreon, newsletter, preorder rewards — the gift bag at the back of the confessional.

)}
{BONUS.map((b, i) =>
{b.label}

{b.title}

{b.body}

❦ {b.lock}
{b.cta && ( {b.cta.label} )}
)}
); } /* ============================================================ PRESS / CONTACT ============================================================ */ function Press({ onCw }) { return (
The rest

For agents, podcasters, conspirators.

No DMs · email only · we read it all · sometimes we even reply

For readers

The list

Reply to any newsletter — a human (one of the two trench coats) will answer.

Press & rights

Hi. We bite.

Foreign rights, podcast interviews, panel invites, content trades. Pitch us in a paragraph; we’ll write back in two.

press@everiche.com
For sensitive readers

Content warnings

We list everything. We mean it. We’d rather you don’t read us than read us underprepared.

Reader community

The Confessional

Our Discord. Spoiler-tagged channels per book. Daily chaos. Murder-puppy memes. Annotations only people who finished should read.

Open Discord
); } /* ============================================================ CW BANNER + MODAL ============================================================ */ function CwBanner({ onOpen }) { return (
Content advisory
These books are dark on purpose. We list every reason out loud.
); } function CwModal({ open, onClose }) { useEffectS(() => { if (!open) return; function key(e) {if (e.key === 'Escape') onClose();} window.addEventListener('keydown', key); document.body.style.overflow = 'hidden'; return () => { window.removeEventListener('keydown', key); document.body.style.overflow = ''; }; }, [open, onClose]); if (!open) return null; return (
e.stopPropagation()}>
Read this before you read us

Content warnings.

We write dark romance that is actually dark. Not aestheticized darkness where everyone’s hot and brooding and nobody does anything morally reprehensible. Our men kill people. Sometimes the women do too. The on-page intimacy is enthusiastic; the on-page violence is not.

    {CONTENT_WARNINGS.map((w, i) =>
  • {w}
  • )}
Every book ships with its own content-warning sheet. Reply to any newsletter and we’ll send yours.
); } /* ============================================================ FOOTER ============================================================ */ function Footer() { return ( ); } Object.assign(window, { Header, Hero, Pitch, Books, SeriesRows, Authors, Quiz, Newsletter, Events, Bonus, Press, CwBanner, CwModal, Footer });