Add login-page site gate and refresh marketing site for complex-care positioning.

Replace HTTP Basic Auth with a branded /login flow and signed session cookie, using Next.js 16's proxy convention for route protection.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-26 02:21:58 -04:00
co-authored by Cursor
parent d521c66903
commit b0636ba5ce
18 changed files with 877 additions and 252 deletions
+54 -11
View File
@@ -4,6 +4,7 @@ import { useState } from "react";
import {
CalendarDays,
Camera,
Check,
ContactRound,
Home,
MessageCircle,
@@ -21,6 +22,11 @@ const features = [
title: "One profile for the person you care for",
description:
"Visits, medications, reminders, and questions live together under the person they belong to.",
points: [
"Switch between everyone you care for",
"One home for the whole picture",
"Nothing scattered across apps",
],
image: "/screenshots/home.png",
alt: "Medscribe home dashboard with record visit, search, medications, and ask shortcuts",
},
@@ -31,6 +37,11 @@ const features = [
title: "The context behind the handoff",
description:
"Conditions, medication changes, visit summaries, and caregiver notes stay close enough to become useful when time is short.",
points: [
"Baseline, allergies, and conditions up front",
"Time-critical medications flagged",
"A source trail behind each fact",
],
image: "/screenshots/emergency-record.png",
alt: "Medscribe emergency record with critical care context",
},
@@ -41,6 +52,11 @@ const features = [
title: "Visit recordings that refresh the record",
description:
"A visit can become searchable context, so a medication change or follow-up instruction does not depend on memory alone.",
points: [
"Consent-gated, on-device recording",
"Searchable transcript and summary",
"Follow-ups captured, not forgotten",
],
image: "/screenshots/visit-timeline.png",
alt: "Medscribe visit timeline with appointment cards",
},
@@ -51,6 +67,11 @@ const features = [
title: "Medication OCR, reminders, and history",
description:
"Prescription labels, reminders, refill alerts, and dose history help the family see what is supposed to happen and what actually happened.",
points: [
"Scan labels with the camera",
"Reminders and refill alerts",
"Dose history at a glance",
],
image: "/screenshots/medications.png",
alt: "Medscribe medications screen with active medications",
},
@@ -61,6 +82,11 @@ const features = [
title: "Medication questions grounded in the record",
description:
"Plain-language questions can draw from the person's record and bundled FDA facts, while keeping diagnosis and dosing with clinicians.",
points: [
"Plain-language answers",
"Grounded in the record and FDA facts",
"Defers dosing and diagnosis to clinicians",
],
image: "/screenshots/chat.png",
alt: "Medscribe Ask chat answering a question about blood pressure medications",
},
@@ -71,6 +97,11 @@ const features = [
title: "Private by architecture, not policy",
description:
"The sensitive work happens on device, so the family record is not another cloud inbox waiting to be mined.",
points: [
"On-device AI, no cloud processing",
"No inbox to breach or mine",
"You control what is ever shared",
],
image: "/screenshots/settings.png",
alt: "Medscribe settings showing on-device AI models and privacy notice",
},
@@ -81,8 +112,8 @@ export function FeatureShowcase() {
const active = features.find((f) => f.id === activeId) ?? features[0];
return (
<div className="grid items-start gap-5 lg:grid-cols-[minmax(0,1fr)_minmax(170px,220px)] lg:gap-10">
<div className="space-y-3">
<div className="grid items-center gap-8 lg:grid-cols-[minmax(0,1fr)_300px] lg:gap-12">
<div className="flex flex-col gap-5">
<div className="flex flex-wrap gap-2">
{features.map((feature) => {
const Icon = feature.icon;
@@ -96,7 +127,7 @@ export function FeatureShowcase() {
className={cn(
"inline-flex items-center gap-2 rounded-full border px-3 py-1.5 text-sm font-medium transition-all",
isActive
? "border-primary bg-primary text-white shadow-sm"
? "border-primary-button bg-primary-button text-white shadow-sm"
: "border-border-soft bg-surface text-muted-foreground hover:border-primary/20 hover:text-foreground",
)}
>
@@ -107,22 +138,34 @@ export function FeatureShowcase() {
})}
</div>
<div className="space-y-1.5">
<h3 className="font-serif text-2xl font-semibold tracking-tight text-foreground">
<div className="space-y-2">
<h3 className="font-serif text-2xl font-semibold tracking-tight text-foreground sm:text-3xl">
{active.title}
</h3>
<p className="max-w-xl text-sm leading-relaxed text-muted-foreground sm:text-base">
{active.description}
</p>
</div>
<ul className="grid gap-x-5 gap-y-2.5 sm:grid-cols-2">
{active.points.map((point) => (
<li
key={point}
className="flex items-start gap-2 text-sm leading-snug text-foreground"
>
<span className="mt-0.5 flex size-4 shrink-0 items-center justify-center rounded-full bg-primary-light">
<Check className="size-3 text-primary" />
</span>
<span>{point}</span>
</li>
))}
</ul>
</div>
<div className="flex w-full max-w-[220px] items-start justify-center rounded-lg bg-surface-soft/70 p-4 shadow-[0_12px_38px_rgba(15,23,42,0.08)] lg:-mt-16 lg:justify-self-end">
<PhoneMockup
src={active.image}
alt={active.alt}
width={146}
/>
<div className="justify-self-center lg:justify-self-end">
<div className="flex items-center justify-center rounded-2xl border border-border-soft bg-gradient-to-b from-surface-soft to-primary-light/30 p-6 shadow-[0_18px_45px_rgba(15,23,42,0.10)]">
<PhoneMockup src={active.image} alt={active.alt} width={188} />
</div>
</div>
</div>
);