Skip to content

Commit 902fceb

Browse files
authored
Merge pull request #2 from flexion/feat/initial-build
Flexion Labs initial build: catalog, views, styles, CI
2 parents 6caac0d + d7be977 commit 902fceb

131 files changed

Lines changed: 5373 additions & 8 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/deploy.yml

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
name: Build, test, and deploy
2+
3+
on:
4+
push:
5+
branches: ['**']
6+
delete:
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: write
11+
deployments: write
12+
13+
concurrency:
14+
group: deploy-${{ github.ref }}
15+
cancel-in-progress: true
16+
17+
jobs:
18+
build-and-test:
19+
if: github.event_name != 'delete'
20+
runs-on: ubuntu-latest
21+
outputs:
22+
branch: ${{ steps.meta.outputs.branch }}
23+
base_path: ${{ steps.meta.outputs.base_path }}
24+
is_production: ${{ steps.meta.outputs.is_production }}
25+
steps:
26+
- uses: actions/checkout@v4
27+
28+
- uses: oven-sh/setup-bun@v2
29+
with:
30+
bun-version: latest
31+
32+
- name: Install dependencies
33+
run: bun install --frozen-lockfile || bun install
34+
35+
- name: Determine deploy metadata
36+
id: meta
37+
run: |
38+
BRANCH="${GITHUB_REF_NAME}"
39+
SANITIZED="$(echo "$BRANCH" | tr '/' '-' | tr -cd 'a-zA-Z0-9._-')"
40+
if [ "$BRANCH" = "main" ]; then
41+
echo "base_path=/" >> "$GITHUB_OUTPUT"
42+
echo "branch=main" >> "$GITHUB_OUTPUT"
43+
echo "is_production=true" >> "$GITHUB_OUTPUT"
44+
else
45+
echo "base_path=/preview/$SANITIZED/" >> "$GITHUB_OUTPUT"
46+
echo "branch=$SANITIZED" >> "$GITHUB_OUTPUT"
47+
echo "is_production=false" >> "$GITHUB_OUTPUT"
48+
fi
49+
50+
- name: Run unit and component tests
51+
run: bun test tests/catalog tests/standards tests/views tests/enhancements tests/build
52+
53+
- name: Build site
54+
env:
55+
SITE_BASE_URL: ${{ steps.meta.outputs.base_path }}
56+
run: bun run build
57+
58+
- name: Run a11y tests against built site
59+
run: bun test tests/a11y
60+
61+
- name: Upload dist artifact
62+
uses: actions/upload-artifact@v4
63+
with:
64+
name: dist
65+
path: dist/
66+
retention-days: 3
67+
68+
publish:
69+
if: github.event_name == 'push'
70+
needs: build-and-test
71+
runs-on: ubuntu-latest
72+
environment:
73+
name: ${{ needs.build-and-test.outputs.is_production == 'true' && 'production' || 'preview' }}
74+
url: ${{ needs.build-and-test.outputs.is_production == 'true' && 'https://labs.flexion.us/' || format('https://labs.flexion.us/preview/{0}/', needs.build-and-test.outputs.branch) }}
75+
steps:
76+
- name: Check out or bootstrap gh-pages
77+
env:
78+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
79+
run: |
80+
set -euo pipefail
81+
git init gh-pages-work
82+
cd gh-pages-work
83+
git config user.name 'github-actions[bot]'
84+
git config user.email 'github-actions[bot]@users.noreply.github.com'
85+
git remote add origin "https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git"
86+
if git ls-remote --exit-code --heads origin gh-pages >/dev/null 2>&1; then
87+
git fetch --depth=1 origin gh-pages
88+
git checkout -B gh-pages FETCH_HEAD
89+
else
90+
echo 'gh-pages branch missing — creating orphan.'
91+
git checkout --orphan gh-pages
92+
git reset --hard
93+
fi
94+
95+
- uses: actions/download-artifact@v4
96+
with:
97+
name: dist
98+
path: dist
99+
100+
- name: Sync dist into gh-pages
101+
run: |
102+
set -euo pipefail
103+
BASE_PATH="${{ needs.build-and-test.outputs.base_path }}"
104+
cd gh-pages-work
105+
if [ "$BASE_PATH" = "/" ]; then
106+
find . -mindepth 1 -maxdepth 1 ! -name '.git' ! -name 'preview' -exec rm -rf {} +
107+
cp -r ../dist/. ./
108+
else
109+
rel="${BASE_PATH#/}"
110+
rel="${rel%/}"
111+
rm -rf "$rel"
112+
mkdir -p "$(dirname "$rel")"
113+
cp -r ../dist "$rel"
114+
fi
115+
if [ ! -f CNAME ]; then
116+
cp ../CNAME . 2>/dev/null || true
117+
fi
118+
119+
- name: Commit and push gh-pages
120+
working-directory: gh-pages-work
121+
run: |
122+
set -euo pipefail
123+
git add -A
124+
if git diff --cached --quiet; then
125+
echo 'No changes to publish.'
126+
exit 0
127+
fi
128+
git commit -m "Deploy ${GITHUB_SHA::7} to ${{ needs.build-and-test.outputs.base_path }}"
129+
git push origin gh-pages
130+
131+
cleanup-preview:
132+
if: github.event_name == 'delete' && github.event.ref_type == 'branch'
133+
runs-on: ubuntu-latest
134+
permissions:
135+
contents: write
136+
steps:
137+
- name: Check out gh-pages (skip if absent)
138+
id: checkout
139+
env:
140+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
141+
run: |
142+
set -euo pipefail
143+
git init .
144+
git config user.name 'github-actions[bot]'
145+
git config user.email 'github-actions[bot]@users.noreply.github.com'
146+
git remote add origin "https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git"
147+
if git ls-remote --exit-code --heads origin gh-pages >/dev/null 2>&1; then
148+
git fetch --depth=1 origin gh-pages
149+
git checkout -B gh-pages FETCH_HEAD
150+
echo 'exists=true' >> "$GITHUB_OUTPUT"
151+
else
152+
echo 'gh-pages branch does not exist — nothing to clean up.'
153+
echo 'exists=false' >> "$GITHUB_OUTPUT"
154+
fi
155+
156+
- name: Remove preview directory
157+
if: steps.checkout.outputs.exists == 'true'
158+
run: |
159+
set -euo pipefail
160+
SANITIZED="$(echo "${{ github.event.ref }}" | tr '/' '-' | tr -cd 'a-zA-Z0-9._-')"
161+
DIR="preview/$SANITIZED"
162+
if [ -d "$DIR" ]; then
163+
rm -rf "$DIR"
164+
git add -A
165+
git commit -m "Remove preview for deleted branch $SANITIZED"
166+
git push origin gh-pages
167+
fi
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: Refresh catalog
2+
3+
on:
4+
schedule:
5+
- cron: '0 9 * * *'
6+
workflow_dispatch:
7+
8+
permissions:
9+
contents: write
10+
pull-requests: write
11+
12+
jobs:
13+
refresh:
14+
runs-on: ubuntu-latest
15+
steps:
16+
- uses: actions/checkout@v4
17+
18+
- uses: oven-sh/setup-bun@v2
19+
with:
20+
bun-version: latest
21+
22+
- run: bun install --frozen-lockfile || bun install
23+
24+
- name: Run refresh
25+
env:
26+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
27+
run: bun run refresh:catalog
28+
29+
- name: Open PR if snapshot changed
30+
env:
31+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
32+
run: |
33+
set -euo pipefail
34+
if git diff --quiet data/repos.json; then
35+
echo 'No changes; nothing to do.'
36+
exit 0
37+
fi
38+
DATE="$(date -u +%F)"
39+
BRANCH="catalog/refresh-$DATE"
40+
git config user.name 'github-actions[bot]'
41+
git config user.email 'github-actions[bot]@users.noreply.github.com'
42+
git checkout -B "$BRANCH"
43+
git add data/repos.json
44+
git commit -m "chore(catalog): refresh snapshot $DATE"
45+
git push --force-with-lease origin "$BRANCH"
46+
if ! gh pr view "$BRANCH" >/dev/null 2>&1; then
47+
gh pr create --base main --head "$BRANCH" \
48+
--title "Refresh catalog snapshot — $DATE" \
49+
--body "Automated snapshot refresh from the GitHub API."
50+
fi
51+
gh pr merge "$BRANCH" --auto --squash

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ dist/
44
.direnv/
55
.DS_Store
66
*.log
7+
bun.lock

CNAME

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
labs.flexion.us

README.md

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,28 @@
1-
# flexion.github.io
2-
flexion organization github pages
1+
# Flexion Labs
2+
3+
Source for [labs.flexion.us](https://labs.flexion.us/) — a public-facing site that showcases Flexion's open source portfolio, indexes our public repositories, and publishes our open source commitment.
4+
5+
## Layout
6+
7+
- `src/` — all source code:
8+
- `src/build/` — the Bun + Hono SSG build driver.
9+
- `src/catalog/` — catalog domain logic: types, loading, merging, stewardship evaluation, refresh script.
10+
- `src/design/` — the design system: all stateless UI components, CSS, assets.
11+
- `src/design/components/` — per-component directories (forms-lab pattern): `tag/`, `button/`, `link/`, `select/`, `card/`, `header/`, `footer/`, `repo-card/`, etc.
12+
- Each component has `index.tsx` (JSX), `styles.css` (CSS), `examples.tsx` (design system showcase).
13+
- CSS layers: `reset, tokens, base, compositions, layout, components, utilities`.
14+
- `src/pages/` — route entrypoints that pass data into design components.
15+
- `data/` — catalog data: generated snapshot (`repos.json`) and hand-authored overrides (`overrides.yml`).
16+
- `content/` — the words we publish, as markdown.
17+
- `docs/` — durable behavioral documentation for contributors and agents.
18+
- `notes/` — ephemeral planning and specs.
19+
20+
## Getting started
21+
22+
```bash
23+
bun install
24+
bun run build # writes static site to dist/
25+
bun test # runs the full test suite
26+
```
27+
28+
See `docs/README.md` for the project orientation.

bunfig.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[test]
2+
preload = ["./tests/setup.ts"]

content/about.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
title: About
3+
---
4+
5+
# About Flexion Labs
6+
7+
Flexion Labs is where we publish our open source work. It's curated by Flexion — a firm that helps government agencies and nonprofits modernize software that matters.
8+
9+
## Engage
10+
11+
- **Adopt** a project. Read the README, try it, open an issue if something is unclear.
12+
- **Contribute** a fix or an improvement. Every repo lists its contribution process.
13+
- **Partner** with us on new public infrastructure. Reach out through the main Flexion site.
14+
15+
[flexion.us](https://flexion.us/) is the home for Flexion the company. This site is the home for Flexion's open source work.

content/commitment.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
---
2+
title: Open source commitment
3+
---
4+
5+
# Flexion Labs open source commitment
6+
7+
*Status: Working draft. Pending delivery leadership and ownership group review.*
8+
9+
## Why we value openness
10+
11+
Open source solves practical problems. For the government agencies we serve, it eliminates vendor lock-in, reduces sustainability risk, and lowers total cost of ownership. For Flexion, it creates options — the freedom to build on proven foundations, to redirect resources from infrastructure to the problems that matter, and to demonstrate technical capability in ways closed projects never can.
12+
13+
Transparency improves quality. When code is open, more eyes find more bugs. Agencies and oversight bodies can audit how public systems work. The discipline of building in the open — knowing anyone can read the code — raises the bar for the work itself.
14+
15+
Openness compounds value across jurisdictions. Investment in one agency's solution becomes infrastructure that others can adopt. This commons-building isn't overhead — it's how we create defensible competitive advantage while empowering agencies to control their technology. Open source attracts talent who value transparency and civic impact, and contributors can become hires.
16+
17+
Openness also makes sense for the public. Publicly funded work should create reusable public infrastructure. Citizens benefit from transparency into the systems that serve them. And when agencies embrace open source, the result is higher public satisfaction with government technology. We don't ask anyone to take our word for it — the code is there to inspect, use, and build on.
18+
19+
## What we commit to
20+
21+
We are open by default. Code, architecture, and interfaces are open unless there's a specific reason otherwise — security concerns, client requirements, or competitive considerations. We will never take an open source project to a closed model. Once we release something as open source, it remains available under that license.
22+
23+
We use licensing appropriate to each project's context. Government-funded work uses public domain (CC0) to maximize reuse and avoid contractual friction. Commercial client work follows client preferences, typically proposing public domain. For projects where Flexion makes significant independent investment and maintains long-term stewardship, we use permissive open source licenses (Apache 2.0) with contributor agreements that preserve flexibility for the project's future. Small enhancements to existing open source projects follow those projects' conventions.
24+
25+
We commit to clear, professional repository standards: proper documentation, contributor guidance, legal terms, and getting-started materials. Code alone isn't enough — a project that's hard to understand or adopt isn't truly open.
26+
27+
Our competitive advantage comes from delivery expertise and proven capabilities, not from hiding code. We compete by being better at building, deploying, and supporting solutions — not by locking them down.
28+
29+
## How we operate
30+
31+
We develop in the open for projects intended to be open source. Public by default means the work is visible from the start, not just after delivery. We are mindful of security considerations and maintain clear vulnerability disclosure processes.
32+
33+
We govern our projects incrementally, starting with Flexion authority and evolving toward broader community governance as projects mature and attract use. For client work, the governance model depends on context — for traditional client engagements, operational decisions belong to the empowered client; for Flexion Solutions, Flexion governs directly.
34+
35+
Contribution processes are documented and all work is done through pull requests. We welcome contributions with clear guidance. We build our stewardship practices by dogfooding them on internal projects first, so we learn what works before applying it externally.
36+
37+
We recognize that governance stagnation — projects going dormant because no one takes ownership — is a primary risk of open source. We address this through honest communication about support levels, explicit project tiers, and a commitment to never let projects silently decay. If a project is no longer actively maintained, we say so clearly.
38+
39+
## What we steward
40+
41+
We recognize that resources are finite and not all projects warrant the same level of investment. We support a tiered approach to stewardship, with honest communication about what we will and won't provide for each project.
42+
43+
For actively maintained projects, we commit to security patch management and defined response commitments. For projects available as-is, we say so clearly. We don't over-promise maintenance. Abandoned repositories damage credibility and create a security risk — if we can't maintain something, we explicitly archive it rather than letting it decay silently.
44+
45+
Open source work is funded primarily through consulting engagements with clients who value openness. We also make strategic investments in projects where the business case warrants it — where open source creates market opportunities, builds community, or strengthens civic infrastructure. Different projects use different funding models: traditional hourly billing, retainers, maintenance within team structures, grants, and partnerships.
46+
47+
## Maintenance tiers
48+
49+
- **Active** — Flexion commits to security patch management and defined response commitments. Bug reports are triaged. Pull requests are reviewed on a predictable cadence.
50+
- **As-is** — Available without active maintenance. The code works (or worked at one point); future updates are not promised.
51+
- **Archived** — No longer maintained. The GitHub archive flag is set. The repo is read-only. Listed for transparency.
52+
- **Unreviewed** — A human has not yet classified this repo. Defaults to this state; visible on the site so gaps are honest.

content/home.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
hero: Public infrastructure, in the open.
3+
intro: Flexion Labs gathers our open source work in one place — products we steward, tools we share, and the commitment behind them.
4+
---

content/work/document-extractor.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
title: Document Extractor
3+
summary: Turn PDFs and images of forms into structured data — without vendor lock-in.
4+
---
5+
6+
## What it solves
7+
8+
Agencies receive millions of scanned forms every year and pay commercial vendors to turn them into structured data. Document Extractor provides an open alternative that agencies can deploy, audit, and extend.
9+
10+
## Who it's for
11+
12+
Teams modernizing paper-based intake workflows. Works on scanned PDFs, phone-camera photos, and faxes.
13+
14+
## Status
15+
16+
Active. Deployed with agency partners.
17+
18+
## Get started
19+
20+
The repository documents supported document types, extraction models, and how to extend the pipeline.

0 commit comments

Comments
 (0)