We wrote a GitHub Issue and Airframe commited to a new branch and opened a pull request in GitHub. We reviewed & merged Airframe's PR and now we have a blog!
The code in this article is what we actually use to render our blog. In fact, it's what renders this post!
We used Airframe to build this feature before turning it into a tutorial. We spent 1 minute writing our issue, 1 minute letting Airframe draft the PR, and 1 minute reviewing and merging the PR.
We need to be able to publish blog posts quickly and easily.
Idea is to have a directory of markdown files in resources that's /resources/markdown/blog
Then we need a route at /blog/{slug} that loads the correct markdown file based on the markdown filename for the slug
The goal of this issue is to implement a Markdown-based blogging system within our Laravel application. This will allow us to publish blog posts quickly and easily by utilizing Markdown files.
resources/markdown/blog
. This directory will store all blog posts in Markdown format./blog/{slug}
. The {slug}
parameter will correspond to the filename of the Markdown file (without the .md
extension) that will be loaded and displayed.resources/markdown/blog
if it does not already exist.routes/web.php
:
Route::get('/blog/{slug}', [BlogController::class, 'show']);
BlogController
, implement the show
method:
resources/markdown/blog/{slug}.md
.Parsedown
).resources/views/blog/show.blade.php
) to display the blog post content./blog/{slug}
correctly loads and displays the corresponding Markdown file.We then used Airframe to generate a pull request with the optimized issue. Airframe generated some great code, but used a markdown parser that we realized we didn't want, since we were already using spatie/laravel-markdown
in our project.
<?php
namespace App\Http\Controllers; // Define the namespace for the BlogController
use Illuminate\Http\Request; // Import the Request class
use Illuminate\Support\Facades\Storage; // Import the Storage facade
use App\Http\Controllers\Controller; // Import the base Controller class
use Parsedown; // Import the Parsedown Markdown parser
class BlogController extends Controller // Define the BlogController class
{
// Method to show a blog post
public function show($slug) // Accepts the slug as a parameter
{
// Construct the file path for the Markdown file
$filePath = resource_path('markdown/blog/' . $slug . '.md'); // Build the path to the Markdown file
// Check if the Markdown file exists
if (file_exists($filePath)) { // If the file exists
$markdownContent = file_get_contents($filePath); // Read the content of the Markdown file
$parsedown = new Parsedown(); // Create a new instance of Parsedown
$htmlContent = $parsedown->text($markdownContent); // Convert Markdown to HTML
// Return the view with the parsed HTML content
return view('blog.show', ['content' => $htmlContent]); // Pass the HTML content to the view
}
// If the file does not exist, return a 404 response
abort(404, 'Blog post not found.'); // Trigger a 404 error with a message
}
<!DOCTYPE html> <!-- Start of the HTML document -->
<html lang="en"> <!-- HTML language attribute set to English -->
<head> <!-- Head section of the document -->
<meta charset="UTF-8"> <!-- Character encoding set to UTF-8 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- Responsive viewport settings -->
<title>Blog Post</title> <!-- Title of the page -->
</head>
<body> <!-- Body section of the document -->
<div class="container"> <!-- Container for the blog post -->
{!! $content !!} <!-- Display the parsed HTML content -->
</div>
</body>
</html>
We reviewed the PR and requested changes to remove the markdown parser and use the <x-markdown>
component provided by the spatie/laravel-markdown
package instead. Airframe made the changes to the file as we requested, and we were ready to merge the PR!
Airframe then made the requested updates to the code and committed them to the existing PR:
if (file_exists($filePath)) { // If the file exists
$markdownContent = file_get_contents($filePath); // Read the content of the Markdown file
$parsedown = new Parsedown(); // Create a new instance of Parsedown
$htmlContent = $parsedown->text($markdownContent); // Convert Markdown to HTML
// Return the view with the parsed HTML content
return view('blog.show', ['content' => $htmlContent]); // Pass the HTML content to the view
// Return the view with the Markdown content as a string
return view('blog.show', ['content' => $markdownContent]); // Pass the Markdown content to the view
}
<body> <!-- Body section of the document -->
<div class="container"> <!-- Container for the blog post -->
{!! $content !!} <!-- Display the parsed HTML content -->
<x-markdown>{{ $content }}</x-markdown> <!-- Use the existing x-markdown component to render the Markdown content -->
</div>
</body>
That's it! We merged the PR and now have a blog system in our Laravel app that uses Markdown files to render blog posts.
In today's fast-paced development environment, creating content should be as streamlined as possible. Markdown is a popular choice among developers for writing formatted text, and integrating it into your Laravel application can greatly enhance your blogging workflow. In this blog post, we’ll walk through the steps to build a simple Markdown-based blogging system in Laravel using the spatie/laravel-markdown
package.
Markdown allows you to write formatted text using an easy-to-read, easy-to-write plain text format. It’s perfect for writing blog posts because it’s both powerful and simple to use. By using Markdown, you can focus on writing content without worrying about HTML tags and other complexities.
Why not release this as a package?
Packages require maintenance, updates, and compatibility checks. By implementing this feature directly in your Laravel application, you have full control over the codebase and can easily customize it to fit your specific needs.
To render Markdown content in Laravel, we’ll use the spatie/laravel-markdown
package. This package provides a convenient way to convert Markdown to HTML using Blade components.
First, install the package via Composer:
composer require spatie/laravel-markdown
Once the package is installed, it will automatically register its service provider. You can optionally publish the configuration file if you need to customize the Markdown rendering settings:
php artisan vendor:publish --tag="markdown-config"
Next, we need a place to store our Markdown files. Within the Laravel project, create a directory named resources/markdown/blog
. This directory will house all the Markdown files that represent your blog posts.
mkdir -p resources/markdown/blog
Define a route in routes/web.php
that will handle requests for blog posts. The route will map to a BlogController
which we'll create shortly. The {slug}
parameter in the URL corresponds to the filename of the Markdown file (excluding the .md
extension).
Route::get('/blog/{slug}', [BlogController::class, 'show'])->name('blog.show');
Create a new controller named BlogController
using the Artisan command:
php artisan make:controller BlogController
In BlogController
, we’ll implement a show
method that handles the logic of loading and rendering a Markdown file.
Here’s the code for the BlogController
:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use App\Http\Controllers\Controller;
class BlogController extends Controller
{
public function show($slug)
{
$filePath = resource_path('markdown/blog/' . $slug . '.md');
if (file_exists($filePath)) {
$markdownContent = file_get_contents($filePath);
return view('blog.show', ['content' => $markdownContent]);
}
abort(404, 'Blog post not found.');
}
}
In this method:
Now that we have the Markdown content, we need to render it as HTML. The spatie/laravel-markdown
package provides an x-markdown
Blade component that makes this process incredibly simple.
Here’s the code for the view resources/views/blog/show.blade.php
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Blog Post</title>
</head>
<body>
<div class="container">
<x-markdown>{{ $content }}</x-markdown>
</div>
</body>
</html>
The x-markdown
component automatically converts the Markdown content into HTML, allowing you to easily display it on your blog page. This component is provided by the spatie/laravel-markdown
package and leverages the league/commonmark
package under the hood for the actual parsing.
And there you have it—a simple yet powerful Markdown-based blog renderer in Laravel. By leveraging Laravel's routing, controllers, Blade templates, and the spatie/laravel-markdown
package, you can quickly implement a blogging system that is both developer-friendly and scalable.