Tarotoro – A card app

I made an app for showing off my collection of tarot decks to my friends.

New URL!

The links to the app discussed in this post used to point to tarotoro.cards. That link still works, but after being informed that certain internet service providers (like Telenor) will blanket block all sites on .cards domains, I switched the main address to tarotoro.art.

Screenshot

Prelude

I work as a technical writer at Sanity, documenting a fairly beefy platform for dealing with structured content. It’s all very geeky, but a core concept is that you can make some pretty cool stuff happen just by being clever about modelling and treating content as data. Sanity isn’t a CMS (Content Management System) but it has a CMS, which is called Sanity Studio.

Since my job is to explain this stuff, I really do need to understand it myself, so faffing about with a number of hobby projects is just part of the job. One of my forever projects, or bikesheds, in nerd parlance, is a tarot studio.

A custom dashboard for my tarot studio (v5.5.0)

A custom dashboard for my tarot studio (v5.5.0)

The joy of hex

The Tarot, for those not conversant in witchcraft, is a set of 78 playing cards used in fortune-telling and for other esoteric purposes. It's also a pretty interesting dataset for structured content!

Each card has a number of fixed properties (number, suit, elemental affinity, etc.), but also endless artistic interpretations. I will never have more than 78 card documents, but there can be unlimited cardArt documents connected to each. And you can organize cardArts together in a deck which is made by one or more persons, and so forth.

Eight different tarot cards for The Lovers, arranged in two rows of four.
Different artistic interpretations of the tarot card The Lovers

One thing led to another, and I now collect tarot decks. I’m pretty sure there’s a law that says every male of a certain age is compelled to collect something. Each deck is a collection of 78 works of art interpreting a common set of archetypes, which is pretty neat, whether you believe in magic or not.

A flat lay of several tarot card decks and books on a wooden surface, including "The Fool" card.

As it behooves a proper bikeshed project, my tarot studio is tricked out with ALL the cool stuff. No sense in moderation when it’s quite literally part of my job to explore every nook and cranny of the platform, after all. More is more!

Card - The base type. Contains no images, but is referred to by Card Art.
Card Art – Connected to Card and Deck
Studio Dashboard
Prose type – Text interpretations connected to Cards
Content graph view – Left appendix is daughter's in progress deck with two cardArts so far
Card - The base type. Contains no images, but is referred to by Card Art.(1/5)

Spread the joy – Tarotoro

That’s how I came to sit on an ever-expanding digital hoard of neatly filed tarot artwork. Another key aspect to the tarot isn’t as easily explored in a CMS, even if it does happen to be a pretty slick one of those. (What? I’ve declared my bias!)

Namely the much more tactile and spacially oriented relations between the subset of cards you draw in any one reading, or “spread”. How you lay out the cards, and which order you open them and so forth.

These can be as simple as a three-card spread: Just three cards in a line representing past, present and future, or … they can get complicated. Like the Celtic Cross.

Carousel image
Carousel image

Thus, the idea of a tarot whiteboard app was conceived.

Missing art?

Wonder why you’re seeing artwork in this blog post that you can’t find in the app? I've contacted the artists behind all the decks in my collection asking permission to feature their work. So far one has said yes — Sam Rook, who generously gave blanket permission for all SIX(!) of her decks and even supplied graphics for the ones I don't yet own. Thanks for being awesome, Sam! Other decks will be made available as artists give consent.

The first opportunity to explore this idea came as I was tasked with documenting Sanity’s new SDK. An SDK, or Software Development Kit, is a way for developers to create fully custom applications on top of the Sanity platform. Perfect!

During the weeks I spent learning and documenting the SDK, I created the first prototype by piggybacking on the excellent tldraw whiteboard app, which sports a pretty robust API (Application Programming Interface) for customization.

Six diverse tarot and oracle cards displayed horizontally on a black background in a browser.
Tarotoro v0.1 – Implemented in tldraw

It became clear that I needed something a little more specialized to my particular use case. I wanted my app to follow the logic of a deck of cards, rather than just a generic whiteboard. Also, applications built with the Sanity SDK are, by design, only available to members of the relevant project. Fun for me, but no one else.

So, I started from scratch, helped by some very useful libraries for selecting, moving, scaling, and rotating elements, and, admittedly, Claude Code.

Contextual info panel
Multi-select supported!
Deck selector
Deal face down to keep suspense up
Loads of options for positioning and scaling in the right-click menu
Switch between searching cards left in deck, or card present on canvas
The Fool's Journey – All 78 cards laid out in order
Contextual info panel(1/7)

Over the 2025 Christmas break, I managed to get most of the basic functionality in place. Initially, I had a “file system” based on saving the state of the canvas to local storage (where your browser keeps settings for different websites and stuff like that), but I figured out that I could comfortably fit the whole state of the app into the URL itself using a compression algorithm that is older than I am (Noteworthy after you reach a certain age.)

Here’s a real short one with just a single card as an example:

https://tarotoro.art/#AwLgbAjANBFlB2AzFATADgJxQCyYVALTYrBA

That’s enough for the app to determine the card, deck, position, scale, and rotation + zoom and pan values for the canvas itself. So, at the cost of making my URLs look fugly, I completely circumvented any concerns of storing and recalling app state. That’s a win!

The URL updates on every change in the app, so to share your spread, you simply copy what’s in your browser’s address bar. Here’s one that has all 78 cards on the canvas, positioned, scaled, and rotated:

1http://tarotoro.art/#AwLgrA7ANGCMUBYCcVbAEyogZisPeAPgGy6zH5j5ryw4HzAnzoSXXC336ZNjFRsADnapOWXPkmEwYRElE0JBBEQpQKi4NW4w1mCGhgdMdSRqJhcQ9Fp3noTBNCTY7y-EMso0Cd2YIUJghoWFgqYygkH10jJlgvCPRsMm0PVEYZL3IeFKjs2N5CVVZc3Gj02GkEL2EysS5zWFU+VWR6ioDqOSZiaE0oZPKYpoFeuUN6tHsGRxJVGw6Rhi9egVclyqDCOjE-Qbzp9Ns1bOaUZLkjrsHM3AiEcjEZniKIARzEJ+vdZKIITClL7rZY8Fo7AR1YFRUGDHo7TDtaE-czoMbFAQDR4fcQ3VhEBAGIzY57HVaELyLZG437bNxRekkpQ3el8UzAfYkzq6bB3VRhB7fNIsopo1Bo-BM4U86TCVDYNjUxoEbDg9CmGqSp7c8zYeGiMCdaW69H0T6Gnw03VzYgXRUW0ks8lVQQiGBGl6CbYoJEOlEqfBOXADP1WlR3FCTd2Wz2EyxQKmh2PSfEbaMw9IIcHIPaUD2Z+G8jIRUPKyXov6wCXp-2SuZ6+X2-M3GpEWA+TU1sOS7aYCIQGwZm4RYJXdQD9llmCZQyDRUToe6MBFcKu-ALnUEKxt+BIhe1mDZuQDffGrfwx5QKOnqf8f4Jk6nz2QIjoFBpjewsDkuC5q+Dg9DSIQ5wnXADuw0QNCHQK5qxvdJiDuUIFTAzBN3wYhRVoTt4JuUg20iJBiDkJACnMYhwQgfl1CIq4zww+FFSBWjF3I9FmjXKJiMdXQ+jbHt8BYtBTF48ks0gwTuIPW0CXXIwhPoq8oIEKkFM9WcmHQLw0zU9IAUsDh9l0m5uEIbBTFAri6PUtV+WrYzdAgQsPhQqyGj0itqF5FSnPyVA+IAWlUEI8AAAWAAA6fSqx9IQgA

It’s a chonker! But at 950 characters, it’s well within the max length browsers will accept for a URL, which is commonly agreed to be about 2000 characters. You’ll never have more than 78 cards to keep track of, because the app mimics a real deck. Meaning there’s one copy of each card, and when you remove one from the canvas, it becomes available in the deck again. The early prototype would let you pick a different deck artwork for each individual card, but I decided against that.

So if the URL for ALL the cards is only 950 characters, I figured: Why not let people add a personal note when sharing a spread? We still have over 1000 characters left, after all. And, while we’re at it, let’s make it markdown, so we can support ASCII art and links and stuff.

Carousel image
Carousel image

Another URL trick I came up with is that adding an asterisk to the end of the address draws random cards while preserving the positions and scaling from the state string. Instant templates!

Also, since the URL updates every time you make a change, that means we get undo/redo functionality out of the box through the browser API. Back is undo, forward is redo. Which made it a trivial matter to hook up (shift+)ctrl/cmd-z to move backward and forward.

And there’s a phone version. Ish.

Look. Some websites are desktop websites, and that’s OK. This is one of them. Yes, it works on phones, because everything should, of course, work on phones, but I will not pretend that’s where I’m spending the majority of my time and effort.

It works, and I’ll keep it working, but the desktop experience is probably your best bet. It’s a personal project, so I’m allowed.

A black iPhone 17 displays a web page with three ornate tarot cards: Justice, Eight of Swords, and Death. The browser address bar shows 'tarotoro.cards'.