Content Lifecycle Management with Scalar
How to implement comprehensive governance from creation to archival using Scalar's workflow features.
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:
- Planning - Strategy, ideation, and scheduling
- Creation - Authoring, design, and assembly
- Review - Editing, approval, and compliance checks
- Publishing - Release, distribution, and promotion
- Maintenance - Updates, optimization, and monitoring
- 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 modelconst 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 ruleexport 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 templateexport 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 templateexport 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 featuresexport 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:
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 checksexport 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 publishingexport default defineConfig({ publishing: { scheduling: { enabled: true, timezone: 'America/New_York', schedulingField: 'publishDate', }, },});
// In your content modelconst 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 workflowexport 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 remindersexport 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 workflowexport 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 settingsexport 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 dashboardsexport 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 permissionsexport 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 integrationsexport 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:
-
Centralized Content Repository
- Unified content types across the organization
- Standardized metadata and tagging
- Integrated taxonomy management
-
Compliance-Focused Workflow
- Legal and compliance review stages
- Automated expiration for time-sensitive content
- Complete audit trails for regulatory purposes
-
Performance-Driven Maintenance
- Automated analytics collection
- Quarterly review cycles based on content type
- Structured archival process with proper redirects
-
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 .