skip to Main Content

Let’s say that there’s a CMS made with Laravel. We would be providing different clients with that same CMS, upgrade their CMS on every release we create but have a configuration file that would define what features are available for each client. The entire backoffice (admin panel etc.) would be mostly static and would use Vue only for certain dynamic elements. This solution suits our needs when it comes to the backend.

However, we plan on deploying different end-user frontends for each of these clients. Decoupling those sounds very simple (create a completely separate frontend project and use API endpoints to fetch and render everything dynamically) but if we were to completely decouple the frontend and the backend we would lose the ability to render static pages using Laravel Blade and we need that feature for the certain pages because of the rendering speed, loading times, SEO etc.

The main question is: how to decouple the frontend from the backend for each client without losing the ability to render pages with Laravel and Blade while keeping the development and testing easy?

One of the solutions that comes to my mind is to create a post-build step where we would “merge” the client-specific frontend files into the CMS but this would make the development process very difficult or would even make it all practically impossible to develop and test.

The second solution that comes to my mind would be to:

  1. Keep everything in one Git repository.
  2. Develop the CMS on it’s own branch and develop only the backend and backoffice stuff on that branch and it’s children.
  3. Create separate branches (What's the best practice for putting multiple projects in a git repository? perhaps some of the solutions presented here?) for different end-user frontends and develop only the end-user frontend on those branches.
  4. Merge the CMS branch into the client branches on each release.

This solution seems viable and would allow us to use Laravel Mix and server-side rendering but it’s very prone to human error and it would make it very difficult for us to keep track of these branches after a while. One of the other potential solutions that I’ve read about is using Git submodules but I simply have difficulty grasping how that works and it seems that it is not as flexible as it should be in this use case.

What would actually be the best architectural solution for us here?

2

Answers


  1. I would think of your CMS as a package, and think of your different front-end pieces as separate projects that each have a dependency on your CMS. For instance, I use Backpack for Laravel for a number of projects: https://github.com/Laravel-Backpack/CRUD which I think is similar to what you’re describing – a common set of core functionality with an un-opinionated front-end.

    Laravel packages can register routes, publish views and assets, pull in migrations, etc etc – really anything you can do in a Laravel app can be done via a composer package.

    So you would take the functionality that is repeated between your builds, and extract that into a “core” package that can be required via composer. Then the front-end stuff can be built in projects that simply require your core codebase. When you update your main core package, you can go into each front-end build and pull in the new version of the core via composer. This would give you an opportunity to roll the new core version out to each project one-by-one, making sure you can resolve issues or adapt to breaking changes on those projects individually.

    Your core package can also include any front-end components that are commonly re-used across your client projects, so ideally you aren’t re-writing any code between the front end projects.

    It can be challenging to make that core code modular enough to be a standalone package, but I think that makes the most sense based on what I understand about your project. Hope it helps.

    Login or Signup to reply.
  2. When you´re decoupling your system I strongly suggest not to pick the easiest solution without first guarantee it can scale and be ( as one of your concerns is ) easy to test.

    Let´s call your core product CMS vanilla, it works as supposed and designed to be. Now you have CMS Chocolate wich is slightly different on the frontend, here´s what I did:

    • Keep UI theme ( template files, images, js, css, etc. ) in one single repository (i.e. yourcompany/cms-front) and each version in its own branch ( v-vanilla, v-chocolate, v-strawberry)
    • On your UI Theme you will need to include a simple composer.json file to describe the project
    • On your CMS project give each version its own branch and force version name match its corresponding layout name.
    • Reference your front repository in your cms composer.json, I´m assuming We´re talking about a private one here otherwise next lines won´t be necesary.

    {
    "repositories": [
    {
    "type": "vcs",
    "url": "[email protected]:your-company/cms-front.git"
    }
    ],
    "config": {
    "github-oauth": {
    "github.com": "******"
    }
    }
    }

    • Add yourcompany/cms-front@dev-$version dependencie to your composer.

    composer require yourcompany/cms-front@dev-chocolate

    • You will need a post-build step to copy from vendor/your-company/cms-$version to your project but this is easy

    {
    "scripts": {
    "sync-theme": [
    "cp -r vendor/your-company/cms-front/resources app/resources",
    "cp -r vendor/your-company/cms-front/public app/public",
    ],
    "post-install-cmd": [
    "@sync-theme"
    ],
    "post-update-cmd": [
    "@sync-theme"
    ]
    }
    }

    • Add yourcompany/cms-front@dev-$version on your composer dependencies.

    • Switch between themes whenever you feel to.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search