📋 Content Models
Projects
📖 Docs

Projects - Optimizely CMS 12

Exam Area: Content Area 5 – Content Models (25%)
Reference: https://docs.developers.optimizely.com/content-management-system/docs/projects


1. What Are Projects?

Projects allow editors to group multiple content items together and publish them simultaneously as a release. For example: campaign launches, product releases.

Project: "Summer Campaign 2024"
├── StartPage (updated hero banner)
├── ProductPage A (new content)
├── ProductPage B (updated pricing)
└── Article 1 (new blog post)
    └── All published together → July 1, 2024 at 9AM

2. Creating and Managing Projects

using EPiServer.Core.Internal;
using EPiServer.DataAbstraction;

public class ProjectService
{
    private readonly IProjectRepository _projectRepository;
    private readonly IContentRepository _contentRepository;

    public ProjectService(
        IProjectRepository projectRepository,
        IContentRepository contentRepository)
    {
        _projectRepository = projectRepository;
        _contentRepository = contentRepository;
    }

    // Create new project
    public async Task<Project> CreateProjectAsync(string name)
    {
        var project = new Project
        {
            Name = name,
            Description = "Summer Campaign 2024"
        };
        
        await _projectRepository.SaveAsync(project);
        return project;
    }

    // Add content to project
    public async Task AddContentToProjectAsync(int projectId, ContentReference contentLink)
    {
        var projectItem = new ProjectItem
        {
            ProjectId = projectId,
            ContentLink = contentLink
        };
        
        await _projectRepository.AddItemAsync(projectItem);
    }

    // Get all projects
    public async Task<IEnumerable<Project>> GetAllProjectsAsync()
    {
        return await _projectRepository.ListAsync(new ProjectQuery());
    }

    // Get project items
    public async Task<IEnumerable<ProjectItem>> GetProjectItemsAsync(int projectId)
    {
        return await _projectRepository.GetItemsAsync(projectId);
    }
}

3. Project Publish

public class ProjectPublishService
{
    private readonly IProjectRepository _projectRepository;

    public ProjectPublishService(IProjectRepository projectRepository)
    {
        _projectRepository = projectRepository;
    }

    // Publish entire project
    public async Task PublishProjectAsync(int projectId)
    {
        await _projectRepository.PublishAsync(projectId);
    }

    // Schedule publish
    public async Task SchedulePublishAsync(int projectId, DateTime publishAt)
    {
        var project = await _projectRepository.GetAsync(projectId);
        project.ScheduledPublishDate = publishAt;
        
        await _projectRepository.SaveAsync(project);
    }
}

4. Project in Edit UI

Edit View → Projects panel (left sidebar)
  → Create new project
  → Add current page to project
  → View all project items
  → Publish/Schedule project

CMS toolbar when editing:
  → Project selector dropdown
  → "Add to project" button

5. Working with Project Context

// Read content in project context (draft)
public class ProjectContextService
{
    private readonly IContentRepository _contentRepository;
    private readonly IProjectRepository _projectRepository;

    public async Task<IContent> GetContentInProjectAsync(
        ContentReference contentLink, int projectId)
    {
        // Content in project may be a draft version
        var projectItems = await _projectRepository.GetItemsAsync(projectId);
        var projectItem = projectItems
            .FirstOrDefault(i => i.ContentLink.ID == contentLink.ID);

        if (projectItem != null)
        {
            // Load project version
            return _contentRepository.Get<IContent>(projectItem.ContentLink);
        }

        // Fallback to published
        return _contentRepository.Get<IContent>(contentLink);
    }
}

6. IProjectRepository Members

public interface IProjectRepository
{
    // CRUD
    Task<Project> GetAsync(int projectId);
    Task<IEnumerable<Project>> ListAsync(ProjectQuery query);
    Task SaveAsync(Project project);
    Task DeleteAsync(int projectId);
    
    // Items
    Task<IEnumerable<ProjectItem>> GetItemsAsync(int projectId);
    Task AddItemAsync(ProjectItem item);
    Task RemoveItemAsync(int projectItemId);
    
    // Publish
    Task PublishAsync(int projectId);
    Task<int> CountAsync(ProjectQuery query);
}

7. Project vs Content Approvals

FeatureProjectsContent Approvals
PurposeGroup & release togetherApproval workflow
Who controlsEditorsAdmins/Approvers
ScheduleCan schedule publishNo
Multi-contentMultiple content itemsPer item
WorkflowNo stepsHas approval steps

8. Using ProjectQuery

// Query projects with filters
var query = new ProjectQuery
{
    Status = ProjectStatus.Open,          // Open/Archived
    Page = 1,
    PageSize = 10,
    Search = "Summer"                     // Name search
};

var projects = await _projectRepository.ListAsync(query);

Review Questions

  1. What are Projects used for? (Grouping multiple content items to publish simultaneously as a release)
  2. What methods does IProjectRepository provide? (CRUD for projects, add/remove items, publish)
  3. How do Projects differ from Content Approvals? (Projects: group release; Approvals: approval workflow)
  4. Where do editors create a project? (Edit View → Projects panel)
  5. How do you schedule publish a project? (project.ScheduledPublishDate = publishAt; _projectRepository.SaveAsync(project))