Compare commits
8 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5780ceae46 | |||
| 48f5e7b46c | |||
| 6fd9f47325 | |||
| d2e0fbdd73 | |||
| ed6188bc75 | |||
| ff22a0637e | |||
| cea509a0ce | |||
| 185dc5f662 |
8 changed files with 104 additions and 62 deletions
|
|
@ -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" }
|
||||
]
|
||||
}
|
||||
],
|
||||
|
|
|
|||
28
CHANGELOG.md
28
CHANGELOG.md
|
|
@ -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
|
||||
|
|
|
|||
81
README.md
81
README.md
|
|
@ -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!)*
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
4
package-lock.json
generated
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "portfolio",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue