Blog

  • Building a competitive landscape takes two weeks. It shouldn’t.

    Someone on the strategy team asks for a competitive landscape in a new therapeutic area. "Just the key players, where they are in development, and how they compare."

    Just.

    What "just" actually looks like

    You start in ClinicalTrials.gov. Pull every trial for the condition. Cross-reference with vendor databases — Citeline, Evaluate Pharma, Cortellis. Figure out who owns each asset, what phase they're actually in, and whether they're relevant to the indication you care about.

    The data cleaning part is straightforward. Tedious, but straightforward. You can get a decent Excel sheet together in a few days.

    Then it gets painful.

    The slide

    The landscape needs to be a PowerPoint slide. Arranged by development phase. Each drug is a textbox. You're placing them on a grid, color-coding by MOA, adjusting because twenty drugs don't fit the way ten did.

    You realize you missed one. Add it. The layout breaks. Reformat. Someone mentions a drug you hadn't included. Add it. Reformat again.

    This is where the time actually goes. Not in the data — in the visualization. Getting fifty drugs onto a single slide in a way that's readable and tells a story. Every change to the underlying data means moving textboxes around on a PowerPoint.

    The "so what"

    Leadership doesn't care about the grid. They care about what it means. Where are the white spaces? What does the competitive picture mean for our strategy?

    That narrative — the actual intelligence — takes maybe a day to write. But you can't write it until the data is clean and the visualization makes sense. So the strategic thinking, which is the whole point, gets whatever time is left after two weeks of data work and slide formatting.

    The shelf life

    A landscape starts going stale the day you finish it. A trial readout or an FDA action can change the picture overnight. Three months later, the landscape is a historical artifact.

    So you either rebuild from scratch or you try to maintain it. Maintaining means going back through the same sources, checking what changed, updating the Excel, and — this is the part that kills you — moving the textboxes again.

    The gap

    The vendor platforms are excellent databases. I've used all of them. What they don't do is build the landscape for you. You still export to Excel. You still build the PowerPoint. The data is better organized, but the workflow is the same.

    The gap isn't data availability. Public sources contain almost everything you need. The gap is everything between raw data and a finished landscape — verification, building the slide, keeping it updated. All manual work, and it's where most of the time goes.

    The hardest part isn't building the first landscape. It's keeping it alive. A landscape that can't update itself is just a more expensive version of the slide it replaced.

  • 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.

  • Teaching an AI to research stocks and poke holes in my ideas

    I had a trade idea. To evaluate it properly I needed: current price action, historical bars for technicals, macro context, and whether the company filed anything interesting with the SEC recently. Four different sources. Four different formats.

    That's a lot of context switching for one question: "Is this idea actually any good?"

    The research agent

    Give it a ticker, it goes to work. It pulls market data, computes technicals, fetches filings, and puts it all into a structured report. Technicals, fundamentals, recent filings, preliminary thesis assessment.

    No single piece of the output is amazing on its own. The technical analysis mostly tells me what I can already see on the chart. The value is seeing everything in one place. Instead of switching between six tabs and trying to hold the full picture in my head, I get a structured starting point.

    Is it as good as a professional analyst's report? No. Is it better than what I was doing before, which was "glance at a chart and go with my gut"? By a lot.

    The thesis interviewer

    This might be my favorite thing I've built. Almost didn't build it because it sounded gimmicky.

    You describe a trade idea and it asks hard questions. What's your exit plan? What if the catalyst doesn't materialize? How much are you willing to lose?

    It surfaces things I hadn't considered. Not because the AI is smarter. It's just methodical in ways that humans, especially humans excited about a trade idea, aren't. It asks the obvious questions you forgot to ask yourself because you were busy being convinced you were right.

    I haven't had a dramatic "gotcha" moment where it saved me from a terrible trade. It's more subtle than that. It forces me to articulate my reasoning, and sometimes the act of articulating it reveals how thin it is.

    The workflow

    The two tools together create a loop: start with an idea, run the research agent to build context, then run the thesis interviewer to stress-test the idea against that context. What comes out the other end isn't a recommendation. It's a clearer picture of whether the idea is worth acting on.

    Some ideas don't survive the process. That's the point.

    What I've learned about AI in trading

    If I've learned anything, it's that AI is best at synthesis and worst at judgment. Give it five sources about a company and ask for themes, and the results are solid. Ask "should I take this trade?" and it can't answer that. It doesn't know my risk tolerance or portfolio context.

    As a devil's advocate it's surprisingly effective, because it doesn't care about being right. It just pokes at your reasoning until it finds weak spots. Humans get attached to ideas. AI doesn't.

  • What a PhD taught me about building things

    I did a PhD in clinical experimental therapeutics and an MBA at the same time. Terrible idea. Would not recommend it to anyone.

    The PhD was not a good experience. I'm not going to romanticize it. Five years of grinding through a program that didn't work for me. I didn't come out the other side with a clean set of transferable skills and a love of the scientific method. I came out tired and wondering what I wanted to do next.

    What the MBA actually gave me

    Most of what they teach in business school, the frameworks, case studies, strategy models, I could take or leave. But there was one class that genuinely changed how I think.

    A venture feasibility course. One professor. He taught me how to evaluate whether an idea was worth pursuing before sinking time into it. How to think about whether something is viable. Not abstract. Practical. "Is this real or are you fooling yourself."

    That class shifted something. Before it, I thought of myself as a researcher. Someone who studies things. After it, I started thinking like someone who could build things. The entrepreneurial mindset didn't come from the PhD. It came from that one class and the gut instinct I developed through the MBA experience.

    The gap

    Wanting to build things and being able to build things are different. I had ideas. I understood problems. I could think through whether something was viable. But I couldn't code. I'd tried learning. Tutorials, toy projects. Nothing stuck.

    For years I was stuck in that gap. Enough business instinct to know what to build. Not enough technical skill to build it.

    AI closed the gap

    Then vibe coding happened, and the gap closed.

    I can describe what I want and ship something real. I'm building a trading platform and a competitive intelligence tool. I'm running an automated e-commerce experiment. A year ago these were ideas in a notebook.

    The PhD didn't teach me to build. The MBA, or at least one professor in it, gave me the instinct for what's worth building. And vibe coding finally made the building part possible. The path from researcher to builder is messier than any clean narrative. But I got here.

  • Why I’m building my own trading platform

    I wanted to learn Python. Tried tutorials, toy projects, the usual. Nothing stuck. I could follow along but I couldn't build anything real on my own.

    Then vibe coding happened.

    I trade on the side. Swing trades, some options, mostly based on technical signals and fundamental research that I piece together manually. The trading itself isn't the problem. The process around it is. I have a full-time job. I can't spend three hours every evening on research. But I'm trading real money, and "glance at a chart and go with my gut" isn't a system. It's a habit I haven't replaced yet.

    I'd always wanted to build a trading platform. Something that forces me to learn async programming, API integrations, all of it. I just couldn't get past the gap between "I understand the tutorial" and "I can build the thing." AI-assisted coding closed that gap. I can describe what I want, iterate on the output, and ship something real. I'm learning more about Python from building with AI than I ever did from courses.

    What I actually want

    I don't want a Bloomberg terminal or a hedge fund quant stack. I don't want a bot that trades while I sleep.

    I want a single place where I can see what's happening with the stocks I care about, test ideas against history, and track my trades honestly. Right now I don't track trades in any structured way. No journal. No system for reviewing what worked. That's a problem when you're trading real money and trying to improve.

    The honest part

    I still don't fully understand every line of code in this project. But I understand what it does, why it's structured the way it is, and how to change it. Every feature I build teaches me something. Last week it was async programming. This week it's state management. Some days it feels like building a car while learning to drive.

    But the act of building, translating a vague idea into working software, I can't stop doing that. Vibe coding didn't replace learning. It gave me a way in.

    This is going to be a series. I'll share what I'm building and what I'm learning. Eventually, the actual investment theses that come out of it.

  • 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.

  • Competitive intelligence is broken and I can prove it with my inbox

    CI analysts spend 80% of their time on data work and 20% on the strategic thinking that actually influences decisions. The ratio is wrong.

    The strategic work is what CI is supposed to be. Anticipating competitive moves, synthesizing across programs, surfacing insights that change how leadership thinks about a market. That's the part that matters. And it gets whatever time the noise leaves behind.

    The noise

    Google Alerts, ClinicalTrials.gov updates, SEC filing notifications, RSS feeds, PubMed digests, industry newsletters, stakeholder asks. Hundreds of items a week across a dozen sources. Most of it is noise. Re-syndicated press releases, routine filings, publications that mention a competitor in passing.

    Buried in that noise, occasionally, is something that actually matters. A data point that changes the competitive picture.

    The problem is you can't tell which is which without processing all of it.

    Signal has a half-life

    Intelligence that surfaces Monday morning changes a strategy conversation. The same intelligence buried in Thursday's alert batch is already stale.

    Every source delivers at its own pace. Google Alerts batch overnight. ClinicalTrials.gov updates whenever records change. Newsletters arrive weekly. SEC filings post on EDGAR's schedule. None of them know what you're watching for or how urgent any given update is. They just dump everything into the same stream.

    When CI works, it's genuinely valuable. You catch something early, connect it to what you already know, surface it before a decision gets made. But that only happens if the signal arrives in time. Right now nothing in the workflow respects that.

    Why better filters won't fix it

    "Build better filters" is the obvious fix. But relevance in CI is contextual. The same event is critical or meaningless depending on what else is happening.

    An 8-K filing could be a material event or a routine auditor change. A new publication could be novel data or a rehash. You can't filter by keyword or filing type. You need to know what's happening with that specific competitor, that specific program, at that specific moment to decide whether it matters.

    That requires combining every alert with everything you already know about the competitive landscape. Humans do that kind of synthesis well. They can't sustain it at volume, week after week.

    So you start skimming. And the thing you skim past might be the signal.

    The patchwork

    There's no single system that holds the full competitive picture. Vendor platforms for pipeline data. Spreadsheets for what the vendor doesn't cover. Slide decks for the landscapes leadership reads. A dozen browser tabs for the sources you check manually.

    Every CI analyst I know has some version of this patchwork. The tools vary. The fragmentation doesn't. Nothing connects.

    The tools are good at storing facts. They're bad at surfacing what those facts mean in context.

    The ratio

    80% data work. 20% strategic thinking. The thinking is the part that influences decisions, and it gets squeezed into whatever's left after triage, tracker updates, landscape rebuilds, and source switching.

    I want to flip that ratio. That's what I'm building toward.

  • 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.