Refocus homepage as Northwell exec summary with float layout.

Single-page strategic pitch for health-system readers; phone mockup wraps in newspaper-style columns; retire multi-page nav and redirect /executive-summary to home.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-13 14:53:23 -04:00
co-authored by Cursor
parent a590a506f8
commit 2f8dcd66ad
3 changed files with 148 additions and 410 deletions
@@ -1,6 +1,7 @@
import type { CSSProperties } from "react"; import type { CSSProperties } from "react";
import type { Metadata } from "next"; import type { Metadata } from "next";
import { redirect } from "next/navigation";
import Image from "next/image"; import Image from "next/image";
import { MedscribeLogo } from "~/components/medscribe-logo"; import { MedscribeLogo } from "~/components/medscribe-logo";
@@ -131,6 +132,11 @@ const printLightTokens = {
} as CSSProperties; } as CSSProperties;
export default function ExecutiveSummaryPage() { export default function ExecutiveSummaryPage() {
// The home page is now the executive summary (single-page site). This deep
// page is retired but kept in place — its content (incl. the print one-pager)
// is a one-line revert away if we want a longer version back.
redirect("/");
return ( return (
<> <>
{/* ===================== SCREEN ===================== */} {/* ===================== SCREEN ===================== */}
+139 -298
View File
@@ -1,332 +1,173 @@
import { import { HeartPulse, Layers, ShieldCheck } from "lucide-react";
AlertTriangle,
ChevronRight,
ClipboardList,
HeartPulse,
Lock,
Mic,
Pill,
Shield,
Users,
} from "lucide-react";
import { FeatureShowcase } from "~/components/feature-showcase";
import { PhoneMockup } from "~/components/phone-mockup"; import { PhoneMockup } from "~/components/phone-mockup";
import { SectionLabel } from "~/components/section-label"; import { SectionLabel } from "~/components/section-label";
import { import { BETA_INVITE_MAILTO } from "~/lib/beta";
BETA_CTA_BODY,
BETA_CTA_TITLE,
BETA_INVITE_MAILTO,
} from "~/lib/beta";
import { Badge } from "~/components/ui/badge"; import { Badge } from "~/components/ui/badge";
import { Button } from "~/components/ui/button"; import { Button } from "~/components/ui/button";
import { import {
Card, Card,
CardContent,
CardDescription, CardDescription,
CardHeader, CardHeader,
CardTitle, CardTitle,
} from "~/components/ui/card"; } from "~/components/ui/card";
const quickActions = [ const fit = [
{
icon: Layers,
title: "Complements Epic — doesn't compete",
body: "Different question. Epic answers “what does Northwell know about this patient?” Medscribe answers “what does the patient carry everywhere else?” With the patient's consent, the out-of-network and between-visit context it captures flows back into the workflows Northwell already runs — raising the value of the Epic investment rather than competing for it.",
},
{ {
icon: HeartPulse, icon: HeartPulse,
title: "Know Me card", title: "Patient-centered where it counts",
meta: "Baseline, conditions, allergies", body: "The emergency handoff, the family caregiver covering a shift, the newly-diagnosed patient who half-remembers the plan. Fewer blank handoffs, safer medication moments, patients who stay engaged instead of going dark.",
featured: true,
}, },
{ {
icon: Pill, icon: ShieldCheck,
title: "Time-critical meds", title: "Private by architecture",
meta: "Schedules caregivers can trust", body: "The sensitive work — transcription, medication questions, building the record — runs entirely on the device, not the cloud. No health data sent to a server for AI processing, no new inbox to breach, no BAA to negotiate.",
},
{
icon: Mic,
title: "Visit capture",
meta: "Consent-gated, on-device",
},
{
icon: Users,
title: "Caregiver handoff",
meta: "One current shared truth",
},
];
const pillars = [
{
icon: ClipboardList,
title: "Keep the record current",
body: "Capture visits, scan labels, and keep conditions, medications, allergies, contacts, and caregiver notes in one portable record.",
},
{
icon: AlertTriangle,
title: "Make the critical context obvious",
body: "The emergency view prioritizes the facts clinicians need fast: baseline, time-critical meds, active conditions, allergies, and who to call.",
},
{
icon: Shield,
title: "Stay private by architecture",
body: "Transcription, OCR, and medication chat run locally. No cloud AI processing. Sharing should be explicit, revocable, and encrypted.",
},
];
const impact = [
{
title: "Fewer blank handoffs",
body: "When a caregiver is overwhelmed, the important facts are already assembled: conditions, medications, allergies, baseline, contacts, and recent changes.",
},
{
title: "Safer medication moments",
body: "Time-critical schedules and dose history stay visible, so a missed or delayed medication is easier to catch before it becomes a crisis.",
},
{
title: "More confident families",
body: "Caregivers can see what changed, where it came from, and what still needs a clinician or pharmacist instead of guessing from memory.",
}, },
]; ];
export default function HomePage() { export default function HomePage() {
const today = new Date().toLocaleDateString("en-US", {
weekday: "long",
month: "long",
day: "numeric",
});
return ( return (
<div className="mx-auto max-w-6xl space-y-14 px-4 py-8 sm:px-6 sm:py-12 lg:space-y-20 lg:py-14"> <div className="mx-auto max-w-5xl px-4 py-10 sm:px-6 lg:py-14">
{/* Phone floats right on sm+; prose sections wrap around it like a newspaper column */}
<div className="animate-fade-in-up-delay-1 mx-auto mb-8 flex justify-center sm:float-right sm:mx-0 sm:ml-8 sm:mb-4 lg:ml-10">
<PhoneMockup
src="/screenshots/home.png"
alt="Medscribe home screen"
width={200}
priority
/>
</div>
{/* Hero */} <div className="space-y-10 lg:space-y-12">
<section className="grid items-center gap-8 lg:grid-cols-[minmax(0,1fr)_minmax(230px,280px)] lg:gap-14"> {/* Hero */}
<div className="space-y-6"> <section className="animate-fade-in-up space-y-5">
<div className="animate-fade-in-up space-y-5"> <SectionLabel>Executive summary · Northwell Health</SectionLabel>
<SectionLabel>Medscribe · Private complex-care context</SectionLabel> <h1 className="font-serif text-4xl leading-[1.05] font-semibold tracking-tight text-foreground sm:text-5xl lg:text-6xl">
<h1 className="max-w-2xl font-serif text-4xl leading-[1.05] font-semibold tracking-tight text-foreground sm:text-5xl lg:text-6xl"> Be known when care gets complicated
Be known when care gets complicated </h1>
</h1> <p className="text-base leading-relaxed text-muted-foreground sm:text-lg">
<p className="max-w-xl text-base leading-relaxed text-muted-foreground sm:text-lg"> Medscribe is a private, patient-owned medical record that lives on the
A private medical context app for families managing complex care. patient&apos;s phone and stays with them exactly where Epic
It keeps visits, medications, baseline, contacts, allergies, and can&apos;t follow.
emergency facts ready before the chart catches up. </p>
</p> <div className="flex flex-wrap gap-2">
<p className="text-sm text-muted-foreground">{today}</p> <Badge variant="success">On-device · no cloud AI</Badge>
</div>
<div className="animate-fade-in-up-delay-1 flex flex-wrap gap-3">
<Button asChild size="lg">
<a href="/executive-summary">
Read executive summary
<ChevronRight className="size-4" />
</a>
</Button>
<Button asChild variant="outline" size="lg">
<a href="#features">See how it works</a>
</Button>
</div>
<div className="animate-fade-in-up-delay-2 flex flex-wrap gap-2">
<Badge variant="success">Beta available</Badge>
<Badge variant="outline">iOS · TestFlight</Badge>
<Badge variant="outline">Android · Play internal</Badge>
<Badge variant="outline">Emergency-ready</Badge> <Badge variant="outline">Emergency-ready</Badge>
<Badge variant="outline">No cloud AI</Badge> <Badge variant="outline">Complements Epic</Badge>
<Badge variant="outline">iOS · Android beta</Badge>
</div> </div>
</div> </section>
<div className="animate-fade-in-up-delay-3 flex justify-center lg:justify-end"> {/* What it is */}
<div className="flex w-fit items-start justify-center"> <section className="animate-fade-in-up space-y-3">
<PhoneMockup <SectionLabel>What it is</SectionLabel>
src="/screenshots/home.png" <h2 className="font-serif text-3xl font-semibold tracking-tight sm:text-4xl">
alt="Medscribe home dashboard" A medical record the patient owns and carries
priority </h2>
width={190} <p className="leading-relaxed text-muted-foreground">
/> Current medications, allergies, baseline, visit summaries, and an
</div> emergency &ldquo;know-me&rdquo; record kept current through everyday
</div> use, and ready to hand to a caregiver, a new doctor, or an ER in seconds.
</section> Everything runs on the device. Nothing is uploaded.
</p>
</section>
{/* Strategic spine */} {/* The gap Epic can't close */}
<section className="animate-fade-in-up space-y-5"> <section className="animate-fade-in-up space-y-3">
<SectionLabel>The story</SectionLabel> <SectionLabel>The gap Epic can&apos;t close</SectionLabel>
<div className="grid gap-6 lg:grid-cols-[minmax(0,0.9fr)_minmax(0,1.1fr)] lg:items-start"> <h2 className="font-serif text-3xl font-semibold tracking-tight sm:text-4xl">
<div className="space-y-3"> The record that leaves the building with the patient
</h2>
<p className="leading-relaxed text-muted-foreground">
Epic is Northwell&apos;s system of record the definitive account of
care inside the network. What no institutional EHR is built to be is the
record the patient owns and carries everywhere else: the out-of-network
ER, a specialist on a different Epic instance, the weeks at home between
visits. That out-of-hospital stretch is a structural blind spot the
system loses sight of the patient the moment they leave, and often only
learns what happened when they return, worse.
</p>
</section>
{/* What makes it different */}
<section className="animate-fade-in-up space-y-3">
<SectionLabel>What makes it different</SectionLabel>
<h2 className="font-serif text-3xl font-semibold tracking-tight sm:text-4xl">
No one else owns the whole job
</h2>
<p className="leading-relaxed text-muted-foreground">
The market is full of single-purpose apps visit recorders, medication
trackers, record vaults, emergency-ID cards, caregiver portals. Each owns
one slice. None keeps a private, patient-owned record that stays current
through daily use, is ready to hand over in a crisis, and runs entirely on
the patient&apos;s own device. Medscribe is that combination and no
existing product has it.
</p>
</section>
{/* Why it fits Northwell — clear float so the card grid spans full width */}
<section className="animate-fade-in-up clear-both space-y-6">
<div className="space-y-2">
<SectionLabel>Why it fits Northwell</SectionLabel>
<h2 className="font-serif text-3xl font-semibold tracking-tight sm:text-4xl"> <h2 className="font-serif text-3xl font-semibold tracking-tight sm:text-4xl">
The story scatters right when it matters Built to strengthen the Epic investment, not compete with it
</h2> </h2>
<p className="max-w-xl leading-relaxed text-muted-foreground">
A daughter remembers the medication schedule. A spouse knows what
normal looks like. A specialist mentioned a change three visits ago.
In a crisis, those details are scattered across people, portals, and
memory.
</p>
<p className="max-w-xl text-sm leading-relaxed text-muted-foreground/80 italic">
I built the first version of Medscribe after watching my own family
try to hold this together for my grandfather. The record scattered
right when we needed it most.
</p>
</div> </div>
<div className="rounded-lg border border-border-soft bg-surface p-5 shadow-[0_1px_4px_rgba(0,0,0,0.05)]"> <div className="grid gap-4 md:grid-cols-3">
<div className="flex items-start gap-3"> {fit.map((item) => {
<HeartPulse className="mt-0.5 size-5 shrink-0 text-primary" /> const Icon = item.icon;
<div className="space-y-2">
<h3 className="font-serif text-xl font-semibold tracking-tight"> return (
One current story <Card key={item.title} className="card-hover">
</h3> <CardHeader>
<p className="text-sm leading-relaxed text-muted-foreground"> <div className="flex size-10 items-center justify-center rounded-[10px] bg-primary-light">
Medscribe gives the family a private place to keep that context <Icon className="size-5 text-primary" />
alive: current meds, timing, baseline, allergies, recent visit </div>
summaries, emergency contacts, and the source trail behind each <CardTitle className="text-lg">{item.title}</CardTitle>
fact. <CardDescription>{item.body}</CardDescription>
</p> </CardHeader>
</Card>
);
})}
</div>
</section>
{/* Who's behind it + the ask */}
<section className="animate-fade-in-up">
<Card className="overflow-hidden border-primary-button/20 bg-primary-button text-white">
<CardHeader className="gap-4">
<div className="space-y-3">
<CardTitle className="text-white">Who&apos;s behind it</CardTitle>
<CardDescription className="leading-relaxed text-white/80">
Sean O&apos;Connor built Medscribe after watching his own family try
to hold this together for his grandfather the record scattered
exactly when it mattered most. Bucknell computer-science engineer;
the app is live in beta on iOS and Android today.
</CardDescription>
<CardDescription className="leading-relaxed text-white/80">
The ask is a short conversation about whether an out-of-hospital,
patient-owned context layer one that feeds Northwell&apos;s Epic
investment rather than competes with it is worth exploring
together.
</CardDescription>
</div> </div>
</div> <Button
</div> asChild
</div> size="lg"
variant="outline"
<div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-4"> className="w-fit border-white/30 bg-white text-primary-button hover:bg-white/90"
{quickActions.map((action) => {
const Icon = action.icon;
return (
<Card
key={action.title}
className={`card-hover ${action.featured ? "border-primary-button/20 bg-primary-button text-white" : ""}`}
> >
<CardHeader className="gap-3"> <a href={BETA_INVITE_MAILTO}>Start the conversation</a>
<div </Button>
className={`flex size-10 items-center justify-center rounded-[10px] ${ </CardHeader>
action.featured ? "bg-white/18" : "bg-primary-light" </Card>
}`} </section>
> </div>
<Icon
className={`size-5 ${action.featured ? "text-white" : "text-primary"}`}
/>
</div>
<div>
<CardTitle className={action.featured ? "text-white" : ""}>
{action.title}
</CardTitle>
<CardDescription
className={action.featured ? "text-white/72" : ""}
>
{action.meta}
</CardDescription>
</div>
</CardHeader>
</Card>
);
})}
</div>
</section>
{/* Interactive feature showcase */}
<section id="features" className="animate-fade-in-up scroll-mt-24 space-y-5">
<div className="space-y-2">
<SectionLabel>The record</SectionLabel>
<h2 className="font-serif text-3xl font-semibold tracking-tight sm:text-4xl">
The pieces that keep the story current
</h2>
<p className="max-w-2xl text-muted-foreground">
Visits, medications, reminders, search, and questions all point toward
the same outcome: a record the family can trust when the stakes rise.
</p>
</div>
<FeatureShowcase />
</section>
{/* Privacy */}
<section id="privacy" className="animate-fade-in-up scroll-mt-24 space-y-6">
<div className="space-y-3">
<SectionLabel>Why this is different</SectionLabel>
<h2 className="font-serif text-3xl font-semibold tracking-tight sm:text-4xl">
Built for the family record, not another cloud inbox
</h2>
<p className="max-w-2xl text-muted-foreground">
The crowded space already has visit recorders, medication apps, and
caregiver portals. Medscribe&apos;s wedge is the private, portable
context layer families control before an institution is ready and
it works alongside the systems a care team already uses, not instead
of them.
</p>
</div>
<div className="grid gap-4 md:grid-cols-3">
{pillars.map((pillar) => {
const Icon = pillar.icon;
return (
<Card key={pillar.title} className="card-hover">
<CardHeader>
<div className="flex size-10 items-center justify-center rounded-[10px] bg-primary-light">
<Icon className="size-5 text-primary" />
</div>
<CardTitle>{pillar.title}</CardTitle>
<CardDescription>{pillar.body}</CardDescription>
</CardHeader>
</Card>
);
})}
</div>
<Card className="border-primary/15 bg-primary-light/40">
<CardContent className="flex items-start gap-4 pt-5">
<Lock className="mt-0.5 size-5 shrink-0 text-primary" />
<p className="text-sm leading-relaxed text-foreground">
All AI models run on your device. No health data is uploaded for
processing. The medication chatbot stays in drug-information
territory. It defers dosing and diagnosis questions to your
clinician or pharmacist.
</p>
</CardContent>
</Card>
</section>
{/* Impact */}
<section id="impact" className="animate-fade-in-up scroll-mt-24 space-y-6">
<div className="space-y-3">
<SectionLabel>Potential impact</SectionLabel>
<h2 className="font-serif text-3xl font-semibold tracking-tight sm:text-4xl">
Less panic, more context, better handoffs
</h2>
<p className="max-w-2xl text-muted-foreground">
The goal is simple: make the person easier to understand at the exact
moment their care team has the least context.
</p>
</div>
<div className="grid gap-4 md:grid-cols-3">
{impact.map((item) => (
<Card key={item.title} className="card-hover">
<CardHeader>
<CardTitle>{item.title}</CardTitle>
<CardDescription>{item.body}</CardDescription>
</CardHeader>
</Card>
))}
</div>
</section>
{/* CTA */}
<section className="animate-fade-in-up">
<Card className="overflow-hidden border-primary-button/20 bg-primary-button text-white">
<CardHeader className="gap-4 sm:flex-row sm:items-center sm:justify-between">
<div className="space-y-2">
<CardTitle className="text-white">{BETA_CTA_TITLE}</CardTitle>
<CardDescription className="text-white/75">
{BETA_CTA_BODY}
</CardDescription>
</div>
<Button
asChild
size="lg"
variant="outline"
className="border-white/30 bg-white text-primary-button hover:bg-white/90"
>
<a href={BETA_INVITE_MAILTO}>Request an invite</a>
</Button>
</CardHeader>
</Card>
</section>
</div> </div>
); );
} }
+3 -112
View File
@@ -1,22 +1,8 @@
"use client";
import { useState } from "react";
import { FileText, Home, Menu, X } from "lucide-react";
import Link from "next/link"; import Link from "next/link";
import { usePathname } from "next/navigation";
import { MedscribeLogo } from "~/components/medscribe-logo"; import { MedscribeLogo } from "~/components/medscribe-logo";
import { cn } from "~/lib/utils";
const navLinks = [
{ href: "/", label: "About", icon: Home },
{ href: "/executive-summary", label: "Summary", icon: FileText },
];
export function SiteHeader() { export function SiteHeader() {
const pathname = usePathname();
const [isOpen, setIsOpen] = useState(false);
return ( return (
<header className="print-hidden sticky top-3 z-50 px-3 sm:px-6"> <header className="print-hidden sticky top-3 z-50 px-3 sm:px-6">
<div className="relative mx-auto max-w-5xl"> <div className="relative mx-auto max-w-5xl">
@@ -25,109 +11,14 @@ export function SiteHeader() {
href="/" href="/"
className="flex items-center text-foreground transition-opacity hover:opacity-80" className="flex items-center text-foreground transition-opacity hover:opacity-80"
aria-label="Medscribe home" aria-label="Medscribe home"
onClick={() => setIsOpen(false)}
> >
<MedscribeLogo className="h-7 w-[88px]" /> <MedscribeLogo className="h-7 w-[88px]" />
</Link> </Link>
<span className="text-xs font-medium tracking-[0.14em] text-muted-foreground uppercase">
{/* Desktop nav */} Executive summary
<nav className="hidden items-center gap-6 text-sm sm:flex"> </span>
{navLinks.map((link) => {
const isActive = link.href === pathname;
return (
<Link
key={link.href}
href={link.href}
aria-current={isActive ? "page" : undefined}
className={cn(
"relative py-1 transition-colors",
isActive
? "text-foreground"
: "text-muted-foreground hover:text-foreground",
)}
>
{link.label}
<span
className={cn(
"absolute inset-x-0 -bottom-0.5 h-0.5 origin-center rounded-full bg-primary transition-transform duration-200",
isActive ? "scale-x-100" : "scale-x-0",
)}
aria-hidden
/>
</Link>
);
})}
</nav>
{/* Mobile menu toggle */}
<button
type="button"
onClick={() => setIsOpen((v) => !v)}
className="relative size-6 text-muted-foreground transition-colors hover:text-foreground focus:outline-none sm:hidden"
aria-label={isOpen ? "Close menu" : "Open menu"}
aria-expanded={isOpen}
>
<Menu
className={cn(
"absolute inset-0 transition-opacity duration-200",
isOpen ? "opacity-0" : "opacity-100",
)}
/>
<X
className={cn(
"absolute inset-0 transition-opacity duration-200",
isOpen ? "opacity-100" : "opacity-0",
)}
/>
</button>
</div>
{/* Mobile dropdown */}
<div
className={cn(
"absolute inset-x-0 top-16 overflow-hidden rounded-2xl border border-border-soft/80 bg-canvas/95 shadow-[0_10px_30px_rgba(15,23,42,0.12)] backdrop-blur-md transition-all duration-200 sm:hidden",
isOpen
? "pointer-events-auto opacity-100"
: "pointer-events-none -translate-y-1 opacity-0",
)}
>
<nav className="flex flex-col p-2">
{navLinks.map((link) => {
const isActive = link.href === pathname;
const Icon = link.icon;
return (
<Link
key={link.href}
href={link.href}
aria-current={isActive ? "page" : undefined}
onClick={() => setIsOpen(false)}
className={cn(
"flex items-center gap-3 rounded-xl px-3 py-2.5 text-sm font-medium transition-colors",
isActive
? "bg-primary-light/60 text-foreground"
: "text-muted-foreground hover:bg-surface-soft hover:text-foreground",
)}
>
<Icon className="size-4" />
{link.label}
</Link>
);
})}
</nav>
</div> </div>
</div> </div>
{/* Backdrop */}
<div
className={cn(
"fixed inset-0 -z-10 bg-canvas/30 backdrop-blur-sm transition-opacity duration-200 sm:hidden",
isOpen ? "opacity-100" : "pointer-events-none opacity-0",
)}
onClick={() => setIsOpen(false)}
aria-hidden
/>
</header> </header>
); );
} }