Simplify Website Development with Fusion: Markdown Content Management
Tags: laravel, markdown, webdev, php
Published: 2024-04-12 13:49:11

**Fusion is a Laravel package** for building Website and managing the content through the integration of Markdown files with Frontmatter in Eloquent models.

> **Markdown** is a lightweight markup language that uses simple syntax to format plain text, allowing users to easily create structured documents for web content, documentation, and more.

> **Frontmatter** in Markdown refers to metadata at the beginning of a document that provides structured information such as title, author, and date.

Fusion is an Open Source package for Laravel and you can access to the GitHub repository here: https://github.com/Hi-Folks/fusion.

> Fusion integrates Markdown into Laravel Models, simplifying Website development.

You can install the package quickly via:
```shell
composer require hi-folks/fusion
```
But before to mention **how to use** Fusion, let me share **why** you should evaluate to use Fusion and **when**. 

So, why should developers adopt Fusion, and when is it the ideal choice for website content management?

## Why Fusion?

- Simplicity (**Markdown**) meets power (**Eloquent Models**): Fusion combines the simplicity of Markdown syntax with the robustness of Frontmatter, enabling developers to manage content effortlessly. Markdown's intuitive formatting makes it easy to create content, while Frontmatter adds metadata to improve organization and structure;
- Avoiding database dependencies: in Laravel usually web applications that allow traditional content to be managed rely heavily on databases, introducing complexity and overhead. Fusion allows Laravel developers to manage content directly in Markdown files. This not only simplifies development, but also improves portability and scalability;
- Seamless integration with Laravel Eloquent: Fusion seamlessly integrates Markdown files with Laravel's powerful Eloquent ORM (Object-Relational Mapping). By automatically parsing the Frontmatter headers of Markdown files into Eloquent models, Fusion enables developers to leverage familiar database paradigms and manage content in Markdown format.

## When to Use Fusion?

- Content-Based Websites:Fusion is especially ideal when building content-based websites, such as blogs, documentation portals or news platforms. Its streamlined content management process using Markdown makes it ideal for projects where rich, structured content is critical;
- Developer preference for Markdown: For developers accustomed to using Markdown to write documentation or create README files, Fusion is a natural extension of their workflow. Its Markdown-centric approach reduces context switching, promoting productivity and code clarity;
- Database-free development: Fusion is the ideal choice for projects where minimizing database dependencies is a priority. Whether it is simplicity, performance or architectural considerations, Fusion offers a database-free solution without compromising functionality by allowing the Laravel developer to access content through Eloquent.

## A practical example

Now let's take a practical example.
We have a Laravel project in which we are going to add the Fusion package.
So we're going to start creating markdown content.
Through the commands provided by Fusion we are going to go and create the Models that we will then need to be able to query the data.

### Installation of Fusion

To install Fusion we will use the usual composer command:

```shell
composer require hi-folks/fusion
```

### Creating the content

Now we want to create a couple of articles.
In the `resources/content` directory, create a directory with the name of the content you want, in our example `article`.
So we are going to create the directory `resources/content/article`:

```shell
mkdir -p resources/content/article
```
In the `resources/content/article` we are going to create some Markdown files with the Frontmatter headers.

The first file is the file `resources/content/article/article-1.md` and we will set the content:

```markdown
---
date: 2023-01-26
title: Example title for article 1
excerpt: This will be a short excerpt from article number 1.
published: true
highlight: true
head:
  - tag: php
    content: This content is about PHP
  - tag: laravel
    content: This content is about Laravel
---

# Article 1

Markdown goes here
```

As you can see we have some field like `date` (is a date), `title`, `excerpt`, `published`, `highlight`, and also an `head` field with an array of structured data.

The second file `resources/content/article/article-2.md` will contain:

```markdown
---
date: 2023-01-10
title: Example title for Article 2
excerpt: This will be a short excerpt from article number 2.
published: true
highlight: false
head:
  - tag: php
    content: This content is about PHP
  - tag: symfony
    content: This content is about Symfony
---

# Article 2

**Markdown** goes here

~~~php
echo "We love PHP!";
~~~
```

As you can see we created two Markdown files, each with a Frontmatter header that includes some string type fields such as the `title` field, date type fields such as the `date` field, and a more structured field like the `head` field that can hold an array (or in the Laravel context I would say a Collection).
Identifying the type of the fields is not mandatory but I recommend it especially to take advantage of all the benefits we can get from a good casting definition in the Model. But let's take it one step at a time.

Now that we have defined the Markdown files (you can create more than two of course) let's proceed with the generation of the Laravel Eloquent Models.

### Creating the Eloquent Model

We are going to create an Eloquent Model, in this case one for the articles, which we will call `Article` since we are defining Markdowns in the `article` folder (lowercase).

In order to allow Fusion to correctly parse Markdown files and make them accessible via Eloquent, we need to follow a few small rules in defining our new Model such as:
- Extend the class `FusionBaseModel`;
- Use the Trait `FusionModelTrait`;
- Implement the method `frontmatterFields` with the list (array) of field names we want to make available through our Eloquent Model

To generate the Model we can do it manually, for example by creating in the app/Models directory in our Laravel application the file `Article.php` for the class Article.

Or you can use the command `fusion:sync-model` via `artisan` in your Laravel project:

```shell
php artisan fusion:sync-model --path=resources/content/article --create-model
```

where:
- `fusion:sync-model` is the artisan command;
- `--path=` defines the path of the directory of the Markdown files;
- `--create-model` asks to Fusion to generate the Model class.

The Fusion model creation will take the name of the markdown folders `article`, it converts it in PascalCase format for defining the name of the Model.


![The execution for Sync model command for generating the Model](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ricd6kcfyj71979grj80.png)

The generated model in `app/Models/Article.php` is:

```php
<?php

namespace App\Models;

use HiFolks\Fusion\Models\FusionBaseModel;
use HiFolks\Fusion\Traits\FusionModelTrait;

class Article extends FusionBaseModel
{
    use FusionModelTrait;

    public function frontmatterFields(): array
    {
        return [
            "date","title","excerpt","published","highlight","head"
        ];
    }
}
```

### Casting field types


In Eloquent models, casting refers to the process of automatically converting attributes to native types, such as integers, booleans, arrays, or JSON, enhancing data consistency and simplifying manipulation.

Casting fields helps when you need to sort or filter fields (think about a date time field or an array field).

So because we have in our Frontmatter a date and a collection we can add the cast, implementing in the Model the `casts()` method:

```php
    protected function casts(): array
    {
        return [
            'head' => 'collection',
            'date' => 'datetime:Y-m-d',
        ];
    }
```

> If you are interested into learn more about field (or attribute) casting you can take a look at the [Eloquent documentation in the Laravel doc](https://laravel.com/docs/11.x/eloquent-mutators#attribute-casting).

Now because we created an Eloquent Model, we can start using it in our Laravel application, for example in a Controller or in a blade component.

### Querying the Markdown content

Now thanks to the Eloquent Model in your Laravel application you can retrieve the data, for example for retrieving the articles sorted by date you can use the typical Eloquent methods like:

```php
$articles = \App\Models\Article::orderBy('date')->get();
```

Thanks to the casting we defined for the date through the `casts()` method in the `Article` model, we are sure that the sorting will act on the date time type and not just a string.

If we want to retrieve articles ordered by date, and we want only published articles, we can use `orderBy()` for sorting and `where()` for filtering:

```php
use App\Models\Article;
$articles = Article
                ::where('published', true)
                ->orderBy('date')
                ->get();
```

If you are familiar with Eloquent, there is nothing new for you, but again, the "new thing" is that under the hood, with Fusion you don't have to worry about database management; your content is managed through Markdown files and via Frontmatter headers.

Because in the example, we are using the `published` field for filtering, you can decide to force the type of `published` field as `boolean`. In this case you can edit the app/Models/Article.php file and change the `casts()` method adding the fields you want to cast like for example `published` and `highlight`:

```php
    protected function casts(): array
    {
        return [
            'head' => 'collection',
            'date' => 'datetime:Y-m-d',
            'published' => 'boolean',
            'highlight' => 'boolean',
        ];
    }
```

Another thing to mention about casting, if you are casting the `head` field as collection you can loop through the `head` attribute, for example in your blade template/component you can loop through the articles and for each article you can loop thourgh head items:

```php
@foreach ($articles as $article)
  @if (! is_null($article->head))
    @foreach ($article->head as $headItems)
      <div class="mx-3 px-8 badge badge-neutral">{{ $headItems["tag"] }}</div>
    @endforeach
  @else
    <div class="mx-3 px-8 badge badge-ghost">No Tag</div>
  @endif
@endforeach
```

## Takeaways

Fusion redefines content management in Laravel development, offering a practical and effective solution for building content-driven Web sites. Leveraging Markdown and Frontmatter, Fusion enables developers to easily create structured, database-free content. Whether it simplifies content management workflows or eliminates database complexities, Fusion is a versatile tool in the Laravel Web developer's arsenal.
Embrace Fusion and embark on a journey toward efficient and simplified Web site development with Laravel via Markdown.

## Thank you!

Your feedback is invaluable to us. If you found this article helpful, please consider liking/sharing the article, or starring our GitHub repository.
We appreciate your support in making Fusion even better!!!