Files
PocketVeto/frontend/app/how-it-works/page.tsx
Jack Levy 676bf1b78d docs: overhaul documentation + add deployment guides
- ARCHITECTURE.md: update for v0.9.0/v0.9.3 — collections schema,
  collection_bills schema, alert_filters in notification_prefs,
  action_category in notification payload, migrations 0015/0016,
  /api/collections + /api/share endpoints, updated pages table,
  pipeline flow reflects categorize_action(), v0.9.0 and v0.9.3
  feature history entries
- ROADMAP.md: new file merging "MVP threshold" and "Feature Roadmap"
  docs into one clean shipped/upcoming/backlog structure with v1.0
  definition; removes stale design notes and duplicate entries
- DEPLOYING.md: new — prerequisites, .env setup, first run, admin
  account, domain/SSL with Caddy, useful commands
- UPDATING.md: new — SSH setup, manual deploy, deploy script, Gitea
  webhook + webhook listener, rollback procedure, env-only updates
- Delete: "MVP threshold this make v1 complete.md" and
  "PocketVeto — Feature Roadmap.md" (superseded by ROADMAP.md)
- how-it-works/page.tsx: accurate per-mode default alert sets,
  Alert Filters callout linking to Notifications settings
- notifications/page.tsx: Follow mode default includes amendment filed;
  Pocket Veto default excludes calendar placement

Authored-By: Jack Levy
2026-03-02 19:22:02 -05:00

228 lines
11 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Link from "next/link";
import {
Bell,
Bookmark,
Calendar,
Clock,
FileText,
Filter,
Heart,
HelpCircle,
Rss,
Shield,
Share2,
Zap,
} from "lucide-react";
function Section({ id, title, icon: Icon, children }: {
id: string;
title: string;
icon: React.ElementType;
children: React.ReactNode;
}) {
return (
<section id={id} className="bg-card border border-border rounded-lg p-6 space-y-4 scroll-mt-6">
<h2 className="text-lg font-semibold flex items-center gap-2">
<Icon className="w-5 h-5 text-primary" />
{title}
</h2>
{children}
</section>
);
}
function Item({ icon: Icon, color, title, children }: {
icon: React.ElementType;
color: string;
title: string;
children: React.ReactNode;
}) {
return (
<div className="flex gap-3">
<div className={`mt-0.5 shrink-0 w-7 h-7 rounded-full flex items-center justify-center ${color}`}>
<Icon className="w-3.5 h-3.5" />
</div>
<div>
<p className="text-sm font-medium">{title}</p>
<p className="text-xs text-muted-foreground mt-0.5 leading-relaxed">{children}</p>
</div>
</div>
);
}
export default function HowItWorksPage() {
return (
<div className="max-w-2xl mx-auto space-y-6">
<div>
<h1 className="text-2xl font-bold flex items-center gap-2">
<HelpCircle className="w-5 h-5" /> How it works
</h1>
<p className="text-muted-foreground text-sm mt-1">
A quick guide to PocketVeto&apos;s features.
</p>
{/* Jump links */}
<div className="flex flex-wrap gap-2 mt-3">
{[
{ href: "#follow", label: "Following" },
{ href: "#collections", label: "Collections" },
{ href: "#notifications", label: "Notifications" },
{ href: "#briefs", label: "AI Briefs" },
{ href: "#bills", label: "Bills" },
].map(({ href, label }) => (
<a
key={href}
href={href}
className="text-xs px-2.5 py-1 bg-muted rounded-full hover:bg-accent transition-colors"
>
{label}
</a>
))}
</div>
</div>
{/* Following */}
<Section id="follow" title="Following bills" icon={Heart}>
<p className="text-sm text-muted-foreground">
Follow any bill to track it. PocketVeto checks for changes and notifies you through your
configured channels. Three modes let you tune the signal to your interest level each
with its own independent set of alert filters.
</p>
<div className="space-y-3">
<Item icon={Heart} color="bg-red-100 text-red-600 dark:bg-red-900/30 dark:text-red-400" title="Follow">
The standard mode. Default alerts: new bill text, amendments filed, chamber votes,
presidential action, and committee reports.
</Item>
<Item icon={Shield} color="bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400" title="Pocket Veto">
For bills you oppose and only want to hear about if they gain real traction. Default
alerts: chamber votes and presidential action only no noise from early committee or
document activity.
</Item>
<Item icon={Zap} color="bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400" title="Pocket Boost">
For bills you actively support. Default alerts: everything new text, amendments,
votes, presidential action, committee reports, calendar placement, procedural moves,
and committee referrals. Also adds &ldquo;Find Your Rep&rdquo; action buttons to push
notifications.
</Item>
</div>
<div className="rounded-md bg-muted/60 px-4 py-3 space-y-1.5">
<p className="text-xs font-medium flex items-center gap-1.5">
<Filter className="w-3.5 h-3.5" /> Adjusting alert filters
</p>
<p className="text-xs text-muted-foreground leading-relaxed">
The defaults above are starting points. In{" "}
<Link href="/notifications" className="text-primary hover:underline">Notifications Alert Filters</Link>,
each mode has its own tab with eight independently toggleable alert types. For example,
a Follow bill where you don&apos;t care about committee reports uncheck it and only
that mode is affected. Hit <strong>Load defaults</strong> on any tab to revert to the
preset above.
</p>
</div>
<p className="text-xs text-muted-foreground">
You can also follow <strong>members</strong> (alerts when they sponsor new bills) and{" "}
<strong>topics</strong> (alerts when new bills matching that topic are briefed).
Member and topic follows use the Follow mode filters.
</p>
</Section>
{/* Collections */}
<Section id="collections" title="Collections" icon={Bookmark}>
<p className="text-sm text-muted-foreground">
A collection is a named, curated group of bills like a playlist for legislation. Use
collections to track a policy area, build a watchlist for an advocacy campaign, or share
research with colleagues.
</p>
<div className="space-y-3">
<Item icon={Bookmark} color="bg-blue-100 text-blue-600 dark:bg-blue-900/30 dark:text-blue-400" title="Creating a collection">
Give it a name (e.g. &ldquo;Healthcare Watch&rdquo;) and add bills from any bill detail
page using the bookmark icon next to the Follow button.
</Item>
<Item icon={Share2} color="bg-purple-100 text-purple-600 dark:bg-purple-900/30 dark:text-purple-400" title="Sharing">
Every collection has a unique share link. Anyone with the link can view the collection
no account required. The link works whether the collection is public or private.
</Item>
</div>
<p className="text-xs text-muted-foreground">
<strong>Public vs. private:</strong> Both have share links. Marking a collection public
signals it may appear in a future public directory; private collections are invisible to
anyone without your link.
</p>
</Section>
{/* Notifications */}
<Section id="notifications" title="Notifications" icon={Bell}>
<p className="text-sm text-muted-foreground">
PocketVeto delivers alerts through two independent channels use either or both.
</p>
<div className="space-y-3">
<Item icon={Bell} color="bg-blue-100 text-blue-600 dark:bg-blue-900/30 dark:text-blue-400" title="Push via ntfy">
<a href="https://ntfy.sh" target="_blank" rel="noopener noreferrer" className="text-primary hover:underline">
ntfy
</a>
{" "}is a free, open-source push notification service. Configure a topic URL in{" "}
<Link href="/notifications" className="text-primary hover:underline">Notifications</Link>{" "}
and receive real-time alerts on any device with the ntfy app.
</Item>
<Item icon={Clock} color="bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400" title="Quiet hours">
Pause push notifications during set hours (e.g. 10 PM 8 AM). Events that arrive
during quiet hours are queued and sent as a batch when the window ends.
</Item>
<Item icon={Calendar} color="bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400" title="Digest mode">
Instead of one push per event, receive a single bundled summary on a daily or weekly
schedule. Your RSS feed is always real-time regardless of this setting.
</Item>
<Item icon={Rss} color="bg-orange-100 text-orange-600 dark:bg-orange-900/30 dark:text-orange-400" title="RSS feed">
A private, tokenized RSS feed of all your bill alerts. Subscribe in any RSS reader
(Feedly, NetNewsWire, etc.). Completely independent of ntfy.
</Item>
</div>
</Section>
{/* AI Briefs */}
<Section id="briefs" title="AI Briefs" icon={FileText}>
<p className="text-sm text-muted-foreground">
For bills with published official text, PocketVeto generates a plain-English AI brief.
</p>
<div className="space-y-3">
<Item icon={FileText} color="bg-blue-100 text-blue-600 dark:bg-blue-900/30 dark:text-blue-400" title="What's in a brief">
A plain-English summary, key policy points with references to specific bill sections
(§ chips), and a risks section that flags potential unintended consequences or contested
provisions.
</Item>
<Item icon={Share2} color="bg-purple-100 text-purple-600 dark:bg-purple-900/30 dark:text-purple-400" title="Sharing a brief">
Click the share icon in the brief panel to copy a public link. Anyone can read the
brief at that URL no login required.
</Item>
<Item icon={Zap} color="bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400" title="Draft a letter">
Use the Draft Letter panel (below the brief) to generate a personalised letter to your
representative based on the brief&apos;s key points.
</Item>
</div>
<p className="text-xs text-muted-foreground">
Briefs are only generated for bills where GovInfo has published official text. Bills
without text show a &ldquo;No text&rdquo; badge on their card.
</p>
</Section>
{/* Bills */}
<Section id="bills" title="Browsing bills" icon={FileText}>
<p className="text-sm text-muted-foreground">
The <Link href="/bills" className="text-primary hover:underline">Bills</Link> page lists
all tracked legislation. Use the filters to narrow your search.
</p>
<div className="space-y-2 text-xs text-muted-foreground">
<p><strong className="text-foreground">Search</strong> matches bill ID, title, and short title.</p>
<p><strong className="text-foreground">Chamber</strong> House or Senate.</p>
<p><strong className="text-foreground">Topic</strong> AI-tagged policy area (healthcare, defense, etc.).</p>
<p><strong className="text-foreground">Has text</strong> show only bills with published official text available for AI briefing.</p>
</div>
<p className="text-xs text-muted-foreground">
Clicking a topic tag on any bill or following page takes you directly to that filtered
view on the Bills page.
</p>
</Section>
</div>
);
}