Skip to main content

Global Variables

Charting New Territory

Today I’m publishing the 1.0 release of my first Eleventy plugin, Uncharted. It’s a plugin for creating charts on the static site generator I use for my blog and a number of other websites. It takes data from CSV files, JSON in the data directory, or the YAML frontmatter for the post or page. It generates static HTML and CSS to render a growing number of types of charts, with a limited amount of interactivity (i.e., hover effects and tooltips). Here’s an example:

Claude Code AdoptionAI-assisted development since May 2025
60300
MayJunJulAugSepOctNovDec
Pull RequestsCommits

Because they’re HTML + CSS instead of images, they can adapt and resize to fit the page and device they’re on, be responsive to light/dark mode, and be styled to match the website—and without running client-side Javascript.

The chart above is relevant to Uncharted for multiple reasons. The genesis of the project was a two-page Wrapped-style website I put together for work to document what I did last year, based primarily on GitHub data. Since the C-Suite is very interested in any applications of AI within the company, I also added some numbers and the above chart to demonstrate my adoption of Claude Code, which by the end of the year had become a key part of my development workflow.

I developed that website itself with Claude Code, first as just a couple of HTML files and a stylesheet. Then I had the idea to rebuild it in Eleventy, which would also make adding pages a lot easier next year and beyond. I’d thought about trying to develop some sort of charts plugin for Eleventy in the past; once I’d gone through implementing a bunch of CSS-based charts with Claude for this, it was just a matter of asking Claude to use those charts as the basis of a new plugin and then migrate the site over.

Once I had a 0.1, my next use case (and the one I’d had in mind before the Wrapped project) was to move my Tidy Tuesday site to Eleventy. I was increasingly unsatisfied with the framework I’d been using before—one that is specifically designed for BI (business intelligence—i.e., dashboards). I’d been very impressed with it when I first came to it, but my hangups over time were more to do with the stack. It was built on a different SSG, not Eleventy. I was constantly getting alerts for vulnerabilities in the dependencies, I kept having compatibility issues with different packages and the things I was trying to connect it to, and I had much less flexibility to customize the website.

Meanwhile, pretty much every new site I start now I do in Eleventy, and I really just wanted my Tidy Tuesday site to be on that same stack. So I worked with Claude Code to do just that. I started fresh with the first couple datasets in January, and have built out Uncharted as I’ve needed new chart types or other features for each week since.

At whatever point I added a Sankey diagram to the available chart types, I also went back and replaced the chart on a recent(ish) post here, which had just been a screenshot from my old Tidy Tuesday site before.

While working on this I’ve had the privilege of interacting with Bob Monsour of 11tybundle fame. He used a prerelease version to work on a new Insights page, and while he was drafting that he opened a number of issues on the GitHub repo that we went back and forth on to debug. It was really helpful to get some external feedback during early development and very rewarding to see Uncharted in the wild so soon after I started the project.

The last few weeks I’ve been holding myself to no new features as I’ve been trying to get what I have all buttoned up and ready to release as a solid v1 with (hopefully) minimal bugs. It’s been basically done, just waiting on being tested to the point that I felt ready to release it—and on this post being written. Now that 1.0.0 is out, I can go back to adding new stuff again.

So if you happen to be a fellow soul with Eleventy under the hood of your website, go run

npm install eleventy-plugin-uncharted

Show me what you come up with.

Rachel Weeps

I picked up my phone this morning to see an email notification with the subject: “Security Alert: Worldwide Caution”—a message from the US State Department for citizens abroad. This was how I learned about the “launch of U.S. combat operations in Iran.” After reading the email, I opened up the news to see the headline about American and Israeli strikes on Iran and the (at that point unconfirmed) killing of the Ayatollah.

As my daughter picked out and put on church clothes across the room, I read about the 140+ (and counting) civilian casualties—including the girls’ elementary school where dozens of children had been killed, with bodies still being pulled out of the rubble. Parents had just dropped their little girls at school and headed off to work, with no idea they would be coming back to find rubble, bloodied backpacks, and tattered schoolbooks.[1] I turned away from my own little girl, who just started pre-K this year. I couldn’t hold back the tears.

I have let a lot of current events happen without adding my voice to the online cacophony, but I cannot let this go by in silence. Abel’s blood cries out from the ground; Rachel weeps for her children. The people of God have always been called to be a prophetic voice to those in power—especially on behalf of the vulnerable in the face of violence and oppression. I hope pulpits across the country spoke out against this monstrous slaughter of innocent life. But I can’t say I’m optimistic. Too many, I imagine, didn’t want to “get political”—or are already outspoken in their support of the current administration and everything it does.

But there is no excuse or justification that can make this right. So this school had the bad luck of being next to a major naval base. No strategic gain or victory is worth the cost of the blood of children. This is evil. This is hell on earth.

This is just the latest in a long and growing list of inhumane injustices and acts of violence by this White House against the vulnerable and particularly the foreigner. But civilian deaths in military operations abroad are not a sin unique to this presidency. Every administration in my lifetime has had innocent blood on its hands. This continues to be an acceptable price for both sides—which is why the Church must never get too cozy with any political party.


As I wrap this up my kids are playing in the street with another little Indian boy from the neighborhood, laughing, throwing balls, and riding little scooter-car things down the hill. Meanwhile dozens of families in Iran are still reeling from the loss of a child, or another loved one, in an unprovoked war that has senselessly and indiscriminately taken hundreds of civilian lives in just the opening salvo. The body count at this school alone is now 153.

My Iranian friend came to mind today. We went to the same international church for several years, both as expats. He was there for religious asylum and trying to get a visa to the West for university, while his parents were still back in Iran. It’s been a few years since we were last in touch, but with our countries now going to war, he came to mind and I wondered how he was doing. So I sent him a message. I haven’t heard back from him yet, but I hope his family is OK.

I cannot imagine the grief and pain of those living through this, and only more grief is yet to come. In the oncoming firehose of news and battle lines, regime changes or scrambles for power, let us not forget the price paid by the normal people who just wanted to live their lives like the rest of us.


  1. The NYT piece with these links translated this man’s words as: “Under this rubble, students are buried. The blood of our loved ones, our students, which you can see on their schoolbooks.” ↩︎

Tuesdays and Travels

I started this draft at 5:30 in the morning on Monday, waiting to board a flight in Delhi. I’m picking it back up to (hopefully) publish it as I wait for another flight at Heathrow, after three days at a data conference in London. This was my second time at this particular conference, and the fourth year running I’ve gone to a data conference in London in the fall.

This year was the first time I had to request an ETA for entry into the UK—not an estimated time of arrival, but an electronic travel authorization. Some weeks ago I downloaded the UK ETA app and used it to submit a scan of my passport, a scan of my face, and other information. I got the approval in my inbox almost immediately, but it was an extra step where in the past I’d been able to just land in the UK, walk through their automated gates with my passport, and be in. My arrival this year was the same experience, but only because the ETA on my passport was already in their system for this next year.

Why am I writing about data and passports? Well, fittingly, I just did some recreational data visualization on the topic as part of TidyTuesday, a weekly data project I’ve started participating in the last month or so. The one from a couple weeks ago was on the Henley Passport Index, which measures the strength of passports based on visa-free access to other countries. The contributor of this dataset was inspired by an article about the strength of US passports declining. The US passport is still #10 on the rankings, but that’s down from #1 in 2014. So that news is pretty relevant to me, one of a generation of TCKs and now digital nomads who grew up thinking the world was our oyster—and a US passport-holder myself.

I could have done a visualization tracking the change in rankings over time as addressed in that article, but as I explored this dataset, I became more intrigued in looking at the data as a two-way street—essentially, how does access to a country for other nationalities correspond to the access granted to its nationals abroad? It took a few attempts to figure out how best to represent that, but I landed on what’s called a Sankey chart—typically used to represent flow. I set it up to show the breakdown of visa requirement categories as designated in the data—for entering a given country on the left side, and for passport holders entering others on the right. The page on my TidyTuesday site has an interactive version with a dropdown menu to pick the country.[1] Here’s the US:

Oyster QuotientVisa requirements to and from the United States
🛬 Visa Required → United States: 152🛬 Electronic Travel Authorization → United States: 42🛬 Visa-Free Access → United States: 4United States → 🛫 Visa-Free Access: 136United States → 🛫 Visa on Arrival: 36United States → 🛫 Visa Required: 24United States → 🛫 Online Visa: 20United States → 🛫 Electronic Travel Authorization: 10
🛬 Visa Required
🛬 Electronic Travel Authorization
🛬 Visa-Free Access
United States
🛫 Visa-Free Access
🛫 Visa on Arrival
🛫 Visa Required
🛫 Online Visa
🛫 Electronic Travel Authorization

So I can see myself in that little slice of US passport holders applying for ETAs in one of 10 countries. But this also clearly shows what I was already pretty sure I knew: that while a majority of countries (at least for now) allow US citizens to visit with no visa at all—a privilege that I’ve taken advantage of plenty—an even larger majority of nationalities are required to apply for a visa to enter the United States. The number allowed to arrive visa-free? Four.

I wonder how many Americans would even think twice about this imbalance. Or how many would defend it?

This also doesn’t account for the difficulty of attaining visas, where visas are required.[2]

Anyway, I’d been wanting to write about these TidyTuesday projects since I started working through them, and then this particular one hit pretty close to home for me. There are a few other datasets up there too—including last week where I tried to look at bread (or more technically wheat/flour) and rice across cuisines.

You may have noticed it says “Global Variables” at the top of the page now. I’ve been sitting on that name for a couple months. I was going to tie it to a redesigned site, but while I haven’t gotten around to the redesign, this felt like an appropriate first post under that masthead. Global variables are, of course, a programming term, with an appropriate double meaning for someone like me—someone who, as I mentioned, grew up in a world that seemed increasingly connected and closer together—where “globalization” was only considered a positive word, bringing with it a literal world of opportunities. That starry-eyed optimism is starting to show some cracks in the cold light of reality—as countries around the world seem to be pulling away from that glimmer of a more interconnected globe. Megan and I still choose this life for ourselves and for our kids. We want to give them the same global perspective we had the privilege of growing up with. It is increasingly important as so much of the world pendulum-swings in the other direction. I hope something of that world survives long enough for my kids to experience it and learn from it.


Update (Feb 2026): Replaced the chart screenshot with a chart using my Uncharted plugin, which also powers my new TidyTuesday site.


  1. I’ve since migrated to a new site, which doesn’t yet have interactive filtering. There I just posted a handful of countries to compare. ↩︎

  2. Like, say, an H-1B visa. Just to name a totally random example. ↩︎

New Horizons

I definitely didn’t plan this, but as I’m finally catching a few minutes to write, I find myself once again eleven days from an international move. I remember the final stretch feeling like a crunch last time, but seven years later, this is so much more overwhelming—because this time we’re moving a family of four, and trying to sell off and pack up a much larger place than half of the little apartment I shared back then. No matter how much progress we make, there always seems to be so much more left to do before we can move out of our apartment at the end of the month, and board a plane two days later.

I say “we”, but the vast majority of the work going into this move is being pushed forward by my incredible wife, with me playing a supporting role at best—trying to juggle keeping on top of my job, taking kids so that Megan can get focused time to work on this move, and somewhere in there handle the pieces of the move that can only come down to me. We’re both so tired.

But when I manage to get my head enough above water to see past all that, I am really excited for what’s next. For our next adventure. A fresh start. New horizons.

“New Horizons” has been my theme for 2025. We started this year knowing it was time to move this summer, though we didn’t know where. The first four or five months of the year were figuring that part out. We considered—and ultimately ruled out—a return to the US for a few years. Instead, it became clear to us that the right next step for our family was to move somewhere where Megan could pick up her career in international education again, and where our 4-year-old could start preschool—ideally at the same school. So Megan spent months submitting applications, interviewing, looking at openings from the Philippines to Italy to Uganda before—at about the eleventh hour—connecting with an international school in India that felt like a really good fit for her, for our daughter, and for our family. So with not much more than a month before we’d have to fly, we decided we were moving to India.

Needless to say, it has been a bit of a whirlwind since that decision. But when I actually stop and look past all the stuff filling my field of view, I’m excited for the future. I’m looking forward to being in South Asia again—though India itself will be new. Navigating a familiar but different-in-some-key-ways culture will be interesting. We managed to find a house already through some mutual contacts. We saw a video walkthrough last week and the place looks really great.

The other day I found myself reading that post from before that last big move, and what struck me was how bittersweet that move was. On some level, I was ready and eager to get back overseas, but I was also really sad to leave Blacksburg and my church there. This time, I’m mostly just ready for the new chapter. This season will always be meaningful. This is where I met my wife and we had our two kids. I’ll always look back on these memories fondly. The greatest loss will be having grandparents in the same city.

But this time, with much less internal conflict, it feels like time. We’re leaving the babies stage behind; we’re entering the school-aged era, and returning to both of us working. We’re moving to a part of the world that is meaningful to both of us and that we’re excited to share with our kids. We will be joining a community and environment that seems like it will be the restful, rejuvenating space we desperately need right now. Sitting here I’m looking at a lot that still needs to happen before wheels up in a week and a half, but I can’t wait to explore new horizons.

Unearthing My One Post From 2024

I just came across this draft from September, in which I not only wrote a post about some recreational coding/data analysis, but made a bunch of updates to my website to better handle code and tables. Instead of updating and publishing it with today’s date, I decided to pull a Gruber and backdate it to when it was basically done and just never published.[1]


  1. Of course, in my case, it’s not as if it’s getting buried under 11 years of prolific writing. It’s literally the post right below this one. ↩︎