The Draft Package Workflow provides a development environment for testing components, content types, and content before creating formal package versions. This workflow enables teams to iterate on their work while maintaining a clear development-to-production path.
Concepts
The workflow follows these principles:
-
Development Lifecycle
- Draft components → Draft package → Draft content type → Draft content
- Each stage requires the previous to be in place
- Formal publishing follows the same sequence
- Dependencies flow downward through the chain
-
Draft Package
- Virtual package composed of latest components (both draft and modified)
- Includes all draft components (never published)
- Includes all modified components (unpublished changes)
- Acts as a working copy within the project
- Not formally versioned or published
- Used for development and testing
-
Publishing Constraints
- Content type cannot be published unless its package is published
- Content cannot be published unless its content type is published
- Enforces stability in the production chain
- Prevents referencing unstable components
Workflow Diagram
Using Draft Package in Content Types
Content types can reference the draft package during development to use the latest component versions without needing to create a formal package.
Create Content Type with Draft Package
POST /v1/organizations/:organizationId/projects/:projectId/content-types
Request Body:
{
"name": "Blog Post",
"description": "Standard blog post layout",
"layoutComponentId": "comp125",
"componentIdsAllowList": ["comp123", "comp124"],
"packageVersion": "draft",
"permissions": {
"roles": ["editor"]
}
}
When using "packageVersion": "draft", the content type is tied to the current working state of components. This content type cannot be published until an actual package version is created and the content type is updated to reference it.
Creating Content from Draft Content Types
Content can be created from draft content types, but it will also remain in draft state until its content type is published.
Create Content with Draft Content Type
POST /v1/organizations/:organizationId/projects/:projectId/content
Request Body:
{
"typeId": "ct123",
"name": "My First Blog Post",
"content": {
"title": "Hello World",
"body": "This is my first post..."
}
}
Publishing Workflow
Step 1: Publish Package
First, create and publish a formal package version. This will:
- Publish all draft components (never published) with version 1
- Publish all modified components with incremented version
- Create an immutable package snapshot
POST /v1/organizations/:organizationId/projects/:projectId/packages
Request Body:
{
"version": "1.0.0",
"metadata": {
"description": "Initial release"
}
}
Step 2: Update Content Type to Use Published Package
PUT /v1/organizations/:organizationId/projects/:projectId/content-types/:id/package-version
Request Body:
{
"packageVersion": "1.0.0"
}
Step 3: Publish Content Type
POST /v1/organizations/:organizationId/projects/:projectId/content-types/:id/publish
Step 4: Publish Content
POST /v1/organizations/:organizationId/projects/:projectId/content/:id/publish
Code Example
Complete workflow from development to production:
// 1. Create components (they start as drafts)
await fetch('/v1/organizations/org123/projects/proj456/components', {
method: 'POST',
headers: { 'Authorization': 'Bearer TOKEN', 'Content-Type': 'application/json' },
body: JSON.stringify({
name: 'HeroSection',
type: 'view',
content: 'const body = (props) => { ... }'
})
});
// 2. Create content type referencing draft package
await fetch('/v1/organizations/org123/projects/proj456/content-types', {
method: 'POST',
headers: { 'Authorization': 'Bearer TOKEN', 'Content-Type': 'application/json' },
body: JSON.stringify({
name: 'Landing Page',
layoutComponentId: 'comp123',
packageVersion: 'draft'
})
});
// 3. Create and test content with draft content type
await fetch('/v1/organizations/org123/projects/proj456/content', {
method: 'POST',
headers: { 'Authorization': 'Bearer TOKEN', 'Content-Type': 'application/json' },
body: JSON.stringify({
typeId: 'ct123',
name: 'Homepage',
content: { headline: 'Welcome' }
})
});
// 4. When ready, publish the package
await fetch('/v1/organizations/org123/projects/proj456/packages', {
method: 'POST',
headers: { 'Authorization': 'Bearer TOKEN', 'Content-Type': 'application/json' },
body: JSON.stringify({ version: '1.0.0' })
});
// 5. Update content type to use published package
await fetch('/v1/organizations/org123/projects/proj456/content-types/ct123/package-version', {
method: 'PUT',
headers: { 'Authorization': 'Bearer TOKEN', 'Content-Type': 'application/json' },
body: JSON.stringify({ packageVersion: '1.0.0' })
});
// 6. Publish content type
await fetch('/v1/organizations/org123/projects/proj456/content-types/ct123/publish', {
method: 'POST',
headers: { 'Authorization': 'Bearer TOKEN' }
});
// 7. Publish content
await fetch('/v1/organizations/org123/projects/proj456/content/cont123/publish', {
method: 'POST',
headers: { 'Authorization': 'Bearer TOKEN' }
});