Conn2Flow documentation has a single source: the Markdown files in ai-workspace/<lang>/docs/ in the Core repository. The public website (/docs/) is generated from them; nothing is written directly in the admin panel.
The golden rule is that the code is the authority. A doc only counts once it has been checked against the code, and the commit of that check is recorded in it.
Where each doc lives
ai-workspace/<lang>/docs/
├── index.md docs home page
├── guides/ task-oriented walkthroughs
├── concepts/ how the system works and why
├── reference/
│ ├── libraries/ one doc per gestor/bibliotecas/<name>.php
│ ├── modules/ one doc per gestor/modulos/<id>/
│ ├── api/ cli/ hooks/
└── whats-new/ release highlights-
Folders and file names are identical in both languages.
pt-br/docs/guides/x.mdpairs withen/docs/guides/x.md. That is what links translations and defines the URL (/docs/guides/x/). -
Write both versions in the same pass, with the same context in mind. There is no "translate later".
-
The UPPERCASE files at the root of
docs/are legacy. When a subject is migrated, the new doc is born in the tree above and the matching legacy file is removed.
Frontmatter
---
title: "modelo.php library"
description: "One sentence: shown in indexes, social sharing and llms.txt."
section: reference # guides | concepts | reference | whats-new (same as the folder)
order: 20 # position in the menu (default 100)
visibility: public # public (default) | restricted (reserved)
label: "HTML templates" # optional: short menu label (libraries)
module: menus # optional: id of the documented module
sources: # required in reference/: the code this doc describes
- gestor/bibliotecas/modelo.php
verified_at: 86350986
---sources and verified_at are what make drift measurable: if any source changes after verified_at, the doc climbs the docs:audit ranking.
In the menu, a module doc shows the module name from the modulos table (the nome in gestor/db/data/ModulosData.json, in the doc language); the others use label, or title when there is no label. Library and module pages show at the top the code path from the Gestor root (bibliotecas/<lib>.php, modulos/<id>/), built by docs:build.
How to write a doc
-
Read the code before the old text. For a library, read the whole file, its callers (
grep -rn "function_name(" gestor) and its tests. For a module, read<id>.php,<id>.json, the JS, the widget (<id>.widget.php), theresources/(pages, templates,ai_modes), the table migrations and the hooks. -
Describe the actual behavior, including the surprising parts: case sensitivity, first occurrence only, defaults, what happens when something is missing. When the code contradicts its own docblock, the doc follows the code and points out the mismatch.
-
Flag legacy. Functions without callers, functions that call something that does not exist and dead options are useful information, not embarrassment.
-
Show an example taken from a real use in the core, whenever one exists.
-
Fill in
sourcesandverified_atwith the current commit (git rev-parse --short HEAD).
Available callouts (rendered as colored boxes on the website):
> [!NOTE]
> Additional information.
> [!TIP]
> Shortcut or good practice.
> [!IMPORTANT]
> Something that changes the outcome.
> [!WARNING]
> Risk of error.
> [!CAUTION]
> Security or data-loss risk.Links between docs are relative and point to the .md file (../modules/menus.md). The build turns them into website URLs and fails when the target does not exist.
Reference generated from the code
Docs in reference/libraries/ end with a generated block:
C2FFUNCTIONREFERENCEBLOCK
-
php cli/c2f.php docs:extract modeloregenerates themodelo.phpblock in both languages. -
php cli/c2f.php docs:extract --all --checkfails when any block is stale. -
php cli/c2f.php docs:extract 2fa --createscaffolds the doc for a library that is not documented yet.
Do not edit inside the block. The text outside it is yours, and the audit warns you when a function in the code is not mentioned in the text.
The routine: docs:audit
php cli/c2f.php docs:audit # ranking (top 30)
php cli/c2f.php docs:audit --limit=0 # everything
php cli/c2f.php docs:audit --json # for tooling
php cli/c2f.php docs:audit --strict # exit 1 on errors (CI)The ranking adds 10 points per error and 3 per warning. The command checks:
-
frontmatter;
-
language pairs;
-
missing sources;
-
sources changed after
verified_at; -
broken links;
-
stale extracted blocks;
-
unexplained functions;
-
libraries and modules without docs.
On every agent pass over the documentation:
-
Run
docs:auditand take the top items. -
For each item, read the code in depth and rewrite both languages.
-
Run
docs:extract --allanddocs:auditagain until the item leaves the ranking. -
Publish locally with
docs:build(below) and check it in the browser.
Publishing to the website: docs:build
php cli/c2f.php docs:build --project=conn2flow-site-local --dry-run
php cli/c2f.php docs:build --project=conn2flow-site-local-
Configuration: the command reads the
docskey of the project'sdocumentationmodule manifest (gestor/modulos/documentation/documentation.json) or, without it,docs.config.jsonin thegestor/folder. It sets the languages, base path, layout, which publisher receives each section and the sidebar menu id. With the module, generated pages belong to it, thedocs-articleanddocs-sidebartemplates are looked up first in the module resources and each build writesdocumentation.status.jsonin the module folder, shown by the module screen in the panel. Regeneration always happens through the CLI, in the development environment. -
What gets generated: the Markdown becomes HTML with Tailwind classes and is written as the project's system resources:
-
publications (
publisher_pages); -
pages with a
publisher_id; -
the sidebar menu;
-
llms.txt.
-
-
Publishing: from there the path is the same as any resource. Run
project:update-allto sync and rebuild the CSS in the local environment. The production deploy is done by the operator.
Core SDD source
When the configuration sets "sdd": {"enabled": true}, the same build includes public documents from conn2flow/sdd/ at /docs/sdd/ under the docs-sdd publisher. This source is available in Portuguese only and derives titles, descriptions (as plain text, without Markdown markup), and order from Markdown without frontmatter. Each folder's archive/ is published as an "Archive" subgroup at the end of the folder in the menu; the build skips backlog/, memory files, and SDD from projects. Before producing pages and llms.txt, it replaces paths, IP addresses, emails, hosts, and private project names; files containing credentials or private keys are excluded with a build warning. Review the --dry-run warnings before publishing.
See also
-
modelo.php library: an example of a library reference doc.
-
Menus module: an example of a module doc.