Selected work

Manual processes, turned into systems.

A selection of projects from 20 years of production work at XBOX and Microsoft, plus what I'm building for myself. Focused on approach and outcomes (sorry, no proprietary screenshots).

3 languages
became
30 languages

Localization Pipeline Rebuild

XBOX localization was fragmented across surfaces, each with its own CMS and its own rules. I built tooling that generates localized content per surface from its own source, cutting production turnaround from 30 minutes to 3.

The XBOX app for PC Store tab: featured sale banners, a Game Pass promotion, and rows of game tiles
The XBOX app for PC. Every campaign placement ships in 30 languages and 122 locale variants through this pipeline.
Problem, approach, result

The problem

XBOX localization was fragmented across surfaces and systems. One surface in the XBOX app covered just 3 languages with no fallback; another already ran 30 with fallbacks, but on a different CMS. On the console there were fewer languages and variants, but strict character-width limits. Every surface had its own rules and leaned on manual copy-and-paste, and complex multi-market sales (different messaging per market) made all of it harder.

The approach

So I built tooling to pull it together: not one tool but several, refined over time. They generate localized content for each surface from its own source, add worldwide templates and fallbacks where a surface lacks them, and honor each surface's constraints: language coverage on one, character-width limits on another. Rather than start from scratch, I wrapped existing but unadopted tools in a UI and iterated until the whole process took minutes.

The result

The tools turned a fragmented, multi-CMS process into a consistent, largely automated one and cut manual effort on every surface. The most limited surface jumped from 3 languages to 30 and gained fallbacks it never had; the hardest multi-market sale updates dropped from 30 minutes to 3. And because content is generated from each surface's source of truth, an AI review step can verify the output against the origin (not a downstream copy) before it publishes.

reactive QA
became
caught at source

Copilot Localization Review Agent

Localization errors were surfacing after publish. A custom M365 Copilot agent now reviews localized content against the source at import, before it goes live.

Problem, approach, result

The problem

Localization errors (incorrect context, the wrong language shipped to a market, off-brand terminology) were being caught late in the production cycle, sometimes after content had already published to multiple surfaces. Each catch meant updates across several markets and a manual review sweep.

The approach

I built a custom M365 Copilot agent that reviews localized content against the source at the point of import, before it enters production. The agent applies rules for grammar, style, sales terms, and brand terminology, then flags issues with enough context for the producer to fix them immediately or route them to the localization team for review. That gave us something we'd never had: a way to catch errors in languages the producer can't read, and a feedback loop back to the loc team.

The result

The review step that previously required manual spot-checking is now automated. Errors that used to propagate across multiple markets are caught and corrected before they leave the producer's hands.

siloed
became
shared practice

AI Explorers

AI experiments were happening in isolation across teams. I designed and run a cross-team session where practitioners teach each other and share best practices.

Problem, approach, result

The problem

AI tools were being adopted unevenly across the team. Enthusiasts had built sophisticated workflows; others weren't sure where to start. There was no shared language, no knowledge base, and no structured way to transfer what was working. The result was a growing gap between people who were leveraging AI and people who weren't, and no path to close it.

The approach

I started small, pulled together a few people already experimenting with AI, and turned it into a recurring cross-team session where anyone could bring a question and learn from everyone else. Not training I ran top-down; a room where the people doing the work teach each other. I own the agenda, topic curation (Copilot agents, Power Automate, Copilot Studio, homegrown tooling), and facilitation. The value comes from the group.

The result

It became where our AI practice actually spread, person to person. A few people reached out afterward to thank me for setting it up and accelerating their learning. One of the best learnings for me personally was personal knowledge management: I'd just set up my own second brain at home, and hearing how others implemented theirs into their Microsoft work changed how I work.

manual checks
became
alerts in Teams

Real-Time Teams Alerts from ADO

Time-sensitive campaign changes landed as a tag on a work item requiring an impossible level of attention to queries and email. Alerts now arrive in Teams, and only when action is still needed.

Problem, approach, result

The problem

A time-sensitive campaign change would land as a tag on an Azure DevOps work item and be dropped into email. As ADO notifications were easy to miss, and changes accumulated quickly in email, producers and PMs frequently checked both their inbox and a saved ADO query several times a day. Some changes needed action within the hour, which made a missed check on a busy day a real risk.

The approach

I built an ADO tag → Teams message flow in Power Automate, using M365 Copilot to troubleshoot and refine it. When the target tag appears on a work item, the flow checks an Excel tracker to confirm the work isn't already handled, then sends a direct Teams alert to the responsible producers and PMs, but only when action is still needed, reducing misses and stress for everyone.

The result

The team stopped leaning on memory, repeated query checks, and fragmented email to catch time-sensitive work. The alert now lands in the place they're already working, and only when something genuinely needs doing.

a stale doc
became
a self-updating plan

A Self-Updating Project Plan in Copilot Cowork

My editorial calendar was a color-coded Excel sheet: nice-looking, but hard to use as a plan. A Copilot Cowork agent now turns it into a real project plan and keeps it current on its own.

Problem, approach, result

The problem

My editorial calendar lived in Excel: color-coded and formatted as a calendar for people to read at a glance. Useful for sharing, but difficult for production planning. Turning it into an actual project plan meant reading it by hand, and it kept changing, so the plan was always in flux. I also wanted something a non-developer could run to create a plan: an alternative to VS Code and Copilot for teammates who don't live in a code editor.

The approach

When I heard about Copilot Cowork, I gravitated toward it immediately for non-dev work. The agent connects to SharePoint, runs on a schedule, and transforms the colorful editorial calendar into a structured Excel project plan, then watches for changes and folds them back in on its own. Each morning it sends me a Teams ping with what the day actually needs. No code editor required, which was the point. I shared it with the AI Explorers team as something a PM could pick up and use.

The result

It turned an ongoing manual chore into something that runs on schedule, but as with many AI solutions, not perfectly. While it became one of my favorite uses of agentic AI outside of coding (it's practical, genuinely easy to build, and invaluable to how I plan my work) I continue to refine prompts and wait for improvements to the offering.

locale by locale
became
all at a glance

XBOX Ad Preview Tool

Producers checked ad copy against character limits one language at a time. A browser tool now renders every supported language at once, near pixel-perfect.

Problem, approach, result

The problem

XBOX console ad campaign producers checked character limits language by language: manually opening each locale, reading the copy, and hoping nothing exceeded the display constraints. With dozens of languages, this was slow and error-prone. Copy that looked fine in English sometimes blew out in German or Japanese, and those catches often came too late.

The approach

I built a browser-based preview tool that renders the actual ad layout for every supported language simultaneously, using real display dimensions and character constraints. It's near pixel-perfect: what the producer sees in the tool is what ships. The goal was to make the review process a single glance rather than a multi-step iteration.

The result

Character limit overruns are caught immediately. The review process that required iterating through each locale now happens in one view. Producers can make copy decisions with confidence that what they see is what will appear across all markets.

no search
became
one-command reports

A Command-Line Toolkit for a CMS With Limited Search

The XBOX Support CMS couldn't scrub its own content well. I built roughly twenty command-line tools so anyone on the team could audit the global estate without Visual Studio.

Problem, approach, result

The problem

The XBOX Support CMS couldn't search across the full content estate. You could export XML, but answering a broad question (where does something appear, what's broken, what changed) meant manual investigation or one-off work in Visual Studio. Visibility across worldwide content was poor, and routine audits were harder than they had any right to be.

The approach

I used AI-assisted development to build PowerShell tools that parsed the CMS XML exports, then grew them into a suite of roughly twenty C# command-line apps: automated exports, regex and flexible search, CSV and Excel reporting. I packaged them as simple .exe files so teammates didn't need Visual Studio or any scripting knowledge: global content dashboards, broken-link audits, and configuration reporting, all self-serve.

The result

An expert-only, largely manual workflow became a repeatable command-line capability anyone on the team could run. It gave the team real visibility into the global content estate and turned recurring audits into standardized, self-serve reports.

tab triage
became
one ranked list

Personal Job Board

Personal build · Python · local LLM · 2026

A serious job search means watching six sources daily and reading fifty postings to find three that match my interests. I built a pipeline that collects, dedupes, and scores every posting with a local LLM against eight weighted axes.

Problem, approach, result

The problem

I'm trying to simplify how I look for jobs by creating a tool just for myself. I want to watch six-plus sources (government portals, company boards on Greenhouse, USAJobs, aggregators) every day. The same posting appears on three of them under slightly different titles. And "is this worth applying to?" is a judgment call across many dimensions at once: how central each of my skills is to the role, where it sits, whether it quietly wants a hands-on engineer instead of an orchestrator. Reading fifty postings to find three good ones is exactly the kind of manual process suited to an LLM and for what I need.

The approach

So I built the tool I wanted: a Python pipeline that collects from all six sources, dedupes across them (same company + title + city, keeping the richest record), then scores every posting with a local LLM against eight weighted "centrality" axes, plus a location gate and disqualifier factors that encode what I'm not (hands-on IC engineering ×0.35, visual design ×0.5). One axis is Automation Opportunity: a role drowning in manual process scores high, because that's a primary interest of mine. Scores are cached, so a morning run only evaluates what's new. I designed the pipeline and the scoring model; AI wrote most of the implementation under my direction, which is rather the point. Probably obvious, but this is one of my favorite uses of AI: make your own tools! A companion tool compares any posting against my résumé and reports the gaps.

The result

One command each morning produces a ranked, self-contained dashboard: per-axis score meters, sort by any axis, location and source filters. I read the top of a ranked list instead of triaging browser tabs. My fit judgment lives in a config file instead of my head, so tuning it is an edit, not a habit. And because the scoring model runs on a local LLM, the whole thing costs nothing per run and no job data leaves my machine.

The job board dashboard: a ranked list of job cards, each with a fit score, per-axis score meters, salary, and location, under a header showing 516 listings from five sources with min-fit, sort, and filter controls
One morning's run: 516 listings collected, deduped, and ranked; per-axis meters, min-fit slider, sort by any axis. Runs locally, just for me; not a product.

Open to work

Got a manual process worth automating?