Blog
February 22, 2025

Content Lifecycle Management with Scalar

How to implement comprehensive governance from creation to archival using Scalar's workflow features.

Rob Austin
Rob Austin
14 mins read

Content Lifecycle Management with Scalar

How to implement comprehensive governance from creation to archival using Scalar’s workflow features.

Beyond Basic Content Management

Modern organizations face increasingly complex content challenges:

  • Growing content volumes across multiple channels
  • Diverse content teams with specialized roles
  • Compliance and governance requirements
  • Need for content reuse and repurposing
  • Long-term content maintenance and archival

Basic create-publish-update operations are no longer sufficient. Organizations need comprehensive content lifecycle management—a systematic approach to governing content from inception to retirement.

Scalar provides a robust framework for implementing end-to-end content lifecycle management. This post explores how to leverage these capabilities to bring structure and efficiency to your content operations.

The Content Lifecycle Framework

A well-designed content lifecycle typically includes these phases:

  1. Planning - Strategy, ideation, and scheduling
  2. Creation - Authoring, design, and assembly
  3. Review - Editing, approval, and compliance checks
  4. Publishing - Release, distribution, and promotion
  5. Maintenance - Updates, optimization, and monitoring
  6. Archival - Retirement, preservation, and pruning

Let’s examine how to implement each phase using Scalar.

Phase 1: Content Planning

Effective content begins with proper planning. Scalar supports this phase through:

Content Calendar

Scalar’s calendar interface provides a visual overview of planned content:

// Define scheduling metadata in your content model
const BlogPost = defineType({
name: 'blogPost',
fields: {
// Standard content fields...
// Planning fields
plannedPublishDate: fields.date({
required: true,
description: 'Target date for publishing',
}),
author: fields.reference({
to: 'author',
required: true,
}),
status: fields.select({
options: [
{ label: 'Planned', value: 'planned' },
{ label: 'In Progress', value: 'in-progress' },
{ label: 'In Review', value: 'in-review' },
{ label: 'Ready', value: 'ready' },
{ label: 'Published', value: 'published' },
{ label: 'Updated', value: 'updated' },
{ label: 'Archived', value: 'archived' },
],
defaultValue: 'planned',
}),
priority: fields.select({
options: [
{ label: 'Low', value: 'low' },
{ label: 'Medium', value: 'medium' },
{ label: 'High', value: 'high' },
],
defaultValue: 'medium',
}),
},
});

Content Strategy Metadata

Enhance your content with strategic context:

const ContentPiece = defineType({
// ... other fields
// Strategy fields
contentGoal: fields.select({
options: [
{ label: 'Acquisition', value: 'acquisition' },
{ label: 'Conversion', value: 'conversion' },
{ label: 'Retention', value: 'retention' },
{ label: 'Support', value: 'support' },
{ label: 'Brand Building', value: 'brand' },
],
}),
targetPersona: fields.reference({
to: 'persona',
many: true,
}),
targetKeywords: fields.array({
of: fields.text(),
}),
contentBrief: fields.document({
description: 'Strategic brief for this content piece',
}),
});

Assignment and Workflow Initialization

Set up automated processes to streamline planning:

// Define a workflow rule
export default defineConfig({
workflows: {
rules: [
{
name: 'Assign New Content',
on: {
event: 'create',
contentType: 'blogPost',
},
actions: [
{
type: 'notification',
to: ['content-team@example.com'],
subject: 'New content piece assigned: {{title}}',
message: `
A new content piece has been planned:
Title: {{title}}
Due Date: {{plannedPublishDate}}
Author: {{author.name}}
Priority: {{priority}}
`,
},
{
type: 'update',
field: 'status',
value: 'planned',
},
],
},
],
},
});

Phase 2: Content Creation

The creation phase is where ideas transform into structured content. Scalar provides several features to support efficient creation:

Structured Content Templates

Create templates for common content types:

// Define a template
export const blogPostTemplate = {
title: 'New Blog Post',
description: 'Enter a compelling description here...',
content: {
type: 'doc',
content: [
{
type: 'heading',
attrs: { level: 1 },
content: [{ type: 'text', text: 'Main Headline' }],
},
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Start with a compelling introduction...',
},
],
},
{
type: 'heading',
attrs: { level: 2 },
content: [{ type: 'text', text: 'First Subheading' }],
},
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Explain your first point...',
},
],
},
// Additional structure...
],
},
status: 'in-progress',
};
// Register the template
export default defineConfig({
templates: {
blogPost: [
{
name: 'Standard Blog Post',
template: blogPostTemplate,
},
{
name: 'How-To Guide',
template: howToTemplate,
},
// Other templates...
],
},
});

Collaborative Authoring

Enable real-time collaboration between team members:

// Configure collaboration features
export default defineConfig({
collaboration: {
enabled: true,
trackChanges: true,
presence: true,
comments: {
enabled: true,
notifications: true,
},
},
});

Progress Tracking

Monitor content creation progress:

const BlogPost = defineType({
// ... other fields
completionStatus: fields.object({
outline: fields.boolean({ defaultValue: false }),
firstDraft: fields.boolean({ defaultValue: false }),
mediaAssets: fields.boolean({ defaultValue: false }),
technicalReview: fields.boolean({ defaultValue: false }),
finalEdit: fields.boolean({ defaultValue: false }),
}),
completionPercentage: fields.computed({
resolve: (doc) => {
const statuses = doc.completionStatus;
const completed = Object.values(statuses).filter(Boolean).length;
const total = Object.values(statuses).length;
return (completed / total) * 100;
},
}),
});

Phase 3: Review and Approval

The review phase ensures content meets quality standards before publishing. Scalar’s workflow engine excels at orchestrating complex reviews:

Multi-Stage Approval Workflows

Define comprehensive approval processes:

scalar.config.ts
export default defineConfig({
workflows: {
approvals: {
types: {
blogPost: {
stages: [
{
name: 'Editorial Review',
description: 'Check for grammar, style, and structure',
assignees: ['editor-group'],
requiredApprovals: 1,
},
{
name: 'Technical Review',
description: 'Verify technical accuracy',
assignees: ['technical-reviewers'],
requiredApprovals: 1,
conditional: (content) =>
content.category === 'technical' ||
content.tags.includes('technical'),
},
{
name: 'Legal Review',
assignees: ['legal-team'],
requiredApprovals: 1,
conditional: (content) =>
content.requiresLegalReview ||
content.tags.includes('compliance'),
},
{
name: 'Final Approval',
assignees: ['content-director'],
requiredApprovals: 1,
},
],
},
},
},
},
});

Review UI

Scalar provides a dedicated interface for reviews with:

  • Side-by-side comparison with previous versions
  • Inline commenting and threaded discussions
  • Suggested edits functionality
  • Approval/rejection with required feedback
  • Audit trail of all review activities

Quality Checks

Implement automated quality validations:

// Configure quality checks
export default defineConfig({
validation: {
rules: [
{
name: 'Minimum Content Length',
contentType: 'blogPost',
check: (doc) => {
const wordCount = doc.content.textContent.split(/\s+/).length;
return {
valid: wordCount >= 800,
message: `Article contains ${wordCount} words, minimum is 800`,
};
},
},
{
name: 'SEO Title Length',
contentType: 'blogPost',
check: (doc) => {
return {
valid: doc.title.length <= 60,
message: `Title is ${doc.title.length} chars, should be 60 or less`,
};
},
},
{
name: 'Required Images',
contentType: 'blogPost',
check: (doc) => {
const imageCount = doc.content.querySelectorAll('image').length;
return {
valid: imageCount >= 2,
message: `Article contains ${imageCount} images, minimum is 2`,
};
},
},
],
},
});

Phase 4: Publishing

The publishing phase makes content available to its intended audience. Scalar provides robust tools for controlled, scheduled release:

Scheduled Publishing

Set up content to publish automatically at the optimal time:

// Configure scheduled publishing
export default defineConfig({
publishing: {
scheduling: {
enabled: true,
timezone: 'America/New_York',
schedulingField: 'publishDate',
},
},
});
// In your content model
const BlogPost = defineType({
// ... other fields
publishDate: fields.datetime({
description: 'When this content should go live',
}),
expiryDate: fields.datetime({
description: 'When this content should be unpublished (optional)',
}),
});

Publishing Workflows

Automate actions that should occur upon publishing:

// Define publishing workflow
export default defineConfig({
workflows: {
rules: [
{
name: 'Content Publishing Actions',
on: {
event: 'publish',
contentType: 'blogPost',
},
actions: [
{
// Send notifications
type: 'notification',
to: ['marketing@example.com', 'social@example.com'],
subject: 'New blog post published: {{title}}',
message: `
A new blog post has been published:
Title: {{title}}
URL: {{url}}
Author: {{author.name}}
Category: {{category}}
Please promote this content through appropriate channels.
`,
},
{
// Update status
type: 'update',
field: 'status',
value: 'published',
},
{
// Trigger webhook to external systems
type: 'webhook',
url: 'https://api.example.com/social-scheduler',
method: 'POST',
body: {
contentType: 'blogPost',
title: '{{title}}',
excerpt: '{{description}}',
url: '{{url}}',
image: '{{coverImage.url}}',
},
},
],
},
],
},
});

Multi-Channel Distribution

Configure content for distribution across multiple channels:

const ContentPiece = defineType({
// ... other fields
distribution: fields.object({
website: fields.boolean({ defaultValue: true }),
emailNewsletter: fields.boolean({ defaultValue: false }),
socialMedia: fields.object({
twitter: fields.boolean({ defaultValue: false }),
linkedin: fields.boolean({ defaultValue: false }),
facebook: fields.boolean({ defaultValue: false }),
instagram: fields.boolean({ defaultValue: false }),
}),
syndication: fields.array({
of: fields.select({
options: [
{ label: 'Medium', value: 'medium' },
{ label: 'Dev.to', value: 'devto' },
{ label: 'Partner Network', value: 'partners' },
],
}),
}),
}),
channelSpecificContent: fields.object({
socialHeadline: fields.text({
description: 'Alternative headline for social media (optional)',
}),
emailSubject: fields.text({
description: 'Subject line when used in emails',
}),
twitterText: fields.text({
description: 'Twitter-specific copy (optional)',
validation: { maxLength: 280 },
}),
}),
});

Phase 5: Content Maintenance

After publishing, content requires ongoing maintenance. Scalar’s features support efficient content upkeep:

Content Freshness Tracking

Monitor content age and relevance:

const BlogPost = defineType({
// ... other fields
lastReviewedDate: fields.date(),
reviewFrequency: fields.select({
options: [
{ label: 'Monthly', value: 'monthly' },
{ label: 'Quarterly', value: 'quarterly' },
{ label: 'Annually', value: 'annually' },
{ label: 'As Needed', value: 'as-needed' },
],
defaultValue: 'quarterly',
}),
freshnessScore: fields.computed({
resolve: (doc) => {
if (!doc.lastReviewedDate) return 0;
const today = new Date();
const reviewed = new Date(doc.lastReviewedDate);
const daysSinceReview = Math.floor(
(today - reviewed) / (1000 * 60 * 60 * 24),
);
// Calculate score based on review frequency
switch (doc.reviewFrequency) {
case 'monthly':
return Math.max(0, 100 - (daysSinceReview / 30) * 100);
case 'quarterly':
return Math.max(0, 100 - (daysSinceReview / 90) * 100);
case 'annually':
return Math.max(0, 100 - (daysSinceReview / 365) * 100);
default:
return 50; // Middle score for "as needed"
}
},
}),
});

Update Workflows

Automate maintenance processes:

// Configure content review reminders
export default defineConfig({
workflows: {
rules: [
{
name: 'Content Review Reminder',
schedule: '0 9 * * 1', // Every Monday at 9am
query: {
contentType: 'blogPost',
where: {
lastReviewedDate: {
$lt: '{{now-90d}}', // Content not reviewed in 90 days
},
status: 'published',
},
},
actions: [
{
type: 'notification',
to: ['{{content.author.email}}', 'content-manager@example.com'],
subject: 'Content Review Needed: {{content.title}}',
message: `
The following content is due for review:
Title: {{content.title}}
Last Reviewed: {{content.lastReviewedDate}}
URL: {{content.url}}
Please review this content for accuracy and relevance.
`,
},
{
type: 'update',
field: 'reviewStatus',
value: 'due',
},
],
},
],
},
});

Performance Monitoring

Track content effectiveness over time:

const BlogPost = defineType({
// ... other fields
analytics: fields.object({
views: fields.number({ defaultValue: 0 }),
uniqueVisitors: fields.number({ defaultValue: 0 }),
averageTimeOnPage: fields.number({ defaultValue: 0 }),
conversionRate: fields.number({ defaultValue: 0 }),
lastUpdated: fields.datetime(),
}),
performanceTrend: fields.select({
options: [
{ label: 'Increasing', value: 'increasing' },
{ label: 'Stable', value: 'stable' },
{ label: 'Decreasing', value: 'decreasing' },
{ label: 'Not Enough Data', value: 'insufficient' },
],
defaultValue: 'insufficient',
}),
});

Phase 6: Archival and Content Pruning

The final phase of the content lifecycle involves strategic retirement of outdated content. Scalar provides tools for responsible content pruning:

Archival Workflow

Set up processes for content retirement:

// Configure archival workflow
export default defineConfig({
workflows: {
rules: [
{
name: 'Content Archival Process',
on: {
event: 'update',
contentType: 'blogPost',
condition: (before, after) =>
before.status !== 'archived' && after.status === 'archived',
},
actions: [
{
// Create redirect
type: 'createRedirect',
source: '{{slug}}',
destination: '/blog',
isPermanent: true,
},
{
// Notify team
type: 'notification',
to: ['content-team@example.com'],
subject: 'Content Archived: {{title}}',
message: `
The following content has been archived:
Title: {{title}}
URL: {{url}}
Archived By: {{user.email}}
Reason: {{archivalReason}}
A 301 redirect has been created to the blog index.
`,
},
{
// Remove from search index
type: 'webhook',
url: 'https://api.example.com/search-index/remove',
method: 'POST',
body: {
id: '{{id}}',
url: '{{url}}',
},
},
],
},
],
},
});

Archival Metadata

Add fields to track content retirement:

const ContentPiece = defineType({
// ... other fields
archivalMetadata: fields
.object({
archivalDate: fields.date(),
archivalReason: fields.select({
options: [
{ label: 'Outdated Information', value: 'outdated' },
{ label: 'Low Performance', value: 'low-performance' },
{ label: 'Redundant Content', value: 'redundant' },
{ label: 'Product Discontinued', value: 'discontinued' },
{ label: 'Legal/Compliance', value: 'legal' },
{ label: 'Other', value: 'other' },
],
}),
archivalNotes: fields.text(),
replacementContentId: fields.reference({
to: ['blogPost', 'page', 'document'],
}),
})
.when({
condition: (doc) => doc.status === 'archived',
required: true,
}),
});

Content Preservation

Ensure content is properly preserved for future reference:

// Configure content preservation settings
export default defineConfig({
archival: {
preservation: {
enabled: true,
strategy: 'snapshot',
formats: ['html', 'json', 'pdf'],
storage: {
provider: 's3',
bucket: 'content-archive',
pathPrefix: 'archives/',
},
metadata: {
includeVersionHistory: true,
includeAnalytics: true,
},
},
},
});

Implementing a Complete Lifecycle System

To bring all these elements together into a cohesive system:

1. Define Clear Statuses

Create a comprehensive set of statuses that reflect your lifecycle:

const contentStatuses = [
{ label: 'Draft', value: 'draft' },
{ label: 'In Review', value: 'in-review' },
{ label: 'Approved', value: 'approved' },
{ label: 'Scheduled', value: 'scheduled' },
{ label: 'Published', value: 'published' },
{ label: 'Update Needed', value: 'update-needed' },
{ label: 'Updating', value: 'updating' },
{ label: 'Archived', value: 'archived' },
];

2. Create Dashboard Views

Configure role-specific dashboards:

// Configure dashboards
export default defineConfig({
dashboards: {
editors: {
widgets: [
{
type: 'content-list',
title: 'Content Needing Review',
query: {
contentType: 'blogPost',
where: { status: 'in-review' },
orderBy: { updatedAt: 'asc' },
},
},
{
type: 'calendar',
title: 'Publishing Calendar',
query: {
contentType: 'blogPost',
where: {
status: { $in: ['approved', 'scheduled'] },
},
},
dateField: 'publishDate',
},
],
},
contentManagers: {
widgets: [
{
type: 'metrics',
title: 'Content Health',
metrics: [
{
name: 'Fresh Content',
query: {
contentType: 'blogPost',
where: { freshnessScore: { $gte: 70 } },
},
calculation: 'count',
},
{
name: 'Stale Content',
query: {
contentType: 'blogPost',
where: { freshnessScore: { $lt: 30 } },
},
calculation: 'count',
},
],
},
{
type: 'chart',
title: 'Content by Status',
chartType: 'pie',
query: {
contentType: 'blogPost',
groupBy: 'status',
},
},
],
},
},
});

3. Set Up Role-Based Permissions

Configure permissions aligned with your workflow:

// Configure role-based permissions
export default defineConfig({
roles: {
'content-creator': {
permissions: [
{
contentType: '*',
actions: ['create', 'read', 'update'],
conditions: {
status: { $nin: ['approved', 'published', 'archived'] },
},
},
],
},
editor: {
permissions: [
{
contentType: '*',
actions: ['create', 'read', 'update', 'approve'],
conditions: {
status: { $nin: ['archived'] },
},
},
],
},
'content-manager': {
permissions: [
{
contentType: '*',
actions: [
'create',
'read',
'update',
'approve',
'publish',
'archive',
],
},
],
},
},
});

4. Connect External Systems

Integrate with other tools in your content ecosystem:

// Configure integrations
export default defineConfig({
integrations: {
analytics: {
type: 'google-analytics',
propertyId: 'UA-XXXXXXXXX-X',
syncSchedule: '0 0 * * *', // Daily at midnight
},
marketing: {
type: 'hubspot',
apiKey: process.env.HUBSPOT_API_KEY,
mappings: {
blogPost: {
contentType: 'BLOG_POST',
fields: {
title: 'name',
publishDate: 'publish_date',
'author.name': 'author',
url: 'url',
},
},
},
},
translation: {
type: 'smartling',
apiKey: process.env.SMARTLING_API_KEY,
projectId: process.env.SMARTLING_PROJECT_ID,
},
},
});

Case Study: Enterprise Content Lifecycle Implementation

A large financial services company implemented comprehensive content lifecycle management with Scalar. Here’s how they structured their approach:

Challenge

With over 5,000 content pieces across multiple product lines, they struggled with:

  • Inconsistent review processes
  • Outdated regulatory information
  • Poor visibility into content performance
  • Inefficient update workflows
  • Content duplication and overlap

Solution

They implemented a Scalar-powered content hub with:

  1. Centralized Content Repository

    • Unified content types across the organization
    • Standardized metadata and tagging
    • Integrated taxonomy management
  2. Compliance-Focused Workflow

    • Legal and compliance review stages
    • Automated expiration for time-sensitive content
    • Complete audit trails for regulatory purposes
  3. Performance-Driven Maintenance

    • Automated analytics collection
    • Quarterly review cycles based on content type
    • Structured archival process with proper redirects
  4. Integration Ecosystem

    • Connected to customer support knowledge base
    • Integrated with marketing automation
    • Linked to learning management system

Results

After implementation, they achieved:

  • 65% reduction in compliance incidents
  • 40% improvement in content update efficiency
  • 30% reduction in duplicate content
  • 85% of content now reviewed within appropriate timeframes
  • Complete defensible audit trail for regulators

Conclusion

Effective content lifecycle management isn’t just about tools—it’s about establishing clear processes that govern how content moves through your organization. Scalar provides the technical framework to implement these processes, but success depends on aligning technology with your team’s workflows and organizational needs.

By implementing comprehensive lifecycle management, you can ensure your content remains accurate, relevant, and effective throughout its useful life—from initial planning through eventual archival.

To learn more about content lifecycle management with Scalar, explore our detailed documentation or join our community forum to discuss best practices with other content operations professionals.

Wrap-up

A CMS shouldn't slow you down. Scalar aims to expand into your workflow — whether you're coding content models, collaborating on product copy, or launching updates at 2am.

If that sounds like the kind of tooling you want to use — try Scalar or join us on Discord .