Re-designing my site has been something I have been putting off for far too long now. My goal has been to build my personal website to be a good representation of me and a place on the internet that I am happy with. After taking action, this is what I did and I also got it completed before my target date, which is a good birthday present for me!
What My Old Site Was Running On
I was using an old Jekyll setup as a static site generator that I hosted on Github pages. This setup served it's purpose well for a long time. However, I've had so many ideas that it was hard to justify sticking with it and building on top of it. Also, when I got around to writing a new post, I would have to stuggle with my machine's Ruby version to get it serving on local. It actually discourged any motivation to put any effort into my personal site. I've always had the thought that this needed to change.
Why Migrate to Laravel? Why Not (Insert Framework Here)?
There were quite a few options I considered! I initially looked for another static site generator such as Hugo and I was also interested in Astro. However, I decided that it wasn't very efficient for me to put in the hours to learn a new tool and struggle with said tool. Since I've been using Laravel for years and I can build the basics of my new site in less than 10 hours. Considering that, with what I want to build, I know I can do that in Laravel quickly. I chose to go with familiarity over shinyness.
How I Built It
So with a fresh Laravel project installed, I knew I needed a few things to deal with my blog posts, so I needed a few things to parse my frontmatter (probably a YAML parser) and something to parse my markdown. I definitely wanted to keep that part of my site static, and wanted to avoid my posts being DB driven.
Actually, I got most of my inspiration from Christoph Rumpel's post, which I followed along quite a bit. You should check out! https://christoph-rumpel.com/2018/01/how-i-redesigned-my-blog-and-moved-it-from-jekyll-to-laravel
For the YAML front matter parsing, I used one of Spatie's amazing packages: https://github.com/spatie/yaml-front-matter.
For markdown parsing, I thought I was clever and could get away with just using Laravel's Str::markdown()
helper. It worked great, but it had trouble parsing my iframe embeds, so I just installed and integrated CommonMark from The PHP League and added in this helper function.
use League\CommonMark\CommonMarkConverter;
function markdown($markdown)
{
return app(CommonMarkConverter::class)->convert($markdown);
}
Here's the function that powers the blog:
private function postList()
{
$files = File::files($this->postsPath);
return collect($files)
->filter(function($file) {
return str_ends_with($file->getFilename(), '.markdown');
})
->map(function($file) {
[$blogFilename, $extension] = explode('.', $file->getFilename(), 2);
$document = YamlFrontMatter::parse(file_get_contents($file));
$splitDate = explode(" ", $document->date);
$date = Carbon::createFromFormat('Y-m-d', $splitDate[0]);
return (object) [
'path' => $file->getPath(),
'date' => $date,
'slug' => $blogFilename,
//'url' => route('posts.show', [$date->format('Y'), $date->format('m'), $slug]),
'title' => $document->title,
'contents' => markdown($document->body()),
'summary_short' => mb_strimwidth($document->body(), 0, 140, "..."),
];
})
->sortByDesc('date');
}
If I want to grab a single post based on it's slug inside of a controller, I can do something like this:
public function post($slug)
{
$post = $this->postList()->firstWhere('slug', $slug);
$seoData = [
'title' => $post->title,
'description' => $post->summary_short,
'url' => url()->current(),
];
return view('posts.single', [
'post' => $post,
'seoData' => $seoData,
]);
}
Also note, I have a my contents inside my project root as contents/_posts
so I just include that in my constructor for simplicity like so: $this->postsPath = base_path('content/_posts/');
I can also use the postsList
to loop through my posts in a blade template:
<section class="mt-10">
<h2 class="text-2xl font-bold mb-4">My Thoughts</h2>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
@foreach ($posts as $post)
<div class="bg-white rounded-lg shadow p-4">
<h3 class="text-lg font-bold hover:underline"><a href="{{ route('blog.post', $post->slug) }}" class="text-[#c026d3] no-underline">{{ $post->title }}</a></h3>
<p class="text-gray-400 text-xs">{{ $post->date->format('m.d.Y') }}</p>
<p class="text-gray-600 text-sm">{{ $post->summary_short }}</p>
<a href="{{ route('blog.post', $post->slug) }}" class="text-blue-500 hover:underline mt-2 block">Read more</a>
</div>
@endforeach
</div>
</section>
SEO
For SEO, I just kept things simple for the meta tags. I used @yield
and provided a default.
<meta name="description" content="@yield('description', 'Software Engineer from Fresno, California. Just chilling, programming and building apps.')">
<meta property="og:title" content="@yield('og:title', 'Tyler Souza. Software Engineer')">
<meta property="og:description" content="@yield('og:description', 'Software Engineer from Fresno, California. Just chilling, programming and building apps.')">
<meta property="og:image" content="@yield('og:image', asset('images/me.jpg'))">
<meta property="og:url" content="@yield('og:url', url()->current())">
<meta name="twitter:card" content="summary_large_image">
In my blog post template, I can add in those sections if I declare them in my controller action.
$seoData = [
'title' => $post->title,
'description' => $post->summary_short,
'url' => url()->current(),
];
@extends('layouts.site')
@section('title', $seoData['title'])
@section('description', $seoData['description'])
@section('og:title', $seoData['title'])
@section('og:description', $seoData['description'])
@section('og:url', $seoData['url'])
@section('content')
<h1 class="text-4xl text-center mb-4">{{ $post->title }}</h1>
<p class="text-gray-400 text-xs text-center mb-4">{{ $post->date->format('m.d.Y') }}</p>
<div class="post-content">
{!! $post->contents !!}
</div>
@endsection
Styling
For CSS styles, I ended up getting the job done with Tailwind. I've only used Tailwind a handful of times, but each time use it, I enjoy it more. It definitely sped things up to get to release.
What's This Thing Running On?
Well, I didn't want this site to use a database initially, so there's none in that regard. However, I do have Postgres installed, so I plan to use that when I end up building backend features for this site. Running PHP/Nginx of course. I just ended up using Forge and called it a day. I'm running this thing on a T2.Micro
EC2 intance on AWS. The idea is to keep this thing running on the smallest setup, but be able to scale to a "beefier" server if it calls for one.
Closing Points
So there's the story on how I redesigned my site! I'm hoping it motivates me to blog out my thoughts more and build cool things for it. I hope it motivates you to build or re-build your site this year! For now, I have to get back to coding and smashing my keyboard! See ya soon.