Compare commits

...

8 commits
v1.0.0 ... main

Author SHA1 Message Date
5780ceae46
chore: Release 1.1.0
## [1.1.0](https://ssh.git.badblocks.dev/badbl0cks/portfolio/compare/v1.0.1...v1.1.0) (2025-08-15)

### New Features

* allow project card to show on-the-way button for projects not yet uploaded ([d2e0fbd](d2e0fbdd73))

### Bug Fixes

* add <a href="[#projects](https://ssh.git.badblocks.dev/badbl0cks/portfolio/issues/projects)"> around the View My Work button. update wording on ([6fd9f47](6fd9f47325))

### Refactor

* change button text to be more clear ([ed6188b](ed6188bc75))

### Chores

* merge staging changes for next release ([48f5e7b](48f5e7b46c))
2025-08-15 06:21:24 +00:00
48f5e7b46c
chore: merge staging changes for next release 2025-08-15 06:20:11 +00:00
6fd9f47325
fix: add <a href="#projects"> around the View My Work button. update wording on
Some checks failed
Build/Deploy / trigger-dev-build (push) Has been cancelled
Build/Deploy / trigger-staging-build (push) Has been cancelled
Build/Deploy / trigger-main-build (push) Has been cancelled
index page
2025-08-14 23:10:59 -07:00
d2e0fbdd73
feat: allow project card to show on-the-way button for projects not yet uploaded
to my git and linked
2025-08-14 23:08:53 -07:00
ed6188bc75
refactor: change button text to be more clear 2025-08-14 23:08:05 -07:00
ff22a0637e
chore: Release 1.0.1
## [1.0.1](https://ssh.git.badblocks.dev/badbl0cks/portfolio/compare/v1.0.0...v1.0.1) (2025-08-15)

### CI/CD

* don't hide or ignore any commit types, at least bump the patch version if ([185dc5f](185dc5f662))

### Chores

* merge staging changes for next release ([cea509a](cea509a0ce))
2025-08-15 03:55:53 +00:00
cea509a0ce
chore: merge staging changes for next release 2025-08-15 03:54:40 +00:00
185dc5f662
ci: don't hide or ignore any commit types, at least bump the patch version if
new commits are detected by release.yml
2025-08-14 20:38:32 -07:00
8 changed files with 104 additions and 62 deletions

View file

@ -14,7 +14,7 @@
{ "type": "ci", "section": "CI/CD" },
{ "type": "docs", "section": "Documentation" },
{ "type": "refactor", "section": "Refactor" },
{ "type": "chore", "hidden": true }
{ "type": "chore", "section": "Chores" }
]
},
"plugins": [
@ -31,11 +31,11 @@
{ "type": "deps", "release": "minor" },
{ "type": "new", "release": "minor" },
{ "type": "fix", "release": "patch" },
{ "type": "build", "release": false },
{ "type": "ci", "release": false },
{ "type": "chore", "release": false },
{ "type": "docs", "release": false },
{ "type": "refactor", "release": false }
{ "type": "build", "release": "patch" },
{ "type": "ci", "release": "patch" },
{ "type": "chore", "release": "patch" },
{ "type": "docs", "release": "patch" },
{ "type": "refactor", "release": "patch" }
]
}
],

View file

@ -1,3 +1,31 @@
## [1.1.0](https://ssh.git.badblocks.dev/badbl0cks/portfolio/compare/v1.0.1...v1.1.0) (2025-08-15)
### New Features
* allow project card to show on-the-way button for projects not yet uploaded ([d2e0fbd](https://ssh.git.badblocks.dev/badbl0cks/portfolio/commit/d2e0fbdd737b42182af9b54adc77310749ccf794))
### Bug Fixes
* add <a href="[#projects](https://ssh.git.badblocks.dev/badbl0cks/portfolio/issues/projects)"> around the View My Work button. update wording on ([6fd9f47](https://ssh.git.badblocks.dev/badbl0cks/portfolio/commit/6fd9f4732566bf9366cd05a7abf4310dea3fbe16))
### Refactor
* change button text to be more clear ([ed6188b](https://ssh.git.badblocks.dev/badbl0cks/portfolio/commit/ed6188bc759cbf0ab4c1f2ad5a548d8ea31dd7a5))
### Chores
* merge staging changes for next release ([48f5e7b](https://ssh.git.badblocks.dev/badbl0cks/portfolio/commit/48f5e7b46c1e1a318d1eca26ab1d9365d1acdbcc))
## [1.0.1](https://ssh.git.badblocks.dev/badbl0cks/portfolio/compare/v1.0.0...v1.0.1) (2025-08-15)
### CI/CD
* don't hide or ignore any commit types, at least bump the patch version if ([185dc5f](https://ssh.git.badblocks.dev/badbl0cks/portfolio/commit/185dc5f66267d5ab8446ab51e03f051a4210e0b3))
### Chores
* merge staging changes for next release ([cea509a](https://ssh.git.badblocks.dev/badbl0cks/portfolio/commit/cea509a0cee89047e9b261c87906cd05349ca1fd))
## 1.0.0 (2025-08-15)
### New Features

View file

@ -5,12 +5,12 @@ A sweet little portfolio site with some absolutely ridiculous SMS shenanigans bu
## ✨ The Good Stuff
- 🌙 **Night mode everything** - DaisyUI components that won't burn your eyeballs
- 📱 **SMS contact form** - Because I get wayyy too many emails already
- 🎭 **Snazzy animations** - ScrollReveal + Typed.js doing their thang
- 📱 **SMS contact form** - Because I get wayyyyy too many emails already
- 🎭 **Snazzy animations** - ScrollReveal, Typed.js, and more doing their thang
- 🐳 **Zero-downtime deploys** - Blue-green magic with Docker & HAProxy
- 🔧 **Overengineered infrastructure** - We like to do things the hard way over here
- 🔧 **Overengineered infrastructure** - If you didn't spend a week working on a fun but useless feature that will never be used, did you really do any development?
## 🏃‍♂️ Getting Started
## 🏃‍♂️ Wanna Try It Out?
```bash
# Grab the dependencies
@ -38,9 +38,9 @@ bun run generate
## 📞 Contact Form Wizardry
Two-step verification dance: drop your message → prove you're human with SMS → message gets yeeted to my phone via some questionable infrastructure choices.
Two-step verification anti-abuse dance: drop your message → prove you're human with SMS → message gets yeeted to my phone via some very questionable infrastructure choices!
Rate-limited because spam just sucksssss! 🛡️
Rate-limited because spam just sucks!
## 🏗️ Infrastructure Tomfoolery
@ -57,8 +57,8 @@ Here's where things get ~completely~ unhinged:
I'm running the `android-sms-gateway` app on a completely deranged setup:
- **Hardware:** Pixel 1 with the battery surgically removed (no spicy pillows please)
- **Power:** Permanently plugged into the wall like some kind of cursed landline
- **Network:** Hardwired ethernet via USB-C adapter ("WhyFight" with WiFi?)
- **Purpose:** Sits there 24/7 just waiting to send OTPs and forward your messages to my actual phone
- **Network:** Hardwired ethernet via attached USB hub (WhyFight with WiFi?)
- **Purpose:** Sits there patiently 24/7 just waiting to send OTPs and forward your messages to my actual phone
The whole contraption lives on my home network and the VPS reaches it through a WireGuard tunnel because apparently I enjoy making simple things complicated just to save $2 a month!
@ -67,84 +67,83 @@ The whole contraption lives on my home network and the VPS reaches it through a
This repo follows a three-branch strategy with some absolutely bonkers automated promotions because manually managing branches is for chumps:
- **`dev`** - Where the magic happens! All new features and fixes go here
- **`staging`** - Integration testing playground, auto-promoted from dev daily at 13:00 UTC via scheduler
- **`main`** - Production branch, gets promoted from staging weekly on Sundays at 14:00 UTC via scheduler
- **`staging`** - Integration testing playground, auto-promoted from dev daily at 04:00 PST via scheduler
- **`main`** - Production branch, gets promoted from staging weekly on Sundays at 05:00 PST via scheduler
### The Repository Setup
We're running a bit of a funky setup here:
- **Primary repo:** Git origin (configurable - can be self-hosted, GitHub, etc.)
- **GitHub Mirror:** Optional push-only mirror for CI/CD and visibility
It's a bit of a funky setup here:
- **Primary repo:** My Forgejo server (I obviously like self-hosting things)
- **GitHub Mirror:** Forgejo repo configured to push-only mirror to Github for CI/CD and visibility
- **CI/CD:** GitHub Actions (triggered by pushes or scheduled workflows)
So the workflow is: push to Git origin → (optional mirror to GitHub) → GitHub Actions does the heavy lifting.
So the workflow is: do some coding, commit and push to my Forgejo instance → mirror to GitHub → GitHub Actions does the heavy lifting so my little VPS doesn't have to suffer so much.
### Branch Promotion Dance 💃
**Daily (dev → staging):**
- Robot overlord wakes up at 13:00 UTC every day
- Checks if dev has new commits (because we're not animals)
- Wannabe robot overlord wakes up at 04:00 PST every day
- Checks if dev has new commits (because we're not doing all this work for nothing!)
- Actually validates the build passed via GitHub API (fancy!)
- Fast-forward merge to staging (keeps git history from becoming spaghetti)
- Supports `[skip ci]` in commit messages for when you inevitably break something
- Manual "YOLO deploy anyway" button available
**Weekly (staging → main):**
- Sunday funday at 14:00 UTC for production releases
- Sunday funday at 05:00 PST for production releases
- Runs semantic-release for proper versioning (we're not completely chaotic)
- Some gnarly branch gymnastics to keep everything synchronized
- SSH-signed commits because we pretend to care about security
- Seduce the GitHub API with a token for build status
- SSH-signed commits because I <3 cryptography
- Manual panic button also available
### 🤖 The 5-Workflow CI/CD Circus
Because apparently one workflow wasn't enough, we've got a whole circus of automation:
Because apparently one workflow is never enough, I've got a whole collection of automations:
1. **`build.yml`** - The overachiever that builds everything
1. **`build.yml`** - The overachiever that builds everything and gets good grades
- Gets triggered by basically anything that moves
- Smart enough to skip builds when we already did the work (lazy efficiency!)
- Hoards artifacts for 2 days like a digital packrat
- Has more caching layers than a wedding cake
- Smart enough to skip builds when we already did the work (lazy!)
- Hoards artifacts for 30 days like a digital packrat
- Has more caching layers than an onion-flavored wedding cake
2. **`deploy.yml`** - The deployment minion (does what it's told)
- Gets bossed around by the other workflows
- Juggles blue-green deployments without dropping anything
- Speaks fluent SSH and WireGuard
- Downloads artifacts faster than you can say "containerization"
- Downloads artifacts faster than you can say "docker load"
3. **`stage.yml`** - The daily grind automation
- Wakes up every day to promote dev → staging
- Actually checks if builds passed (responsible adult behavior)
- Signs commits with SSH keys because we're fancy like that
- Signs commits with SSH keys because I'm fancy like that
- Has a "force" option for when things go sideways
4. **`release.yml`** - The weekly release party host
4. **`release.yml`** - The weekly release partayyyy
- Shows up every Sunday with semantic versioning
- Does some serious git branch yoga to keep everything aligned
- Maintains that linear history we all pretend to care about
- Maintains that linear history we all pretend to care about but never look at
5. **`scheduler-*.yml`** - The workflow orchestrators
- Exists because GitHub has weird scheduling quirks
- Makes sure the right code runs from the right branch
- Makes sure the workflow runs from the right branch
- Basically the puppet masters of this whole operation
## 🚢 Deployment Shenanigans
Pushes to `staging` or `main` branches trigger some absolutely wild blue-green deployment wizardry with more caching than your browser history!
Pushes to `staging` or `main` branches trigger some absolutely wild blue-green deployment wizardry with more caching than your browser!
### Blue-Green Magic ✨
1. **Build Phase:** Smart enough to skip rebuilding stuff we already built (because efficiency is sexy)
2. **Deploy Phase:** Download cached goodies and poke the new containers to make sure they're alive
3. **Switch Phase:** HAProxy does the old switcheroo faster than a shell game
4. **Cleanup Phase:** Yeet the old containers into the digital void
5. **Artifact Hoarding:** Keeps build artifacts for 30 days like a digital packrat with commitment issues
6. **Moon Phases:** 🌑 🌒 🌓 🌔 🌝 🌖 🌗 🌘 🌚 (for spiritual alignment)
3. **Configure Phase:** Update HAProxy's config, then call it's cell phone and SIG_HUP!
3. **Deploy Phase:** Download cached goodies and poke the new containers to make sure they're alive
4. **Cleanup Phase:** Yeet the old containers into the great /dev/null
5. **Artifact Hoarding:** Keeps old build artifacts much longer than you'd ever need (30 days)
6. **Moon Phases:** 🌑 🌒 🌓 🌔 🌝 🌖 🌗 🌘 🌚
### GitHub Secrets Setup
Deployments generate the needed .env from GitHub secrets, so make sure to slap some secrets up first!
### GitHub Secrets/.env Setup
Deployments generate the needed .env from GitHub secrets, so make sure to slap some secrets up first or copy the .env.example file and edit!
### WireGuard Setup
The stack is rocking gluetun, so just set up your WIREGUARD_ environment variables in Github secrets:
The stack is rocking the popular [gluetun](https://github.com/qdm12/gluetun) container, so just set up your WIREGUARD_ environment variables with your Github secrets!
## 🔒 Security Fortress
@ -153,7 +152,7 @@ The stack is rocking gluetun, so just set up your WIREGUARD_ environment variabl
- 🔢 TOTP phone verification + rate limiting
- 🔤 ASCII-only validation (No spammy weird characters please!)
## 🆘 When Things Go Wrong
## 🆘 Note to Self: When Things Go Wrong
```bash
# Check if containers are actually alive
@ -187,4 +186,4 @@ This project is licensed under **AGPL 3.0 only** - see the [LICENSE](LICENSE) fi
---
*Built with ❤️ and lots of ☕! (Sheesh, if you've read this far, just hire me, please!)*
*Built with ❤️ and lots of ☕! (Wow, if you've read this far, and you're hiring, just hire me!)*

View file

@ -145,7 +145,7 @@
:disabled="!isVerified || isSendingMessage || isMessageSent"
>
<span v-if="isSendingMessage" class="loading loading-spinner" />
Text Me! (Rob )
Send Me a Text!
</button>
</div>
</form>

View file

@ -18,6 +18,9 @@
>
Source Code
</button>
<button v-else class="btn btn-secondary btn-disabled">
Source Code (on the way!)
</button>
</div>
</div>
</div>

View file

@ -8,7 +8,9 @@
Hi, I'm <span class="text-primary">Rob</span>!
</h1>
<p class="py-6 text-2xl">I'm <span id="typed-text" /></p>
<button class="btn btn-primary">View My Work</button>
<a href="#projects"
><button class="btn btn-primary">View My Work</button></a
>
</div>
</div>
</section>
@ -30,7 +32,7 @@
</div>
<div class="md:w-2/3">
<p class="text-lg mb-4">
Hiya! I'm a passionate and creative web developer with a knack for
Hi! I'm a passionate and creative web developer with a knack for
building beautiful and functional websites. I love learning new
technologies and I'm always looking for exciting projects to work
on.
@ -52,34 +54,44 @@
</section>
<section id="projects" class="py-20 bg-base-200">
<div class="container mx-auto px-4">
<h2 class="text-4xl font-bold text-center mb-12">Current Projects</h2>
<h2 class="text-4xl font-bold text-center mb-12">Works in Progress</h2>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
<ProjectCard
title="PKMNTradeClub"
description="A web app to facilitate trading between players of Pokémon TCG Pocket, which frustratingly lacks trade matching features. Currently in development!"
description="A project started to learn and practice Django while facilitating trading between players of Pokémon TCG Pocket, which frustratingly lacks trade matching features."
source-code-link="https://git.badblocks.dev/badbl0cks/pkmntrade.club"
/>
<ProjectCard
title="This Portfolio Site!"
description="A portfolio site built to explore and learn Nuxt.js while showcasing my projects and skills."
source-code-link="https://git.badblocks.dev/badbl0cks/portfolio"
/>
<ProjectCard
title="Home Lab & Self-Hosted Solutions"
description="A collection of hardware, projects, and experiments to learn and explore new technologies and concepts, as well as augment and enhance my personal tech space."
description="A collection of hardware, software projects, and experiments to learn and explore new technologies and concepts, as well as augment and enhance my personal tech space."
/>
</div>
</div>
</section>
<section id="projects" class="py-20 bg-base-200">
<div class="container mx-auto px-4">
<h2 class="text-4xl font-bold text-center mb-12">Past Projects</h2>
<h2 class="text-4xl font-bold text-center mb-12">
Neat Things I've Done
</h2>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
<ProjectCard
title="PokeEmerald Mods"
description="Various mods for one of my favorite games, Pokémon Emerald, to streamline my replays with custom QoL features."
/>
<ProjectCard
title="EditMii"
description="A Python script that allows users to view their WiiU Mii character's data and optionally change the Mii's name. Created in order to easily set flashy, custom names for online play."
source-code-link="https://git.badblocks.dev/badbl0cks/pokeemerald"
/>
<ProjectCard
title="BOTW Completer"
description="A Nintendo Switch application that helps users find missing items and locations in Breath of the Wild by modifying the save file to add stamps to the in-game map."
source-code-link="https://git.badblocks.dev/badbl0cks/botw-completer"
/>
<ProjectCard
title="EditMii"
description="An app that allows users to view their WiiU Mii character's data and optionally change the Mii's name. Created in order to easily set flashy, custom names for online play."
/>
</div>
</div>
@ -102,8 +114,8 @@ onMounted(() => {
const { $sr } = useNuxtApp();
const typedOptions = {
strings: [
"an aspiring Software Engineer.",
"a self-taught Web Developer with experience.",
"a Bachelor's degree holder in Software Engineering.",
"a Full-Stack Magician.",
"a UI/UX Problem Solver.",
"a Web Accessibility Advocate.",

4
package-lock.json generated
View file

@ -1,12 +1,12 @@
{
"name": "portfolio",
"version": "1.0.0",
"version": "1.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "portfolio",
"version": "1.0.0",
"version": "1.1.0",
"hasInstallScript": true,
"dependencies": {
"@nuxt/fonts": "0.11.4",

View file

@ -1,6 +1,6 @@
{
"name": "portfolio",
"version": "1.0.0",
"version": "1.1.0",
"private": true,
"type": "module",
"scripts": {