Environments and migrations > Keeping multiple projects in sync

    Keeping multiple projects in sync

    If you're an agency or developer looking to streamline your development process, this guide will provide you with the necessary steps to efficiently manage multiple projects within DatoCMS.

    Why is it useful?

    Managing multiple projects can be time-consuming and error-prone, especially when each project requires similar configurations and updates. However, with the ability to create a blueprint project in DatoCMS and duplicate it for each client, you can significantly reduce development time and ensure consistency across your projects.

    By following the techniques outlined in this guide, you will be able to:

    1. Save time and effort: Rather than starting each project from scratch, you can create a blueprint project with all the necessary configurations, models, and settings. This allows you to duplicate and then customize the blueprint for each client, minimizing the time spent on repetitive tasks.

    2. Ensure consistency: Keeping multiple projects in sync ensures that any updates or improvements made to the blueprint project can be easily propagated to all the client projects. This guarantees consistency in design, functionality, and content management across your portfolio.

    3. Maintain scalability: As your agency grows and takes on more clients, the ability to efficiently manage multiple projects becomes crucial. By adopting a synchronized approach, you can handle a higher workload without sacrificing quality or increasing development time.

    In the following sections, we will explore various use cases and provide step-by-step instructions on how to keep your DatoCMS projects in sync. Let's dive in and discover how you can optimize your development workflow!

    Creating a blueprint project

    Creating a blueprint project in DatoCMS is a great way to streamline your development process:

    1. Start by setting up a new project in DatoCMS that will serve as your blueprint. Configure it with all the necessary models, fields, plugins and settings that you want to replicate across your client projects.

    2. In parallel to your DatoCMS project, also create a frontend project associated with the blueprint. Use your favorite technology (ie. Next, SvelteKit). Make sure to parameterize the DatoCMS API token using environment variables!

    3. Once your blueprint project is ready, make sure to thoroughly test it and ensure that everything is working as expected.

    Duplicating your blueprint project

    Now that you have your blueprint project set up, it's time to duplicate for each client project.

    Open your DatoCMS dashboard, enter the blueprint project and under the "Danger zone" section click on "Duplicate project". Make sure to check the "Duplicate only models and fields" option, so that any sample content present in the blueprint won't be copied.

    Different projects, same IDs

    By duplicating a project, DatoCMS keeps exactly the same IDs for all the entities. As we'll see in the next section, this is vital to keep your projects synced over time.

    Open your Netlify/Vercel account, and create a new project, pointing to the Git repo of your blueprint frontend. In the project settings, make sure to specify the API token of the cloned project as an environment variable.

    You can repeat these steps for each client.

    Propagating updates across client projects

    Keeping your projects in sync is crucial for maintaining consistency and efficiency. Using migrations, you can easily make changes to your blueprint project, and propagate them to every client project programmatically.

    Step 1: Setup the CLI

    In your blueprint frontend repo, install our CLI:

    npm install --save-dev @datocms/cli

    Create one profile called blueprint for your blueprint DatoCMS project:

    npx datocms profile:set blueprint --migrations-dir=migrations

    This will create a datocms.config.json file. Similarly, create one profile for each of your client projects:

    npx datocms profile:set <client_name> --migrations-dir=migrations

    Create a .env file to store the read/write API token of each DatoCMS project as environment variables. If the profile name you chose for a client project was foo_bar, its API token must be stored in an env variable called DATOCMS_BLUE_PRINT_PROFILE_API_TOKEN:

    DATOCMS_BLUEPRINT_PROFILE_API_TOKEN=...
    DATOCMS_FOO_PROFILE_API_TOKEN=...
    DATOCMS_BAR_PROFILE_API_TOKEN=...

    Add the .env file to your .gitignore to avoid publishing it inadvertently:

    echo '.env' >> .gitignore
    Step 2: Generate a migration script

    Follow the Write and test migration scripts guide to generate a migration with the changes you want to make to every project. Make sure to add the --profile=blueprint flag to every command you launch, so that in this phase you will always work on your blueprint project.

    Step 3: Run the migration in every project

    Now that we have a migration script, we can easily apply the same set of changes to every project by following the steps listed in the Apply migrations to primary environment guide.

    Here is a sample Bash script that you can use to automate the process:

    #!/bin/bash
    # Put the names of the profiles associated to your DatoCMS projects here:
    profiles=("blueprint" "foo" "bar" "qux")
    # Get current date
    current_date=$(date +%Y-%m-%d)
    # Generate the name of the new primary environment, using current date
    destination="new-main-$current_date"
    # Iterate over each profile
    for profile in "${profiles[@]}"
    do
    echo "Running commands for profile: $profile"
    # Enable maintenance mode
    npx datocms maintenance:on --force --profile="$profile"
    # Fork primary environment, run migrations in the new destination
    npx datocms migrations:run --destination="$destination" --fast-fork --profile="$profile"
    # Promote environment
    npx datocms environments:promote "$destination" --profile="$profile"
    # Disable maintenance mode
    npx datocms maintenance:off --profile="$profile"
    echo "Commands completed for profile: $profile"
    done