Back to Blog
laravel self-hosting docker tutorial

Building Player One: How I Built My Portfolio Site with Laravel 13 and a Lot of Coffee

· 5 min read
Building Player One: How I Built My Portfolio Site with Laravel 13 and a Lot of Coffee

Who Am I?
I'm a self-hosting enthusiast who's been running a home server since 2020. What started as a Plex setup quickly spiralled into a full infrastructure - Docker containers, reverse proxies, media automation, the whole kit and caboodle. I run openSUSE Server powering everything from Plex and StreamPulse to Portainer and Azure DevOps pipelines.

Along the way I built two applications - StreamPulse, a real-time Plex monitoring dashboard, and MediaHub, a unified interface for managing Radarr and Sonarr. But I needed somewhere to showcase them. A portfolio site that actually reflected who I am: a tinkerer, a gamer, and someone who reckons your data should stay yours.

That's how Player One was born.

The Tech Stack
I wanted the stack to be modern but practical. No over-engineering, no JavaScript framework drama - just tools I enjoy using:

Laravel 13 - The backbone. I've been writing PHP for yonks and Laravel just keeps getting better. Version 13 with PHP 8.3 is an absolute ripper.

Filament 5.5 - The admin panel. It gave me a fully-featured CMS for blog posts, contacts, changelogs, and site settings without writing admin views from scratch. Ridiculously good.

Tailwind CSS 4 - The design system. Dark mode, custom accent colours, responsive layouts - all utility-first.

Alpine.js 3 - The interactivity layer. Lightweight enough that the entire site ships with minimal JavaScript. No wuckas.

SQLite - The database. For a portfolio site with modest traffic, there's no need for MySQL. One file, zero config.

Vite 8 - The build tool. Fast, simple, and integrated perfectly with Laravel.

Features I'm Chuffed About

The Interactive Terminal
The About page is a fully functional terminal emulator. You can type commands like whoami, skills, neofetch, and projects to learn about me. It supports command history with the up/down arrows, tab completion, and even has a custom neofetch with ASCII art. It's built entirely with Alpine.js - no backend calls needed. Give it a burl.

Dark Mode with Style
The dark/light toggle isn't just a class swap. It uses the View Transitions API to create a radial wipe animation that ripples out from wherever you click the toggle button. It's a small detail, but it makes the experience feel properly polished.

The Command Palette
Press Ctrl+K anywhere on the site and a command palette pops up - just like VS Code. You can fuzzy-search pages, toggle dark mode, or open keyboard shortcuts. It's the kind of feature that makes a developer portfolio feel like a developer portfolio.

Accent Colour Picker
The site defaults to cyan, but you can switch the entire colour scheme to purple, green, or orange. Your preference is saved in localStorage. Every primary colour across the site updates instantly - she'll be right with whichever you pick.

The Konami Code
Yeah, there's an Easter egg. Enter the classic ↑ ↑ ↓ ↓ ← → ← → B A and see what happens. I'm not going to spoil it for you.

News Aggregator
The News page pulls articles from DEV.to, Hacker News, and RSS feeds from Ars Technica, TechCrunch, MIT Technology Review, The Verge, Wired, The Register, and Hacker Noon. Everything is cached and sorted by date. No API keys needed for most sources. It just works.

Blog with Reading Progress
You're reading it right now. Each post has a gradient progress bar, estimated read time, tag filtering, and clean typography. The RSS feed at /feed is Atom-formatted for anyone who still uses feed readers (respect, legends).

Contact Form with Anti-Spam
The contact form uses Cloudflare Turnstile for CAPTCHA, a honeypot field, and rate limiting at five submissions per minute. No reCAPTCHA annoyance, no tracking. Just vibes.

Deploying to Shared Hosting
Here's where it got interesting. I went with OnlyDomains for hosting - simple, affordable shared hosting with cPanel. The catch: no SSH access, and cPanel expects everything in public_html/.

Laravel doesn't work that way. The public folder is the web root, but everything else (your app code, vendor directory, database) should live outside of it. So I split the project:

~/playerone/ - All the Laravel application code

~/public_html/ - Just the contents of public with a modified index.php

The app.php automatically adjusts the public path when it detects it's running under cPanel. No hardcoded paths, works in both environments. Too easy.

For file storage, rather than relying on symlinks, I created a lightweight route that serves public storage files directly - no symlink needed, and it works perfectly on cPanel where symlinks can be temperamental.

Migrations ran locally, and the SQLite database file was uploaded via SFTP.

It's not the fanciest deployment pipeline going around, but it works a treat for a site that updates infrequently.

What I Learned
Alpine.js is criminally underrated. For sites that don't need React or Vue, it's perfect. The entire interactive layer - terminal, command palette, theme switching, typing effects, scroll animations - is one JavaScript file.

Filament is a superpower. Standing up an admin panel with CRUD resources, MFA authentication, and file uploads took less time than writing this blog post. Fair dinkum.

SQLite is fine. For personal projects, portfolio sites, and anything that isn't handling concurrent writes from thousands of users - just use SQLite. Don't overthink it.

Shared hosting still works. It's not Kubernetes. It's not a CI/CD pipeline. But for a portfolio site, a few bucks a month with cPanel gets the job done. Sometimes the simplest solution is the best one.

What's Next
I've got plans for more features - maybe a project showcase gallery, or integrating some of my other projects. For now though, the site does what I need it to: it shows who I am, what I build, and gives people a way to get in touch.

If you've made it this far, cheers for reading. Have a squiz around, try the terminal, find the Easter egg, and if you're building something similar - flick me a message. I'd love to hear about it.

Cookie Notice

This site uses essential cookies to ensure it functions properly. No tracking or analytics cookies are used.

Keyboard Shortcuts

Show keyboard shortcuts ?
Command palette Ctrl K
Toggle dark / light mode T

Navigation

Go to Home G H
Go to Blog G B
Go to About G A
Go to News G N
Go to Contact G C
Close / Dismiss Esc
ESC
No results found.
↑↓ navigate ↵ select
esc close