Skip to content

Commit c3d5c77

Browse files
committed
feat: implement featured content section with enhanced cards
- Rename messaging.md → flexion-notify.md to match repo name - Create forms-lab.md overlay content - Add highlights and related fields to overlay front-matter - Extend Overlay type and parser to support highlights/related - Mark forms, forms-lab, document-extractor, flexion-notify as featured - Build FeaturedCard component with title, summary, highlights, and CTA - Wire FeaturedCard into home page with intentional ordering (Forms and Forms Lab adjacent) - Adjust featured grid: 2 cols at medium, 4 cols at wide - Add "Featured" / "All projects" section headings to work index - Implement related projects cross-links on detail pages (Forms ↔ Forms Lab) - Update work-detail tests for new catalog prop
1 parent 52e4141 commit c3d5c77

16 files changed

Lines changed: 260 additions & 16 deletions

File tree

content/work/document-extractor.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
---
22
title: Document Extractor
33
summary: Turn PDFs and images of forms into structured data — without vendor lock-in.
4+
highlights:
5+
- Scanned PDFs, photos, and faxes
6+
- Open alternative to commercial OCR
7+
- Deploy, audit, and extend in-house
48
---
59

610
## What it solves
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
---
2-
title: Messaging
2+
title: Notify
33
summary: A public-sector-grade platform for sending SMS and email notifications about benefits, deadlines, and outages.
4+
highlights:
5+
- SMS and email from one API
6+
- Self-hosted, auditable delivery
7+
- No per-message vendor pricing
48
---
59

610
## What it solves

content/work/forms-lab.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
title: Forms Lab
3+
summary: An LLM-assisted platform that turns PDF forms into structured specs and delivers them as accessible digital experiences.
4+
highlights:
5+
- PDF-to-spec extraction via LLM
6+
- Static and conversational delivery modes
7+
- Pluggable model variants per step
8+
related:
9+
- forms
10+
---
11+
12+
## What it solves
13+
14+
Government forms are trapped in PDFs. Manually converting them to digital experiences is slow, expensive, and error-prone. Forms Lab automates the pipeline: upload a PDF, extract a structured spec, and deliver a form experience — static or conversational — without hand-coding each field.
15+
16+
## Who it's for
17+
18+
Teams exploring how LLMs can accelerate form digitization. The platform separates *what to collect* from *how to present it*, so extraction and delivery can evolve independently.
19+
20+
## Status
21+
22+
Active. Deployed with branch-per-experiment architecture and a live demo catalog documenting findings on extraction accuracy, model selection, and presentation strategies.
23+
24+
## Get started
25+
26+
The repository includes a live demo, experiment catalog, and architecture documentation. See the README for deployment instructions.

content/work/forms.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
---
22
title: Forms
33
summary: Accessible, USWDS-aligned form experiences that work for every resident and every agency.
4+
highlights:
5+
- WCAG 2.1 AA conformant
6+
- Multi-step with save and resume
7+
- Agency-agnostic, works with any back-end
8+
related:
9+
- forms-lab
410
---
511

612
## What it solves

data/overrides.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,22 @@
11
# Hand-authored overrides keyed by repo name.
22
# See docs/catalog.md for supported fields.
3+
4+
forms:
5+
tier: active
6+
category: product
7+
featured: true
8+
9+
forms-lab:
10+
tier: active
11+
category: product
12+
featured: true
13+
14+
document-extractor:
15+
tier: active
16+
category: product
17+
featured: true
18+
19+
flexion-notify:
20+
tier: active
21+
category: product
22+
featured: true

src/build/entry.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ async function render(
109109
return renderToHtml(<DesignSystem config={config} />)
110110
case 'work-detail': {
111111
const entry = catalog.find((e) => e.name === route.slug)!
112-
return renderToHtml(<WorkDetail entry={entry} now={now} config={config} />)
112+
return renderToHtml(<WorkDetail entry={entry} catalog={catalog} now={now} config={config} />)
113113
}
114114
}
115115
}

src/catalog/overlays.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,18 @@ export async function loadOverlay(path: string): Promise<Overlay | null> {
1818
return {
1919
title: stringOrUndefined(frontMatter.title),
2020
summary: stringOrUndefined(frontMatter.summary),
21+
highlights: stringArrayOrUndefined(frontMatter.highlights),
22+
related: stringArrayOrUndefined(frontMatter.related),
2123
body: body || undefined,
2224
}
2325
}
2426

2527
function stringOrUndefined(value: unknown): string | undefined {
2628
return typeof value === 'string' ? value : undefined
2729
}
30+
31+
function stringArrayOrUndefined(value: unknown): string[] | undefined {
32+
if (!Array.isArray(value)) return undefined
33+
const strings = value.filter((v): v is string => typeof v === 'string')
34+
return strings.length > 0 ? strings : undefined
35+
}

src/catalog/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ export type OverrideEntry = {
3434
export type Overlay = {
3535
title?: string
3636
summary?: string
37+
highlights?: string[]
38+
related?: string[]
3739
body?: string
3840
}
3941

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import type { CatalogEntry } from '../../../catalog/types'
2+
import { url } from '../../../build/config'
3+
4+
export function FeaturedCard({ entry, basePath }: { entry: CatalogEntry; basePath: string }) {
5+
const href = url(`/work/${entry.name}/`, basePath)
6+
const title = entry.overlay?.title ?? entry.name
7+
const summary = entry.overlay?.summary ?? entry.description ?? ''
8+
const highlights = entry.overlay?.highlights
9+
10+
return (
11+
<article class="featured-card">
12+
<h3 class="featured-card__title">
13+
<a href={href}>{title}</a>
14+
</h3>
15+
{summary ? <p class="featured-card__summary">{summary}</p> : null}
16+
{highlights ? (
17+
<ul class="featured-card__highlights">
18+
{highlights.map((h) => <li>{h}</li>)}
19+
</ul>
20+
) : null}
21+
<p class="featured-card__cta">
22+
<a href={href}>Learn more &rarr;</a>
23+
</p>
24+
</article>
25+
)
26+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
.featured-card {
2+
padding: var(--space-5);
3+
border: 1px solid var(--color-surface-alt);
4+
border-block-start: 3px solid var(--color-accent);
5+
border-radius: var(--radius-md);
6+
background: var(--color-surface);
7+
box-shadow: var(--shadow-card);
8+
display: grid;
9+
gap: var(--space-3);
10+
align-content: start;
11+
}
12+
13+
.featured-card__title {
14+
font-size: var(--step-1);
15+
line-height: 1.2;
16+
}
17+
18+
.featured-card__title a {
19+
color: var(--color-ink);
20+
text-decoration: none;
21+
}
22+
23+
.featured-card__title a:hover {
24+
color: var(--color-link-hover);
25+
}
26+
27+
.featured-card__summary {
28+
color: var(--color-ink-subtle);
29+
font-size: var(--step--1);
30+
}
31+
32+
.featured-card__highlights {
33+
list-style: none;
34+
padding: 0;
35+
display: flex;
36+
flex-direction: column;
37+
gap: var(--space-1);
38+
font-size: var(--step--1);
39+
}
40+
41+
.featured-card__highlights li::before {
42+
content: "\2713\0020";
43+
color: var(--color-tier-active);
44+
font-weight: 700;
45+
}
46+
47+
.featured-card__cta {
48+
margin-block-start: auto;
49+
font-size: var(--step--1);
50+
}
51+
52+
.featured-card__cta a {
53+
color: var(--color-link);
54+
text-decoration: none;
55+
font-weight: 600;
56+
}
57+
58+
.featured-card__cta a:hover {
59+
color: var(--color-link-hover);
60+
text-decoration: underline;
61+
}

0 commit comments

Comments
 (0)