Two Recent Demos and What I Actually Learned From Them
I used to write project summaries that listed every feature and called them wins. That felt empty. Now I force myself to write down one concrete thing that broke and how I fixed it. Here are two recent demos and the single lesson each one left me.
AnimalSounds: the base path bug
- Live demo: https://bradleymatera.github.io/AnimalSounds/
- Source: https://github.com/bradleymatera/AnimalSounds
- Stack: vanilla JavaScript, Vite, GitHub Actions
I built a simple soundboard. The code worked locally. Then I deployed it to GitHub Pages and every asset 404'd.
The browser was asking for https://bradleymatera.github.io/assets/sound.mp3, but GitHub Pages had hosted it at https://bradleymatera.github.io/AnimalSounds/assets/sound.mp3. I knew about base paths in theory, but I had never had to think about it because Vercel and Netlify usually hide that from you.
The fix was in vite.config.js:
import { defineConfig } from 'vite'export default defineConfig(({ mode }) => ({base: mode === 'production' ? '/AnimalSounds/' : '/',build: { outDir: 'dist' },}))
That is the whole thing. I also made sure the GitHub Actions workflow set NODE_ENV=production so the build picked up the right branch.
The lesson I kept: deployment is part of the feature. A demo that only runs locally is not finished.
WebGPU Triangle Demo: the pipeline is the program
- Live demo: https://bradleymatera.github.io/TriangleDemo/
- Source: https://github.com/bradleymatera/TriangleDemo
- Stack: TypeScript, WebGPU API, WGSL
Drawing a triangle in the 2D canvas API is three lines of code. In WebGPU it took me about 150 lines of boilerplate just to get a red triangle on screen. That is not a complaint. It is the point.
WebGPU makes you configure the pipeline explicitly:
- Request an adapter from the browser.
- Request a device from the adapter.
- Configure the canvas context with a texture format.
- Create a render pipeline with vertex and fragment shaders.
- Encode a command to draw.
The shader language, WGSL, is stricter than GLSL. One wrong type and the GPU validation layer throws an error that looks like a crash. I spent an hour debugging a vec2 passed where a vec4 was expected. It was a single line.
The lesson I kept: in modern graphics programming, you are not drawing shapes. You are configuring a machine that draws shapes. The mental model is pipeline first, pixels second.
Why I write this way
Each project now gets one sentence: what it taught me. AnimalSounds is my reference for Vite base paths on GitHub Pages. TriangleDemo is my reference for WebGPU device initialization. When I hit the same problem again, I do not start from zero. I start from the note.
If you are building a portfolio, you do not need more features. You need more notes about what broke.