Why the Data Dictionary Comes First
Ask an AI coding agent to build an asset management module and it will produce something. The question is whether that something matches your data. Without a data dictionary, the agent invents column names, picks types by habit, decides which fields are nullable, and guesses how entities relate. Every guess is a divergence you later have to find and correct.
A data dictionary removes those guesses. It is a compact, unambiguous description of the domain: the entities, their fields, the types, what may be empty, how they connect, and the rules that constrain them. Where a prompt explains what you want to build, the data dictionary states what the data is. That is the part an agent cannot derive from a nice paragraph.
It is also efficient. Prose guidance is expensive context: it takes paragraphs to say what a table says in a line, and every extra sentence competes for the agent's attention. A data dictionary is dense and high-signal. It spends its tokens on facts the generator will actually use — names, types, relationships — instead of narrative the generator has to interpret. When context is a budget, the dictionary is the best return on it.
In this workflow the data dictionary is the one artifact a human writes by hand: .ai-assisted/DATA-DICTIONARY.md. It holds the application name and short name, the persona (Admin, Member, or Guest), and the main features with a Group-to-SubGroup taxonomy and a stage enum. Everything downstream — FEATURE.md and PRD.md — is generated from it. That is why it is worth writing carefully: a mistake here propagates through the whole build.
Write once, generate many times
You fill exactly one file, then tell the AI start the development. The data dictionary is the human input; the feature list and the PRD are generated. The more precise the input, the smaller the correction cost later.
What Goes In It
A useful data dictionary is boring and complete. It answers six questions for every entity and every field.
Entity names and types
List each entity and classify its shape before you describe its fields. A Pure Master has no foreign key and no child collection. A Master with Lookup declares a foreign key plus a navigation property. A Master-Detail declares a collection of child items. The shape determines how many files the generator produces, so deciding it once in the dictionary prevents inconsistent guesses across features.
Fields, types, and nullability
For each field give the business name, the type, and whether it can be empty. Nullability is a design decision, not a default: an optional note is string?, a required name is string, an optional timestamp is DateTimeOffset?. State it explicitly, because an agent that has to choose will usually choose the permissive option and quietly allow bad data.
Relationships and foreign keys
Name the parent and the child. A lookup is written as a string foreign key such as AssetModelId plus a nullable navigation such as AssetModel?. A master-detail relationship is written as ICollection<T>? Items on the parent. When the relationship is explicit, the generator can wire up the endpoint, the dropdown, and the persistence without asking.
Enums and stage lifecycles
Enumerate the allowed values and, where relevant, their order. The Asset Manager example uses an AssetStage lifecycle: ReadyToAssigned, then Assigned, then Repair, then Quarantine, then Missing. Writing the sequence down matters because the first enum in a feature is rendered with Tom Select while later enums use radio cards — a control choice that depends on this ordering.
Validation rules
Attach the constraints to the fields: required, maximum length, numeric range, format. These become FluentValidation rules, not database attributes, because the database stays open in this standard. A dictionary that says "quantity must be positive" is the difference between a guard clause the agent writes and a bug it ships.
From Business Column to C# Type
The dictionary fixes both the type and the control in one place. The mapping below is the whole point: for each business meaning there is exactly one C# type and exactly one UI control.
| Business meaning | C# type | UI control |
|---|---|---|
| Short text | string |
Text input |
| Long note | string? |
Textarea |
| Amount or value | decimal |
Range slider |
| Yes / no flag | bool |
Form-switch |
| Optional date | DateTimeOffset? |
Flatpickr date |
| Optional time | TimeSpan? |
Time input |
| Fixed choice set | enum |
Tom Select (first) or radio cards |
| Reference to a master | string {X}Id + navigation |
Lookup dropdown |
| Child rows | ICollection<T>? Items |
Detail grid |
| Generated document number | string? AutoNumber |
Read-only text |
Four types are deliberately forbidden: long, Guid, DateTime, and int. They either expose storage details or lose the offset auditing needs. Derived values such as totals are computed for display, never stored as columns. Putting the allow-list and the forbidden list in the dictionary means the agent never has to choose a type — it only has to read one.
The DATA-DICTIONARY.md Input
A dictionary entry is deliberately plain. It names the application, the persona, and each feature group with its subgroups, and it records the stage enum once:
Application: Asset Manager
Short Name: AM
Persona: Main
Feature Group: Asset Registry
SubGroup: Asset Models
- AssetModelGroup (Pure Master)
- AssetModel (Master with Lookup -> AssetModelGroup)
SubGroup: Assets
- Asset (Master with Lookup -> AssetModel)
Stage Enum: AssetStage = ReadyToAssigned, Assigned, Repair, Quarantine, Missing
The developer writes the dictionary once, then issues a single instruction: start the development. That command hands control to ORCHESTRATOR.md, which first runs Gate 0. Gate 0 checks the AppSettings:Name value in appsettings.json. If it reads Indotalent, the workflow proceeds; otherwise it stops, because the application has been customized and the developer is in maintenance mode.
Assuming Gate 0 passes, the orchestrator reviews the data dictionary and the pipeline runs: Phase 0 generates FEATURE.md, the business source of truth; Phase 1 runs PROMPT.md to turn that into PRD.md, the technical blueprint; Phase 2 builds the app feature by feature, running dotnet build and fixing every error until there are zero. The dictionary is upstream of all of it.
Help Us Grow
Love this guide? Explore our ready-to-use enterprise starter kits built with ASP.NET Core and Vertical Slice Architecture.
A Worked Example: Asset Manager
The Asset Manager example app is used to demonstrate the workflow end to end. It is a real ASP.NET Core application built from this pipeline, and it is not the Indotalent webstore. Its dictionary lists the entities Branch, Department, Manufacture, Vendor, Depreciation, AssetModelGroup, AssetModelSubGroup, AssetModel, Asset, and Employee, organized under a Group-to-SubGroup taxonomy.
The lifecycle and numbering rules are part of the same document. AssetStage moves through ReadyToAssigned -> Assigned -> Repair -> Quarantine -> Missing. Every entity carries an AutoNumber, generated through IHasAutoNumber in the format {ToShortNameConsonant(3)}/{Year}/{4-digit}, with prefixes such as Branch BRN, Manufacture MNF, Vendor VND, AssetModel AST, and Asset ASS. Masters also support image and file attachments, which the dictionary records as part of their definition.
Because the shape and the numbering are stated up front, the generated PRD can order the backlog correctly: Pure Masters such as Branch and Vendor come first, masters with lookups such as AssetModel follow once their parents exist, and detail-bearing entities come last. Nothing in that sequence has to be discovered by trial and error.
Written this way, the dictionary reads like a data model that just happens to be prose. That is exactly what an agent needs before it generates a single class.
Vague dictionary
- • "Asset value" with no type
- • Nullability left implicit
- • Relationships described in prose only
- • Enum values listed without order
Precise dictionary
- •
decimal PurchaseValue, range slider - • Every field marked required or optional
- • Lookup FK plus navigation named
- • Stage enum written in lifecycle order
Key Takeaways
- The data dictionary is the highest-leverage context you can give an AI agent; it states what the data is, not just what you want.
- Include entities and their shapes, fields, types, nullability, relationships, enums, and validation rules.
- Fix the type and the UI control together, using the allow-list and forbidding
long,Guid,DateTime, andint. DATA-DICTIONARY.mdis the one file the developer writes;FEATURE.mdandPRD.mdare generated from it.- Precision here is cheap; imprecision is discovered later as rework.
