Separate content from config in Statamic
Tags: statamic, ddev, laravel, cms
Published: 2022-07-02 16:17:35

Before we continue with the deployment, we need to make some adjustments. As stated before, my goal is to separate content from config as much as possible. Therefore I will **not** rely on Statamics [Git Automation](https://statamic.dev/git-automation). Let's see how far I can push this as a Statamic newbie!

🚧 This article is work in progress. 🚧

## Technical approach

My approach: User editable content (markdown files, media assets in `content/`) should only be stored on the production server, they shouldn't be tracked in the git repository. 

Only configuration files should be tracked and pushed via git, always from local to production in a one-way-street. 

I don't want to handle git merge conflicts on a live server. I simply don't ;-)

Update: I found out that CraftCMS described the approach perfectly in the [CraftCMS deployments docs](https://craftcms.com/knowledge-base/deployment-best-practices#commit-template-amp-config-changes). This is the approach I would love to implement in Statamic: 

![Screenshot CraftCMS Docs Deployment, linked below](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9bllh3r4um2gj9c3fg8o.png)

![Screenshot CraftCMS Docs allowAdminChanges, linked below](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gyp0d02i7qfnz1jarq6t.png) 

But how do we get the production content data to the local development environment to play and develop with it? I'll use use [DDEVs pull feature](https://ddev.readthedocs.io/en/stable/users/providers/provider-introduction/) and get the content via SSH/rsync from the production server later in this series.

## Change storage of collection definitions

Usually the collection yaml definitions are stored in `content/collections` next to the markdown files. But we can change this. We need to change `content/collections` to  `resources/collections` in `config/stache.php`, these are the important lines:

```php
'collections' => [
            'class' => Stores\CollectionsStore::class,
            'directory' => base_path('resources/collections'),
        ],
```

The full `config/stache.php` file:

```php
<?php

use Statamic\Stache\Stores;

return [

    /*
    |--------------------------------------------------------------------------
    | File Watcher
    |--------------------------------------------------------------------------
    |
    | File changes will be noticed and data will be updated accordingly.
    | This can be disabled to reduce overhead, but you will need to
    | either update the cache manually or use the Control Panel.
    |
    */

    'watcher' => env('STATAMIC_STACHE_WATCHER', true),

    /*
    |--------------------------------------------------------------------------
    | Stores
    |--------------------------------------------------------------------------
    |
    | Here you may configure the stores that are used inside the Stache.
    |
    | https://statamic.dev/stache#stores
    |
    */

    // separate collections from entries
    'stores' => [

        'collections' => [
            'class' => Stores\CollectionsStore::class,
            'directory' => base_path('resources/collections'),
        ],

        'entries' => [
            'class' => Stores\EntriesStore::class,
            'directory' => base_path('content/collections'),
        ],

    ],

    /*
    |--------------------------------------------------------------------------
    | Indexes
    |--------------------------------------------------------------------------
    |
    | Here you may define any additional indexes that will be inherited
    | by each store in the Stache. You may also define indexes on a
    | per-store level by adding an "indexes" key to its config.
    |
    */

    'indexes' => [
        //
    ],

    /*
    |--------------------------------------------------------------------------
    | Locking
    |--------------------------------------------------------------------------
    |
    | In order to prevent concurrent requests from updating the Stache at
    | the same and wasting resources, it will be "locked" so subsequent
    | requests will have to wait until the first has been completed.
    |
    | https://statamic.dev/stache#locks
    |
    */

    'lock' => [
        'enabled' => true,
        'timeout' => 30,
    ],

];
```

Afterwards you need to move `content/collections/pages.yaml` to `resources/collections/pages.yaml`.

And we need to remove and add the `content/`-directory to  `.gitignore`:

```
# add to .gitignore:
/content
```

Since these files are already tracked, we need to remove the whole folder from the project and commit these git changes.

```bash
ddev exec rm -rf content/
```

## The missing piece: Permissions based on environment

To avoid confusion it shouldn't be possible to edit configuration things in the control panel on production sites. 
This should only be done in the local dev environment and then be committed from there to the git repository. 

![Screenshot of edit collection menu item](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lkthfbujp5wh4uc3trkw.png)

See this [twitter discussion](https://twitter.com/m_andrasch/status/1543152816281223168) for the current state. I guess I need to implement different permission sets for the local as well as the production site. 🤔 

I opened a GitHub discussion about this:
[Implement a config option like "allowAdminChanges" - override permissions dynamically based on APP_ENV? #6289](https://github.com/statamic/cms/discussions/6289)

Disclaimer: I'm a Statamic newbie, maybe they are some more challenges to this approach.

## Acknowledgements 

Thanks very much to [Jonas Siewertsen](https://github.com/sponsors/jonassiewertsen) for [helpful advice on twitter](https://twitter.com/jonassiewertsen/status/1543126021641322499). He also held a [great talk about zero-downtime deployment](https://www.youtube.com/watch?v=Dsld-2iHv2k) and offers [statamictutorials.com](https://statamictutorials.com/) for free. Thanks so much!