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 ===================== */}
+102 -261
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 */}
{/* Hero */} <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">
<section className="grid items-center gap-8 lg:grid-cols-[minmax(0,1fr)_minmax(230px,280px)] lg:gap-14">
<div className="space-y-6">
<div className="animate-fade-in-up space-y-5">
<SectionLabel>Medscribe · Private complex-care context</SectionLabel>
<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
</h1>
<p className="max-w-xl text-base leading-relaxed text-muted-foreground sm:text-lg">
A private medical context app for families managing complex care.
It keeps visits, medications, baseline, contacts, allergies, and
emergency facts ready before the chart catches up.
</p>
<p className="text-sm text-muted-foreground">{today}</p>
</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">No cloud AI</Badge>
</div>
</div>
<div className="animate-fade-in-up-delay-3 flex justify-center lg:justify-end">
<div className="flex w-fit items-start justify-center">
<PhoneMockup <PhoneMockup
src="/screenshots/home.png" src="/screenshots/home.png"
alt="Medscribe home dashboard" alt="Medscribe home screen"
width={200}
priority priority
width={190}
/> />
</div> </div>
</div>
</section>
{/* Strategic spine */} <div className="space-y-10 lg:space-y-12">
{/* Hero */}
<section className="animate-fade-in-up space-y-5"> <section className="animate-fade-in-up space-y-5">
<SectionLabel>The story</SectionLabel> <SectionLabel>Executive summary · Northwell Health</SectionLabel>
<div className="grid gap-6 lg:grid-cols-[minmax(0,0.9fr)_minmax(0,1.1fr)] lg:items-start"> <h1 className="font-serif text-4xl leading-[1.05] font-semibold tracking-tight text-foreground sm:text-5xl lg:text-6xl">
<div className="space-y-3"> Be known when care gets complicated
<h2 className="font-serif text-3xl font-semibold tracking-tight sm:text-4xl"> </h1>
The story scatters right when it matters <p className="text-base leading-relaxed text-muted-foreground sm:text-lg">
</h2> Medscribe is a private, patient-owned medical record that lives on the
<p className="max-w-xl leading-relaxed text-muted-foreground"> patient&apos;s phone and stays with them exactly where Epic
A daughter remembers the medication schedule. A spouse knows what can&apos;t follow.
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>
<p className="max-w-xl text-sm leading-relaxed text-muted-foreground/80 italic"> <div className="flex flex-wrap gap-2">
I built the first version of Medscribe after watching my own family <Badge variant="success">On-device · no cloud AI</Badge>
try to hold this together for my grandfather. The record scattered <Badge variant="outline">Emergency-ready</Badge>
right when we needed it most. <Badge variant="outline">Complements Epic</Badge>
</p> <Badge variant="outline">iOS · Android beta</Badge>
</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="flex items-start gap-3">
<HeartPulse className="mt-0.5 size-5 shrink-0 text-primary" />
<div className="space-y-2">
<h3 className="font-serif text-xl font-semibold tracking-tight">
One current story
</h3>
<p className="text-sm leading-relaxed text-muted-foreground">
Medscribe gives the family a private place to keep that context
alive: current meds, timing, baseline, allergies, recent visit
summaries, emergency contacts, and the source trail behind each
fact.
</p>
</div>
</div>
</div>
</div>
<div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-4">
{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">
<div
className={`flex size-10 items-center justify-center rounded-[10px] ${
action.featured ? "bg-white/18" : "bg-primary-light"
}`}
>
<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> </div>
</section> </section>
{/* Interactive feature showcase */} {/* What it is */}
<section id="features" className="animate-fade-in-up scroll-mt-24 space-y-5"> <section className="animate-fade-in-up space-y-3">
<div className="space-y-2"> <SectionLabel>What it is</SectionLabel>
<SectionLabel>The record</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 pieces that keep the story current A medical record the patient owns and carries
</h2> </h2>
<p className="max-w-2xl text-muted-foreground"> <p className="leading-relaxed text-muted-foreground">
Visits, medications, reminders, search, and questions all point toward Current medications, allergies, baseline, visit summaries, and an
the same outcome: a record the family can trust when the stakes rise. emergency &ldquo;know-me&rdquo; record kept current through everyday
use, and ready to hand to a caregiver, a new doctor, or an ER in seconds.
Everything runs on the device. Nothing is uploaded.
</p> </p>
</div>
<FeatureShowcase />
</section> </section>
{/* Privacy */} {/* The gap Epic can't close */}
<section id="privacy" className="animate-fade-in-up scroll-mt-24 space-y-6"> <section className="animate-fade-in-up space-y-3">
<div className="space-y-3"> <SectionLabel>The gap Epic can&apos;t close</SectionLabel>
<SectionLabel>Why this is different</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">
Built for the family record, not another cloud inbox The record that leaves the building with the patient
</h2> </h2>
<p className="max-w-2xl text-muted-foreground"> <p className="leading-relaxed text-muted-foreground">
The crowded space already has visit recorders, medication apps, and Epic is Northwell&apos;s system of record the definitive account of
caregiver portals. Medscribe&apos;s wedge is the private, portable care inside the network. What no institutional EHR is built to be is the
context layer families control before an institution is ready and record the patient owns and carries everywhere else: the out-of-network
it works alongside the systems a care team already uses, not instead ER, a specialist on a different Epic instance, the weeks at home between
of them. 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> </p>
</div> </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">
Built to strengthen the Epic investment, not compete with it
</h2>
</div>
<div className="grid gap-4 md:grid-cols-3"> <div className="grid gap-4 md:grid-cols-3">
{pillars.map((pillar) => { {fit.map((item) => {
const Icon = pillar.icon; const Icon = item.icon;
return ( return (
<Card key={pillar.title} className="card-hover"> <Card key={item.title} className="card-hover">
<CardHeader> <CardHeader>
<div className="flex size-10 items-center justify-center rounded-[10px] bg-primary-light"> <div className="flex size-10 items-center justify-center rounded-[10px] bg-primary-light">
<Icon className="size-5 text-primary" /> <Icon className="size-5 text-primary" />
</div> </div>
<CardTitle>{pillar.title}</CardTitle> <CardTitle className="text-lg">{item.title}</CardTitle>
<CardDescription>{pillar.body}</CardDescription> <CardDescription>{item.body}</CardDescription>
</CardHeader> </CardHeader>
</Card> </Card>
); );
})} })}
</div> </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> </section>
{/* Impact */} {/* Who's behind it + the ask */}
<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"> <section className="animate-fade-in-up">
<Card className="overflow-hidden border-primary-button/20 bg-primary-button text-white"> <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"> <CardHeader className="gap-4">
<div className="space-y-2"> <div className="space-y-3">
<CardTitle className="text-white">{BETA_CTA_TITLE}</CardTitle> <CardTitle className="text-white">Who&apos;s behind it</CardTitle>
<CardDescription className="text-white/75"> <CardDescription className="leading-relaxed text-white/80">
{BETA_CTA_BODY} 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> </CardDescription>
</div> </div>
<Button <Button
asChild asChild
size="lg" size="lg"
variant="outline" variant="outline"
className="border-white/30 bg-white text-primary-button hover:bg-white/90" className="w-fit border-white/30 bg-white text-primary-button hover:bg-white/90"
> >
<a href={BETA_INVITE_MAILTO}>Request an invite</a> <a href={BETA_INVITE_MAILTO}>Start the conversation</a>
</Button> </Button>
</CardHeader> </CardHeader>
</Card> </Card>
</section> </section>
</div>
</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>
); );
} }