One Command to Deploy Anything
I built QuickShare -- a Claude Code command that takes any HTML file and deploys it to Firebase Hosting with social-ready OG tags. Because if sharing is hard, you won't share.
Part 5 of the series: Building The Hub
I had a problem that shouldn’t have been a problem.
I was generating HTML reports — CourtSide basketball stats, scouting analyses, player breakdowns — and they looked great on my machine. But sharing them was a mess. Copy the file somewhere? Screenshot it? Paste the HTML into a message? None of these preserved the formatting, the interactivity, or the professional feel of the reports.
What I wanted was dead simple: take an HTML file, put it on a URL, make it look good when someone drops that URL in WhatsApp. One command. Done.
So I built QuickShare.
The Command
/quickshare [path-to-html-file]
That’s it. One command in Claude Code. Give it an HTML file, and it:
- Reads the HTML and identifies (or adds) Open Graph meta tags
- Generates a 1200x1200 social preview image optimized for WhatsApp
- Deploys to a Firebase Hosting preview channel
- Returns a shareable URL that unfurls beautifully in any chat app
The whole process takes about 30 seconds. At the end, I get a URL I can paste into the team WhatsApp group, and instead of a bare link, people see a rich preview with title, description, and an image.
Why OG Tags Matter More Than You Think
Open Graph tags are one of those web standards that most developers know about but rarely think about. You add og:title and og:image to your <head>, and social platforms use those to render link previews.
But here’s the thing: the preview IS the share. When I drop a CourtSide report link in a WhatsApp group with 20 basketball parents, the link preview is what determines whether anyone clicks it. A bare URL with no preview? Nobody clicks. A card with “Team vs Opponent — Scouting Report” and a branded preview image? Everyone clicks.
QuickShare handles the OG tags automatically. It ensures og:title, og:description, og:image, og:url, and og:site_name are all present and correct. If the HTML already has some of them, it respects those values. If they’re missing, it generates sensible defaults.
The Two-Pass Deploy Trick
Here’s where it gets technically interesting. OG tags need absolute URLs. The og:image tag can’t say /images/preview.png — it needs the full Firebase preview channel URL with the path. But you don’t know the Firebase preview channel URL until after you deploy.
The solution is a two-pass deploy:
Pass 1: Deploy the HTML with {{DEPLOY_URL}} placeholders in the OG tags. Firebase returns the preview channel URL.
Pass 2: Replace all {{DEPLOY_URL}} placeholders with the actual URL, then redeploy to the same channel.
It’s not elegant in an architectural sense, but it’s completely reliable and the user never sees the intermediate state. The whole thing is handled transparently by the command.

The .work/ Directory
QuickShare needed a place to stage files — copy the HTML, generate the preview image, set up the Firebase hosting config, and run the deploy. I didn’t want these temp files cluttering the repository or showing up in Obsidian (The Hub is an Obsidian vault).
So I created the .work/ directory convention: a git-ignored, Obsidian-hidden workspace for exactly this kind of transient tooling artifact. Build outputs, deploy staging, cache files — anything that needs to exist temporarily but shouldn’t be tracked or visible.
It sounds trivial, but having a designated place for “work in progress” files turned out to be one of those small decisions that reduced friction across multiple tools.
Lessons Learned the Hard Way
Building QuickShare taught me a few things about Firebase Hosting that aren’t obvious from the docs.
Use object format, not array format. Firebase hosting config supports both "hosting": { "site": "..." } and "hosting": [{ "site": "..." }]. The array format works for multi-site setups in firebase.json, but when deploying programmatically, it can cause a “site not detected” error. The object format just works.
Never delete your CWD. This one bit me hard. The deploy script creates a temp directory, does its work there, then cleans up with rm -rf. But if your shell’s current working directory IS that temp directory when you delete it, every subsequent command fails with a cryptic error. The fix is obvious in hindsight: always cd back to a stable directory before removing the temp folder. I now do this religiously.
Preview channels are ephemeral by default. Firebase preview channels expire after 7 days unless you specify otherwise. For CourtSide reports that parents might revisit, I needed to be aware of this. Not a problem for quick shares, but worth knowing if you expect the links to last.
First Deployment Day
The day I got QuickShare working, I deployed four CourtSide reports in a single session:
- Matt’s player report (scoring breakdown across all 8 periods)
- A teammate’s player report
- Joy’s star player analysis
- A full scouting report on an upcoming opponent
Four reports, four URLs, four WhatsApp messages. Each with branded preview images showing the player names, team colors, and key stats. The response from the parent group was immediate — “How did you make this?” and “Can you do one for [other player]?”
That’s the moment you know a tool is working. Not when it deploys successfully, but when people want more of what it produces.
The DX Philosophy
QuickShare is small. It’s a Claude Code command, some Firebase config, and a deployment script. But it embodies a principle I keep coming back to in all my tooling work:
If sharing is hard, you won’t share.
It doesn’t matter how good your reports are, how clean your data visualizations look, or how useful your analysis is. If the path from “I have this file on my machine” to “other people can see it” involves more than one step, you’ll find excuses not to do it. “I’ll share it later.” “It’s not quite ready.” “Let me just screenshot the important part.”
Remove the friction, and sharing becomes the default. One command, one URL, one paste into the group chat. That’s the bar.
The same philosophy applies to developer tools in general. The best internal tools aren’t the most powerful ones — they’re the ones with the lowest activation energy. If running a tool feels like deploying a space shuttle, nobody will use it. If it feels like pressing a button, everyone will.
QuickShare is my button.