Generate a PDF report from a BCF (Building Collaboration Format) .bcfzip file.
Supports BCF 2.1 and 3.0. Read-only — the tool never modifies the input.
Ships as two surfaces:
- A Python CLI (
python -m bcf_report) for local use. - A Next.js web app deployed to Vercel that accepts a
.bcfzipupload and returns a PDF. Uses Vercel Blob storage for client-side uploads, which lets it handle files well beyond Vercel's 4.5 MB serverless body limit.
Both surfaces reuse the same bcf_report Python package (parser + ReportLab renderer).
Deployed on Vercel. The flow is:
- Browser picks a
.bcfzip, uploads it directly to Vercel Blob via@vercel/blob/client(token minted byapp/api/upload/route.ts). - Browser POSTs
{ blobUrl, filename }to/api/report(Python serverless function). - Python function downloads the blob, parses it, renders the PDF, and streams it back with
Content-Disposition: attachment. - Browser triggers a download of the resulting PDF.
Set by Vercel when you enable Blob storage on the project:
BLOB_READ_WRITE_TOKEN— created automatically by the Blob integration;app/api/upload/route.tsreads it via@vercel/blob.
npm install
# BLOB_READ_WRITE_TOKEN must be exported for client uploads to work locally
npm run devcd C:\Users\Gustavo\bcf-report
uv venv
uv pip install -r requirements.txtuv run python -m bcf_report path/to/file.bcfzip
# or with a custom output path:
uv run python -m bcf_report path/to/file.bcfzip -o my-report.pdf
# or with a custom report title:
uv run python -m bcf_report path/to/file.bcfzip --title "Coordination Report - Q2"By default the PDF is written next to the input as <input-stem>-report.pdf.
- Cover page — project name, BCF version, topic count, generation date.
- Aggregate stats — counts by Status / Priority / Type / Assignee, plus a bar chart of topics per status.
- Topic summary table — one row per topic (Title, Status, Priority, Type, Assignee, Due Date).
- Per-topic detail pages — metadata, description, full comments history, and embedded viewpoint snapshots.
uv run python tests/fixtures/make_sample.py
uv run python -m bcf_report tests/fixtures/sample.bcfzip -o sample-report.pdf
uv run python -m pytest tests/bcf-report/
├── app/ # Next.js App Router (web frontend)
│ ├── page.tsx # upload UI
│ ├── layout.tsx
│ ├── globals.css
│ └── api/upload/route.ts # Vercel Blob client-upload token handler
├── api/
│ └── report.py # Vercel Python serverless: blob -> PDF
├── bcf_report/ # shared Python package (parser + renderer)
│ ├── models.py
│ ├── parser.py
│ ├── report.py
│ └── __main__.py # CLI entry
├── tests/ # pytest suite + synthetic .bcfzip fixture
├── requirements.txt # Python deps (reportlab, Pillow)
├── package.json # Node deps (next, react, @vercel/blob)
├── vercel.json # runtime + includeFiles for the Python function
├── next.config.mjs
└── tsconfig.json