07a921f8ca
## What & why
This adds a **guided tutorial** that teaches the Twenty SDK by building
one real, useful app end to end — plus the finished app itself, ready
for the marketplace.
The app, **Document Generator**, turns reusable templates into
personalized documents using CRM data: write a template once with
`{{placeholders}}`, then generate a filled-in document for any Person or
Company from the command menu, an AI agent, or a workflow.
## Two parts
**1. The app — `packages/twenty-apps/public/document-generator`**
Each capability maps to one tutorial chapter:
- **Data:** `documentTemplate` + `document` objects, fields, and a
bidirectional relation
- **Logic:** a single `generate-document` handler exposed as an **AI
tool**, a **workflow action**, and an **HTTP POST route**; plus a public
**HTML view route**
- **UI:** two views + sidebar navigation, a **command-menu item** (on
Person selection) that opens a **React front component**
- **AI:** an agent + skill; a default application role; marketplace
metadata + logo
- **Tests:** unit tests for the template renderer + an install
integration test
**2. The tutorial —
`packages/twenty-docs/.../apps/tutorials/document-generator/`**
A six-chapter series under **Developers › Apps › Tutorial** (Overview →
Data model → Generating documents → HTTP routes → Building the UI → AI
agent → Publishing). Minimal prose, paste-ready code, inline links to
the matching reference pages, and real screenshots. Registers a new
"Tutorial" nav group and regenerates `docs.json` + the navigation
template.
## Verification
Validated against a running Twenty instance (`twenty-app-dev` on
`:2020`):
- `twenty dev --once` installs cleanly (28 metadata objects created)
- Generated a real document from a Person — placeholders resolved (name,
job title, `company.name`, email), zero missing tokens
- Command menu → front component → generate flow works in the UI
- Public HTML view route renders the document
- App gates green: `yarn lint` (0/0), `yarn typecheck`, `yarn test:unit`
(7/7)
All screenshots in the tutorial are captured from this run.
## Notes
- Left out per-app CI workflows (`.github/workflows`) to keep scope
tight — happy to add them if wanted.
https://claude.ai/code/session_012FoC76zPbPmpgtN7MXMPwy
---
_Generated by [Claude
Code](https://claude.ai/code/session_012FoC76zPbPmpgtN7MXMPwy)_
<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22522?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
---------
Co-authored-by: github-actions <github-actions@twenty.com>
199 lines
4.6 KiB
JSON
199 lines
4.6 KiB
JSON
{
|
|
"tabs": {
|
|
"gettingStarted": {
|
|
"label": "Getting Started",
|
|
"groups": {
|
|
"welcome": {
|
|
"label": "Welcome"
|
|
},
|
|
"coreConcepts": {
|
|
"label": "Core Concepts"
|
|
}
|
|
}
|
|
},
|
|
"userGuide": {
|
|
"label": "User Guide",
|
|
"groups": {
|
|
"userGuideOverview": {
|
|
"label": "Overview"
|
|
},
|
|
"dataModel": {
|
|
"label": "Data Model",
|
|
"groups": {
|
|
"dataModelReference": {
|
|
"label": "Reference"
|
|
},
|
|
"dataModelHowTos": {
|
|
"label": "How-Tos"
|
|
}
|
|
}
|
|
},
|
|
"dataMigration": {
|
|
"label": "Data Migration",
|
|
"groups": {
|
|
"dataMigrationReference": {
|
|
"label": "Reference"
|
|
},
|
|
"dataMigrationHowTos": {
|
|
"label": "How-Tos"
|
|
}
|
|
}
|
|
},
|
|
"calendarEmails": {
|
|
"label": "Calendar & Emails",
|
|
"groups": {
|
|
"calendarEmailsReference": {
|
|
"label": "Reference"
|
|
},
|
|
"calendarEmailsHowTos": {
|
|
"label": "How-Tos"
|
|
}
|
|
}
|
|
},
|
|
"workflows": {
|
|
"label": "Workflows",
|
|
"groups": {
|
|
"workflowsReference": {
|
|
"label": "Reference"
|
|
},
|
|
"workflowsHowTos": {
|
|
"label": "How-Tos",
|
|
"groups": {
|
|
"crmAutomations": {
|
|
"label": "CRM Automations"
|
|
},
|
|
"connectToOtherTools": {
|
|
"label": "Connect to Other Tools"
|
|
},
|
|
"advancedConfigurations": {
|
|
"label": "Advanced Configurations"
|
|
},
|
|
"needMoreHelp": {
|
|
"label": "Need More Help"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"ai": {
|
|
"label": "AI",
|
|
"groups": {
|
|
"aiReference": {
|
|
"label": "Reference"
|
|
},
|
|
"aiHowTos": {
|
|
"label": "How-Tos"
|
|
}
|
|
}
|
|
},
|
|
"layout": {
|
|
"label": "Layout",
|
|
"groups": {
|
|
"layoutReference": {
|
|
"label": "Reference",
|
|
"groups": {
|
|
"layoutViews": {
|
|
"label": "Views"
|
|
}
|
|
}
|
|
},
|
|
"layoutHowTos": {
|
|
"label": "How-Tos"
|
|
}
|
|
}
|
|
},
|
|
"dashboards": {
|
|
"label": "Dashboards",
|
|
"groups": {
|
|
"dashboardsReference": {
|
|
"label": "Reference"
|
|
},
|
|
"dashboardsHowTos": {
|
|
"label": "How-Tos"
|
|
}
|
|
}
|
|
},
|
|
"permissionsAccess": {
|
|
"label": "Permissions & Access",
|
|
"groups": {
|
|
"permissionsAccessReference": {
|
|
"label": "Reference"
|
|
},
|
|
"permissionsAccessHowTos": {
|
|
"label": "How-Tos"
|
|
}
|
|
}
|
|
},
|
|
"billing": {
|
|
"label": "Billing",
|
|
"groups": {
|
|
"billingReference": {
|
|
"label": "Reference"
|
|
},
|
|
"billingHowTos": {
|
|
"label": "How-Tos"
|
|
}
|
|
}
|
|
},
|
|
"settings": {
|
|
"label": "Settings",
|
|
"groups": {
|
|
"settingsReference": {
|
|
"label": "Reference"
|
|
},
|
|
"settingsHowTos": {
|
|
"label": "How-Tos"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"developers": {
|
|
"label": "Developers",
|
|
"groups": {
|
|
"developersOverview": {
|
|
"label": "Overview"
|
|
},
|
|
"apps": {
|
|
"label": "Apps",
|
|
"groups": {
|
|
"appsGettingStarted": {
|
|
"label": "Getting Started"
|
|
},
|
|
"appsTutorial": {
|
|
"label": "Tutorial"
|
|
},
|
|
"appsConfig": {
|
|
"label": "Config"
|
|
},
|
|
"appsData": {
|
|
"label": "Data"
|
|
},
|
|
"appsLogic": {
|
|
"label": "Logic"
|
|
},
|
|
"appsLayout": {
|
|
"label": "Layout"
|
|
},
|
|
"appsOperations": {
|
|
"label": "Operations"
|
|
},
|
|
"appsTranslations": {
|
|
"label": "Translations"
|
|
}
|
|
}
|
|
},
|
|
"api": {
|
|
"label": "API"
|
|
},
|
|
"selfHost": {
|
|
"label": "Self-Host"
|
|
},
|
|
"contribute": {
|
|
"label": "Contribute"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|