Category: Portfolio

  • I ran my portfolio through Apple’s design guidelines and most of it failed

    I had Claude audit my portfolio against Apple's Human Interface Guidelines. Clean dark theme, smooth animations, looks good on mobile. I thought it was solid.

    Nine gaps. Not edge cases. Fundamentals.

    What I didn't know I was missing

    Accessibility is one of those things you can't see when you're the one building the site. You're not navigating with a keyboard or using a screen reader. You're not someone who gets motion sick from animated backgrounds.

    I had animations in over twenty components. Card entrances, hover effects, background blobs, all assuming the user wants movement. Adding a reduced motion check to each one was tedious, but the site still looks good with animations off. Arguably better. Less noisy.

    Touch targets on mobile were embarrassingly small. The standard says 44 pixels minimum. Filter buttons on my site were well under that. A small fix with real impact.

    Decorative elements were being announced by screen readers. Animated blobs, progress bars, overlay gradients. None of them convey meaning. Adding aria-hidden to each one was simple once I knew to look for it.

    The double title bug

    While reviewing blog posts, I noticed every title showed up twice. Once from the page header, once from the content body. I'd been writing H1 titles in the markdown and the page was already rendering the title from metadata.

    The kind of thing that's invisible when you're writing posts and obvious when you're reading them.

    What I actually learned

    Accessibility is a quality bar, same as "the site loads" and "the buttons work." I should've baked it in from day one instead of treating it as an audit item.

    The portfolio is better now. Not done, but closer to something I'd be proud to show someone who navigates the web differently than I do.

  • How I Built This Portfolio (Without Really Knowing How to Code)

    How I Built This Portfolio (Without Really Knowing How to Code)

    I should be upfront about something: I'm not a developer. I have a PhD in therapeutics and an MBA. My coding education consists of one undergrad Python class I barely remember and whatever I've picked up in the last year from yelling at Claude and Cursor until things work.

    And yet here you are, reading this on a site I built. So let me tell you how that happened.

    Why Build at All?

    The easy move would have been Squarespace or a Notion site. And honestly, either would have been fine for what most people need. But I had this itch. I'd been building side projects with AI tools and I wanted a place to write about them that I actually controlled—not some platform that could change its pricing, kill its API, or bury my content in a feed.

    I also wanted to learn. Building a real site felt like the fastest way to understand how the web actually works. And after five years of research methodology, I'm wired to learn by doing.

    The Stack Decision

    Here's what I went with and why:

    Next.js because it seems to be what every serious developer recommends for React, and React is what Claude knows best. When your AI coding partner has strong opinions about a framework, it's wise to go with the flow. The App Router felt modern even though I barely understand it.

    WordPress as a headless CMS because I wanted to separate content from code. The site builds statically—all the pages are generated at build time and served as plain HTML. WordPress just holds the content and serves it through an API. This means the site is fast, cheap to host, and I can write blog posts without touching code.

    Tailwind CSS because writing real CSS felt like learning a second foreign language on top of JavaScript. Utility classes made sense to my brain—you describe what you want right where you want it.

    Cloudflare Pages for hosting because it's free and fast. The site builds, deploys, and just works.

    What Claude and Cursor Actually Did

    Here's the honest breakdown:

    Claude/Cursor handled about 80% of the code. Component structure, API integrations, TypeScript types, Tailwind styling, the WordPress API layer, Zod schema validation—all of that was generated by AI. I could not have written any of it from scratch.

    But I made all the decisions. What pages exist, what they say, how the navigation works, the color palette, the typography, the tone of voice, what content to show and what to hide. AI generated the code; I designed the experience.

    The gap is in debugging. When something broke—and things broke constantly—I couldn't always understand the error message. I'd paste the error into Claude, get a fix, apply it, and sometimes that fix would break something else. The debugging loop was the most frustrating part. AI is great at writing code. It's inconsistent at understanding why code that it wrote doesn't work.

    What Was Harder Than Expected

    Design decisions are exhausting. Every page has dozens of micro-decisions: how much spacing, what font size, which shade of teal, how the animations feel. AI can generate options but it can't tell you which one feels right. That's taste, and taste takes energy.

    The WordPress integration was fiddly. Headless WordPress sounds clean in theory—API in, content out. In practice, you're wrestling with custom post types, ACF fields, embedded media, and authentication. It works now, but it took several rounds of "why isn't this returning the data I expected?"

    Static site generation has trade-offs. Everything is fast because it's pre-built. But that means every content change requires a rebuild and deploy. It's fine for a portfolio but it took me a while to understand why my changes weren't showing up immediately.

    What I Actually Learned

    Building this site taught me more about software development than any tutorial could have. Not the syntax—I still barely know JavaScript. But the concepts: how components compose, how data flows through an application, why type safety matters, what "build time" vs "runtime" means, how CSS actually works.

    More importantly, it taught me that the barrier between "developer" and "non-developer" is thinner than I thought. With AI tools, the constraint isn't technical ability—it's knowing what you want to build and having the patience to iterate until it's right.

    The site isn't perfect. There are probably patterns in the code that would make a real developer wince. But it works, it's fast, it looks the way I want, and I understand every piece of it—even if I couldn't have written it from scratch.

    That feels like enough.

    The Meta Lesson

    The irony of writing this post on this site isn't lost on me. I built a thing to write about building things. It's recursive and a little silly.

    But that's kind of the whole point of this portfolio. I'm not trying to prove I'm a developer. I'm trying to show that I'm someone who builds things to understand them—and then writes about what I find interesting along the way.

    If that resonates with you, there's more where this came from.

  • Seven things wrong with my site (shipped in one session)

    My portfolio had been live for weeks with problems I kept ignoring. The homepage was pulling from the wrong data source. The Resources page had links going nowhere. The Shop page had fake products with made-up reviews. A placeholder icon where visual interest should be. No Open Graph images for social sharing. The Swipefile wasn't in the navigation. And there was no way for someone to support the work.

    Seven things. All small. All embarrassing in the "I showed this to someone and they immediately noticed" way.

    The technique

    There's a technique called Ralph Wiggum — named after a character known for doing things his own way. The idea is simple: write out every known issue as a numbered story, keep each one scoped to a single commit, and blast through them sequentially without overthinking.

    No sprint planning. No prioritization matrix. Just: here's what's broken, fix it, next.

    STORY-001 through STORY-007. Each one a commit.

    What got fixed

    The homepage was showing swipefile entries in the Writing section instead of actual blog posts. Built things in the wrong order — swipefile came before blog posts, so the homepage was still wired to the old source.

    The Resources page had guides listed with "New" and "Recommended" badges but no actual links. Changed them to "Coming Soon." At least that's honest.

    The Shop page was the worst offender. Mock product data from a template — star ratings and prices for things that don't exist. Stripped it down to a single "Coming Soon" message.

    Open Graph images were missing entirely. If someone shared a link on Twitter or LinkedIn, blank preview. Invisible to the site owner, but it's the first impression for everyone else.

    Why this works

    The Ralph Wiggum approach only works for a specific kind of task: small fixes where the solution is obvious and the only blocker is motivation. You wouldn't use this for a new feature or an architectural decision. But for the backlog of "I know exactly what's wrong and I just haven't done it" — it creates momentum.

    There's something about numbering them as stories. STORY-001 done. STORY-002 done. By the fourth one you're in a flow state and the rest feel inevitable.

    The constraint matters: each story has to be one commit. If it can't be one commit, it's a real task, not a Ralph.

    I'd been looking at these seven issues for weeks. Any one of them would've been quick to fix. But as a list of seven things, they felt like work. Numbering the stories and committing to "just blast through them" turned procrastination debt into actual shipping.

  • I built a second brain out of my Twitter bookmarks

    I had over 500 Twitter bookmarks. Saved with the best of intentions. Opened approximately never.

    You know the pattern. See something interesting, hit bookmark, feel like you did something. Three months later you need that one thread about agentic UI patterns and you're scrolling through a graveyard of "I'll get to this later" content.

    What I built

    A local database that stores everything. A sync pipeline that pulls from Twitter's API. An AI categorizer that reads each bookmark and sorts it into categories I defined — things like "AI Agents," "Design," "Tools," plus private buckets for politics, personal stuff, and anything I wouldn't want on my public site.

    The categorizer can use whatever AI model I have available — a local one running on my machine, or a cloud API for better results. The local model is slower but free, which matters when you're processing hundreds of bookmarks.

    There's a public page on my portfolio that shows just the stuff I've marked as shareable. Search, category filters, the works.

    The honest parts

    Twitter's API is hostile to small developers. The free tier is extremely limited. I had to build rate limiting just to avoid burning through my quota in one sync.

    The AI categorization is good but not perfect. It guesses wrong maybe fifteen percent of the time. Usually it's close — putting a design tool under "Tools" instead of "Design" — but sometimes it makes bizarre choices. I'm still tweaking the category descriptions to give the model better signal.

    The public page is still a work in progress. It doesn't always show up reliably on the site, which kind of defeats the purpose. The backend works — the frontend needs attention.

    What I'd do differently

    I'd start with fewer categories. Fifteen is too many. The AI spreads things too thin, and some categories only have two or three entries.

    But the core loop works. Save, categorize, decide what's worth sharing. My bookmarks actually mean something now instead of being a list I never open.

  • Just push it

    My git history for this portfolio includes commits called "yolo pushes," "wtf," and just "git push!" with an exclamation point like I was surprised it worked. There's a five-month gap between the first session and the second one. The early code is embarrassing.

    The site is live anyway. That's the whole point.

    I spent years on personal projects that never shipped. Not because they weren't good enough — because I kept deciding they weren't good enough yet. One more feature. Better animations. Cleaner code. Then I'd lose interest and start something new, and the cycle would repeat.

    This portfolio shipped ugly. Placeholder content, broken links, a shop page with fake products, copy I wrote at 2am that didn't make sense the next morning. I pushed it all. And then a funny thing happened — once it was out there, I could actually see what mattered. Not the "I should fix this someday" feeling. The "someone could click this right now and it's broken" feeling. That urgency is worth more than any amount of planning.

    Every improvement I've made since came from the site being live. You can't iterate on something that doesn't exist yet.