Turning 300-Page Legal PDFs into a Data Product: the Franchise Signal Architecture

A technical overview of an end-to-end pipeline - ingestion, LLM extraction, scoring, RAG, and an MCP server - built to modernize franchise due diligence and reduce information asymmetry for prospective franchisees.

Share
Turning 300-Page Legal PDFs into a Data Product: the Franchise Signal Architecture


The Domain Problem: What is a Franchise Disclosure Document (FDD)? What are the Challenges of Franchise Diligence?

As a former franchisee who started, operated, and sold a home services franchise business (and has read hundreds of FDDs), I have first hand experience with the challenges involved in franchise diligence.

We all know the big food franchises - Jersey Mike's, Jimmy Johns, Taco Bell. Beyond restaurants, there are thousands of additional concepts in fitness, home services, pet care, etc. Collectively, U.S. franchise systems drive an estimated $936 billion in annual economic output through the sale of goods and services. But how does someone evaluate a franchise system? Is the franchise model the "proven playbook" that is often claimed?

FDDs: The Closest Thing Franchising Has to a “10-K”

Every franchise system is required to publish a Franchise Disclosure Document (FDD) annually. For prospective franchisees, the FDD is the closest equivalent to a 10-K filing in public markets.

It includes 23 standardized disclosure items designed to answer key diligence questions such as:

.. What does it cost to open Franchise {X}?

.. What financial performance claims are disclosed (if any)?

.. How many units opened or closed last year?

.. What fees and royalties does the system charge?

These documents are typically 300+ pages long and distributed as PDFs. They are dense, unstructured, and vary significantly in formatting, tables, and level of transparency.

Franchise Signal
How Franchise Signal Is Built
Various states maintain public registries of ~300-page Franchise Disclosure Document (FDD) PDFs for 1,000+ franchise brands. Franchise Signal turns thousands of filings into structured data, disclosure scores, a retrieval index, and MCP tools — accessible to prospective franchisees, attorneys, lenders, and business owners.
Azure Services (Durable Functions)Azure Open AI (Foundry)MCPC# / .NETReact + custom SSR
Sources
Ingestion — .NET jobs
Processing
Data layer
Serving
new filings
1

State filing registries

FDD registration portals
WisconsinDFI FDD registry
MinnesotaCARDS FDD registry
1,000+brands tracked
~300+pages per filing
Annualfilings
2

Registry poll jobs

Poll each state portal, detect new filings, and download the raw PDFs.

Azure Blob · raw filings
3

Promotion job

Validates and dedupes each filing (across states), promotes it to the canonical filing store, writes the filing record metadata to Azure SQL, and enqueues processing.

Azure Blob · canonicalSQL record(s)Queue message(s)
Azure Durable Functions
Orchestration layer · fan-out processing
4

Shallow processing

Queue-triggered on promotion. Reads the first five pages → sector + investment range, so a basic brand profile is built without the expense of full processing.

5

Full processing

Deep dive 2

This is the core logic: full text extraction, LLM segmentation and activities to parse into Items 1–23, Azure Document Intelligence table parsing, per-item reconstruction, Azure OpenAI extraction.

6

Index & embed

Enqueued when extraction completes. Chunks and embeds each item, upserts Azure AI Search keyed on brand and filing year (for downstream RAG).

7

Item 19 scoring

Deep dive 3

LLM Extraction of Item 19 facts combined with parsed Item 20 table data and deterministic scoring. Runs as an in-pipeline activity and as a backfill job.

Blob Storage

Raw downloads · canonical filings · reconstructed per-item artifacts (text + tables, Items 1–23).

Source of truth

Azure SQL

Normalized item data (e.g. litigation cases, investment line items, median revenue, and outlet growth and churn).

Structured & queryable

Azure AI Search

Per-item chunks + vectors, one document per (brand, filing year) — for RAG query.

Azure Web App
One deployment · React + C#/.NET APIs
franchisesignal.com

React front end + custom SSR

A custom server-rendering pipeline makes every brand page crawlable — SEO is the top of the funnel. Brand pages, YoY changes, analytics.

RAG

Natural Language FDD Query

A query-processing pipeline handles diligence queries (and query structuring), retrieves and ranks per-item chunks, and answers with cited data.

MCP connectorIn Claude

MCP Server

Hosted in the same web app. Tools return structured SQL data and per-item blob artifacts to Claude for deep diligence.

Prospective Franchisees & Attorneys · Operators
Click the diagram to enlarge ↗

The Challenges With Franchise Diligence

Buying into a franchise is a six-figure(+) investment, with strict contractual terms, potential liquidated damages, and a range of diligence considerations:

1. Access and Sourcing: Where and how do you obtain the latest FDDs? How can you review this information prior to a brand conversation?

2. Extraction and Interpretation: How do you quickly pull out investment ranges, fees, Item 19 financials, outlet growth and churn data, and other key stats?

3. Connecting the Dots: How do Items 3, 6, 7, 19, and 20 interact to form a realistic view of unit economics and risk? How has a brand changed contract terms year-over-year? How does a given system compare to another? Is the franchise model more viable than an independent or corporate model?

Frankly, the interpretation is the big one... an LLM gives you better answers with better context, and the same applies when conducting due diligence and understanding an FDD.

All of this is where Franchise Signal comes into play. Franchise Signal:

  • Ingests thousands of FDDs from various state filing registries, all in an idempotent fashion with deduplication across state registries.
  • Extracts the 23 standard Items that each franchise system must disclose so that the data can be used downstream.
  • Structures the data and provides analytics and exposed data in the form of brand profiles, YoY changes, aggregated analytics, scoring, RAG, and an MCP server.
Modernizing Franchise Research: Analytics, Benchmarking, and Diligence
We all know the big food franchises - McDonald’s, Jimmy Johns, Taco Bell. Beyond restaurants, there are thousands of additional concepts in Fitness, Senior Living, Home Services, Pet Care, etc.

Ingestion - Pulling in (and organizing) thousands of FDDs

Franchise Signal starts by polling various state registries for FDDs. We pull each PDF directly into Azure Blob storage. This process is run as .NET jobs. Each state repository has its own structure so the jobs are specific to scraping (and being cognizant of throttling).

One a filing has been downloaded, we have a promotion Job (.NET/C#) that is responsible for creating a canonical location for each brand. The biggest challenge here is de-duplication and standardized naming. A brand can be named differently across state registries, so we have a mapping file (manually constructed) that resolves brands and promotes in a specific order.

This de-duplication and promotion is idempotent so that the job can run anytime as needed.

Shallow Processing - Building a full Brand Directory

When we promote a PDF we also enqueue (via Azure queue storage) a message for shallow processing.

A lightweight Azure durable function picks up the brand to process (queue trigger), extracts the first five pages of data, and parses out key summary data (investment and business purpose). We also make a light call to Azure Open AI (Azure Foundry) to classify the brand primary and secondary sectors.

Full processing (outlined below) is monetarily expensive. This "shallow processing" lets us build a full brand directory with investment ranges, categories, filing data, and history.

Franchise directory with FDD-backed franchise data | Franchise Signal
Search the Franchise Signal directory of franchise brands by name or sector. Explore investment ranges, fees, outlet counts, and other FDD-backed data.

Full Brand Filing Processing Pipeline

Processing a full brand-year is monetarily expensive. A single call to extract tables in a 300+ page PDF with Azure Document Intelligence can be ~$5 to $10 for a single brand year (without considering all of the other LLM calls, etc). As such, full brand-filing processing is gated behind a custom admin control plane or a customer request.

Processing involves extracting all text (via pdfpig), arranging each item (1 to 23 of an FDD), extracting all tables into JSON (via Azure Document Intelligence), and then combining all JSON tables and extracted text into a per item folder structure (Azure Blob).

Determining the boundaries of where items start and end and getting the precise text and table extraction is technically complex. Edge cases in presentation, table formats, headers, footers, etc - all add up quickly when creating an extraction pipeline across thousands of filings. A QSR brand vs a gym vs a home service company may all have dozens of tables scattered across hundreds of pages - with tables and headers repeating (or not) or spanning multiple pages.

Extraction and normalization from raw text into Azure SQL - and something that can be queried, aggregated, scored, etc all requires complex LLM prompts, a schema built over many iterations, and processing strategies and a fan out approach.

All of the full processing is done as part of an Azure durable function and is outlined in more details (expandable diagram below).

Franchise Signal
FDD Processing Deep Dive
The Franchise Disclosure Document (FDD) Processing Pipeline
An Azure durable function orchestrates processing of a ~300-page PDF into per-item structured data that becomes available downstream.
Azure Durable FunctionsAzure OpenAIAzure Document Intelligence
From Customer UX

Brand Year Filing

An admin (or user purchase) triggers a brand-year filing process. A queue message serves as the trigger to start one orchestration instance per filing.

Per-Filing Stats

~300pages of dense legal text (PDF)
23FDD items to split and parse (Exhibits are bundled into one group)
~100+tables parsed into JSON and metadata
Full-processing orchestration
One instance per brand-year filing · ~10 activities and parallel processing · Admin control plane and logging
1

PDF Text Extraction

Pull the complete text layer for all ~300 pages, indexed by pdf page.

2

LLM Document Segmentation

A series of LLM calls and custom C# processing locates item boundaries and splits the filing into Items 1–23 (this is the primary complexity).

Azure OpenAI
3

Table Extraction

Azure Document Intelligence returns every table as structured JSON (primary $ cost per filing is this API call).

Azure Document Intelligence
4

Items and Table Metadata

Create and tag metadata for each JSON table to store each item's text and tables together.

Azure Blob · per-item
5

Extract & Normalize

Per-item processing strategies make LLM calls to extract and normalize specific item data (e.g. outlet counts, investment ranges, revenue figures) into Azure SQL.

Azure OpenAIParallel processing
6

Complete & Enqueue

On completion the orchestrator enqueues downstream RAG Index & Embedding processing and calls the Item 19/20 scoring activity for new filings.

Azure Queue
2nd durable function

Index & Embed

Chunks each item, embeds it, and upserts the Azure AI Search document (for brand and filing year) which is served for the downstream RAG web app.

Azure AI Search

One searchable document per (brand and filing year), chunked and embedded by item.

Azure Blob per-item artifacts

Items 1–23 with text and tables grouped for any processing and to be served through MCP.

Azure SQL normalized data

Defined and comparable fields per item (investment line items, outlets, litigation cases)

Deep dive 3

Item 19 & Item 20 Scoring

Activity call uses the scoring library as any new filings are processed.

Click the diagram to enlarge ↗

Presentation Layer - Web UX, RAG, and MCP

After processing hundreds of brands - many over a multi-year period - we have a data repo that consists of Raw PDFs (the FDD filings) in Azure Blob, the per-item text and extracted table JSON and metadata also in Azure Blob, and the structured Azure SQL data that can be normalized across brands.

How do we present this to folks doing diligence or analyzing franchises?

Web UX: this is the primary option - we have brand specific pages that show year-over-year trends (investment ranges and financial data), ongoing litigation cases and history, and page specific call-outs on how to interpret the data. A brand page for Crumbl is here.

Having data structured and normalized also allows for web based presentation of aggregated analytics. For example, "which brands had the highest churn rates over the last three years?" is now accessible via a dashboard.

RAG: users can ask a question directly in the web app for a brand/year. For example "what was the median revenue for a Crumbl franchise in FY 2025?"

MCP: this is one of the primary benefits for users performing diligence. Having multiple years' worth of filings across brands allows a user to build financial models, run skills, perform trend analysis and comparison - all without overloading the context of uploading dozens of 300 page PDFs into Claude.

Scoring a Franchise Brand

Scoring is a "philosophical challenge" just as much a technical one.

Crumbl Item 19 and Item 20 Franchise Signal Disclosure Score

How you compare a bakery and a plumbing franchise? The skills involved, the brand, territories available, support, franchisee satisfaction, system growth and churn, and system financials... all of these are signals. A "franchise" at the end of the day is a legal structure and does not magically offer an "apples to apples" comparison among brands. Should a franchise model even be entertained when considering business ownership?

As such we have developed the Franchise Signal Disclosure Score. How we extract, compute, and render history of this score per brand per year is complex and showcases the full range of extracted data, LLM calls, deterministic models, and eval sets.

This is outlined in a deep dive (expandable) below.

Franchise Signal
Deep dive 3 of 3
Inside the Franchise Signal Disclosure Score
Of all franchise units that operated throughout the year, what percentage are included in Item 19 financial performance representations? How do you use LLMs to extract the numerator(s) among complex varying formats, tables, and presentation to create a reproducible franchise score?
Azure OpenAIAzure Document IntelligenceEval Sets
Azure Blob · per-item

Per-item artifacts

The Item 19 and Item 20 artifacts (text + tables) are produced by upstream processing and extraction.

Azure SQL

Item 20 denominator

Item 20 Table 3 from the FDD supplies the outlet counts — start, opened, terminated, ceased, end. This is extracted and persisted upstream of scoring/extraction and as such the Scoring LLM already has the denominator.

Two entry points

1
Activity and Library Call in full processing with new filings scored on process.
2
Backfill job runs on demand to re-score or initially populate brands.
Stage 1 · Azure OpenAI

LLM Extraction

Reads the Item 19 + Item 20 artifacts and emits defined schema disclosure facts with evidence (populations, ownership, metrics, reporting periods, grain). It only extracts numerator populations among charts, tables, text, and footnotes.

It does not perform scoring.

Confidence and any parsing/ambiguity issues travel with the extraction schema and payload.
Stage 2 · Deterministic Scoring

Deterministic Scorer

FranchiseScoring.Core reconciles the disclosed numerator against the Item 20 denominator: coverage % = included ÷ operated-during-period, and an exclusion breakdown that sums to the gap.

Same facts in → same score out, every time.

Persisted per-brand-filing Disclosure Score

Score document (classification, %, exclusion breakdown, confidence, review notes) plus a run artifact holding both stages’ full JSON. Full scores are gated for paying customers, ranges are displayed in the UI for anonymous visitors.

Score Result Classifications

Scored — the coverage %, shown raw: 92.1% … 18.7% …
AffiliateOnlyFranchisesHidden — 0.0% · had a franchised base, showed only affiliate results
OperatorGrainUnscoreable — n/a · disclosed revenue, but not unit-mappable
ScoreUnavailable — n/a · FPR present, figures we couldn’t retrieve (for example financials in separate exhibit)
AffiliateOnlyFirstYear — n/a · no franchised base operated yet
NoItem19Fpr — n/a · no FPR at all — treated as a red flag
This taxonomy ensures consistency, reproducibility, and a basis for transparency on “how” the score is generated.

Review Queue

All scores stored as JSON and in SQL for queries and highlighting any low confidence scores for manual review.

Guardrails

Multiple rules, flags, and confidence intervals
Eval Fixtures
20+ brand-year filings scored and JSON lives with test infrastructure to exercise variability and edge cases among filings.
Three test layers
Deterministic scorer evaluations · frozen-extraction evaluations · a live end-to-end regression that can be run anytime LLM prompts updated and/or scoring rules updated.
“Human in the Loop”
Low confidence scores or anything unusual (score > 100%) are flagged for review.
Click the diagram to enlarge ↗

SEO & Distribution

This is the "real" challenge. In the age of AI being available to everyone, we all compete and must continue to elevate beyond being seen as a "wrapper" for AI.

Marketing to prospective franchisees - and convincing them to pay for analysis of public data - to potentially hear what could be perceived as an "expensive no" - is a challenge unto itself when folks already have an FDD and a Claude subscription.

There is a lot to discuss on this broader topic - for technical SEO purposes, Franchise Signal makes use of a custom rendering pipeline to ensure that our front end React is optimized for LLMs and crawlers.

Next Steps and Connecting

Franchise Signal exists because there is an information asymmetry present for those conducting due diligence on a franchise. An FDD is not a "click through" contract. It has serious investment ramifications, ten year(+) contracts, liquidated damage clauses, termination and exit details, and a host of considerations.

There is not a "3 year financial statement requirement" like that of a 10-K for a franchisor disclosing their Item 19 Financial Performance Representations. Prospective franchisees need to actively seek out multiple years worth of filings in order to "stitch together" historical trends and patterns. Franchise Signal continues to offer updated filing data, analytics, and diligence packages.


I am currently exploring sales engineering and forward-deployed engineering roles to work at the intersection of real world domain problems, top down strategy, and bottom up AI implementation experience. I would welcome an opportunity to connect if this sounds like a fit for your team.