For companies utilizing a headless CMS there are some important items to consider when scaffolding a projects foundation and content structure.
Consistency
How can a business roll out a consistent foundation for projects going forwards ensuring this foundation is futureproof, best practice, adaptable, and abides to business standards and regulations? It is especially important when leveraging internal integrations that require a specific setup and have sole responsibility of delivering content by bridging the gap between the application and the headless CMS.
Automation
How can the projects foundation creation be automated, so it is re-runnable for new empty projects? How can it be Integrated into CI/CD processes? How can we reduce the requirement of manual user intervention which could require specific CMS knowledge? These types of manual actions performed by a user will not be transparent to other users. Most importantly; can this implementation flow through multiple environments to reduce risk, allow collaboration and manual or automated testing?
Review Process
Can this implementation be integrated into existing Software Development Lifecycle Processes (SDLC), planning, design, pull requests, testing etc to improve quality and reduce risk?
Kontent by Kentico have got this spot on, they have a provided a quick start kontent migrations boilerplate which follows a migration approach, rolling out structure, such as content items, content types etc. This approach is extremely similar to something I have used in the past within a enterprise environment, where we used DbUp
for rolling out a SQL databases schema and data. The Kontent Migrations Boilerplate provides a great developer best practice experience and really compliments the kontent-cli
with how easy it is to use, integrate and store migrations into existing applications.
Migrations can be created in both JavaScript and Typescript but remember if using Typescript remember to transpile them back to JavaScript as this is required by the cli.
The migrations boilerplate has everything out of the box to get started with building a great foundation, if you look in the Migrations folder you will see example of how you can migrate and manipulate content, insert and update, content types, content items, language variations etc. You can even link new pages into Web Spotlight so they are visible as subpages in the site root. You can also manage environment configuration at GitHub Action runtime so the .environments.json
is dynamic and does not need secrets to be checked in, this is covered in an example towards the end of the post.
Example migration that adds a page content type below.
import { MigrationModule } from '@kentico/kontent-cli'; import { ContentTypeElementsBuilder, ContentTypeModels, ManagementClient, } from '@kentico/kontent-management'; /** * Creates content type Page. * This content type has the element foundation for pages. */ const migration: MigrationModule = { order: 1, run: async (apiClient: ManagementClient) => { await apiClient.addContentType().withData(BuildPage).toPromise(); }, }; const BuildPage = ( builder: ContentTypeElementsBuilder ): ContentTypeModels.IAddContentTypeData => { return { name: 'Page', codename: 'page', content_groups: [ { name: 'Content', codename: 'page_content', }, { name: 'Configuration', codename: 'page_config', } ], elements: [ //Content Group builder.linkedItemsElement({ name: 'Page Blocks', guidelines: 'The blocks of the content for the page.', codename: 'page_blocks', type: 'modular_content', content_group: { codename: 'page_content', }, }), //Configuration Group builder.urlSlugElement({ name: 'Page URL', guidelines: 'The URL slug element specifies an SEO-friendly text that you can use in the URLs of your content items. The element generates its value based on the text element of your choice.', codename: 'page_url', type: 'url_slug', depends_on: { element: { codename: 'page_text' }, }, content_group: { codename: 'page_config', }, }) ], }; }; export default migration;
Conclusion
Following a Kontent as code approach using the Kontent Migrations Boilerplate as a starting point, will provide consistency through code, resulting also to CMS consistency, it can be automated into a GitHub Action (See below for example). Migrations can be automatically triggered and run on multiple Kontent Environments & Projects, a status.json
file is outputted providing feedback, allowing the run results to be tracked and stored for which migrations have completed successfully against which Kontent Environments projectId
. This means you don’t have to re-run them, and an incremental approach can be followed, once the foundation is built. All code can be stored in source control such as GitHub, integrated into SDLC processes, provoking team discussion, collaboration and reducing risk, whilst also maintaining a code first approach.
The benefit of the Kontent CLI is that all of the things I’ve mentioned above, can be achieved without logging into the UI and allowing for the developer, code first approach.
Bonus – GitHub action below to install the kontent-cli as a global dependency on the action runner, run a step to add a dynamic environment of dev, with the correct secrets and run all migrations for this environment on a manual trigger for POC from the Github Action Screen.
name: Deploy Kontent Migrations on: workflow_dispatch: jobs: deploy-migrations: name: Deploy Migrations runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v2 - name: Install Global Dependencies run: | yarn global add @kentico/kontent-cli - name: Deploy Kontent Migrations run: | cd src/web kontent environment add --name DEV --project-id ${{ secrets.KONTENT_DEV_PROJECTID }} --api-key ${{ secrets.KONTENT_DEV_MANAGEMENT_KEY }} kontent migration run --all --environment DEV
Note – this should also be enhanced to store the output (status.json
) from what migration has successfully run for each environment.