THE DOCUMENTATION PROBLEM IN SALESFORCE ORGS
Every mature Salesforce org has the same documentation problem: the real architecture of the system exists only in the metadata, and nobody has time to document it.
There are custom objects nobody remembers creating, validation rules with no description, Flows that reference fields that were renamed two years ago, Apex classes with no comments, and permission sets that have accumulated permissions like barnacles. The org works — mostly — but onboarding a new developer takes weeks, and nobody can answer "what does this field actually do?" without spending an hour in Setup.
We've been in this situation on every enterprise Salesforce project we've worked on. The documentation that exists is out of date. The documentation that's accurate is in someone's head and leaves when they do.
SF Docs Portal was our answer to this.
THE CORE IDEA
Salesforce stores everything as metadata — XML files in a structured directory format that you can pull into a Git repository with the Salesforce CLI. Object definitions, field configurations, Apex code, Flow XML, permission sets, profiles, custom labels, all of it.
That metadata is the source of truth for the org. It's also machine-readable. So instead of asking developers to write documentation, we read the metadata and generate it.
SF Docs Portal takes a Salesforce SFDX project repository as input and outputs a static HTML documentation site. No runtime server. No database. No configuration file required — it reads the project structure directly and infers everything it needs.
WHAT GETS GENERATED
From a standard SFDX repository, the tool generates documentation covering:
- Data model — every custom object, every field, its type, whether it's required, its formula or picklist values, and which page layouts it appears on
- Security model — permission sets, profiles, field-level security across the org
- Automation inventory — Flows, Process Builder automations, Apex triggers, and validation rules, organized by object
- Apex library — class documentation extracted from docblock comments, method signatures, and test coverage indicators
- UI components — LWC and Aura component inventory with dependencies
- Architecture overview — a cross-reference of which objects, automations, and classes are connected
The output is a fully static site — just HTML, CSS, and a small JavaScript search index. It can be hosted on GitHub Pages, Netlify, or any static file server for essentially nothing.
THE SEARCH PROBLEM
Documentation is useless if you can't find things. A Salesforce org with 200 custom objects and 3,000 custom fields generates a lot of pages.
We built client-side search using a pre-built index — at generation time, the tool creates a JSON search index of every documented entity, its type, and its description. The search UI does a fuzzy match against this index in the browser with no server call. For org sizes we've encountered, the index stays under 2MB and search returns results in under 50ms.
For very large orgs where the search index would get unwieldy, we added an optional split-index mode that loads sections of the index on demand. We haven't needed this in practice yet, but it's there.
RUNNING IT IN CI
The most useful deployment pattern is running SF Docs Portal in CI. Every time a pull request merges to main, the docs regenerate and redeploy automatically. The documentation is never more than one deployment cycle behind the actual org.
This is the key insight that makes generated docs worth having: they stay current automatically. Written documentation rots because nobody remembers to update it. Generated documentation is always accurate because it reads the same source the org is deployed from.
The CI setup is straightforward — the tool runs as a Node script, takes the repository path as an argument, and writes the site to an output directory. Standard GitHub Actions or equivalent CI can handle the rest.
LIMITATIONS
Generated documentation has a ceiling. It can tell you what fields exist and what type they are. It can't tell you why a business decision was made, what the edge cases are in a particular Flow, or what the original developer intended by a field named Custom_Flag_1__c.
For that, you still need humans. SF Docs Portal adds a layer on top of the generated docs — optional markdown description files that get merged into the generated output. If a developer writes a `DESCRIPTION.md` for a class or object, it appears in the docs alongside the auto-generated content. The generated part stays current automatically; the human part stays where it's written.
The combination — auto-generated structural documentation plus optional human narrative — is more useful than either alone.