SNCF Blog

A spreadsheet that is always September 3rd

September 3, 2026 · by Timur Tukaev

A quick bit of context for the meme this is built on. In Russia, every September 3rd the internet flips its calendar to a Mikhail Shufutinsky song, «Третье сентября» (“The Third of September”), whose chorus goes “I’ll flip the calendar.” It has become a nationwide, unkillable meme. So this year, instead of fighting it, I made it permanent in engineering: a public Google Sheet that can only ever be September 3rd.

Anyone on the internet can open it and edit it. Erase the face, recolor the cells, change the banner. A few seconds later it all snaps back. You cannot win. You will flip the calendar, and it will flip right back.

Under the joke is something I had wanted to build properly for a while: a canonical operator. Not a script inside the sheet, but an external controller that drags reality toward a desired state, exactly like an operator in Kubernetes. In the first article I wrote about Sheeternetes, an orchestrator whose control plane lives in a spreadsheet. This is the next logical step: the operator pattern applied to spreadsheets themselves.

The live sheet: banners, bonfires and a pixel portrait in cell backgrounds

First, a thank-you

The idea to build an actual operator for sheets (rather than yet another script) was not mine. Artem Goryachev suggested looking at sheet management through the operator pattern and adding federation. Thank you, Artem. It grew into a thing I am now unreasonably happy with. Here is what came out of it.

What “a self-healing sheet” means, and why it is an operator and not a script

The distinction is subtle but it is the whole point.

The naive version: attach an Apps Script onEdit trigger to the sheet that reverts changes. But that is not an operator. It is a defense from inside the managed resource, like a Kubernetes pod trying to heal itself. It breaks together with the resource, lives within its boundaries, and does not scale across many sheets.

A real operator is built differently. Three parts:

Desired state lives outside the managed resource, and the controller pulls the resource toward it. That is the definition of an operator, word for word. You can delete the managed sheet entirely, recolor it, wipe it, the controller does not care, it redraws it from the template. That is why this is “self-healing,” not “edit rollback.”

SheetsOperator: a control plane, a controller, a managed sheet

The whole reconcile is a single idempotent function: take the template, repaint the banners and the pixel image (via cell backgrounds) onto the sheet, and do it again every cycle. Repainting over the top is the drift correction. There is no need to figure out what changed, it is enough to bring it back to the reference.

The demo: a sheet that is always September 3rd

The managed sheet is public, anyone can edit it. Its desired state is:

Bonfires and rowan berries drawn out of cells

The portrait is not a cartoon, it is a downsample of a real photograph (taken, fittingly, on 2021-09-03). The grid is 138×192 cells, each cell 6 pixels, so three times the detail fits into the same overall footprint: you can make out the bald head, the blue sunglasses, the goatee, the pendant.

Now the best part. Here is the self-heal live: I opened the sheet, broke the banner and punched a white hole through the face, and the operator put it all back within seconds.

Break anything, the operator reverts it

This is not staged. I really defaced it through the API (changed the banner text to “EVERYTHING IS BROKEN” and filled the center of the face with white), and then the controller repainted the sheet from the template on its next pass. The banner came back, the face reassembled, the hole vanished. Public to read, it lives in the cloud and heals itself as long as a controller is running somewhere.

Touch it live (only while a controller is running):

Run your own, in one command

This is a template for sheets-operator. You need Docker, git, and a Google OAuth “authorized-user” JSON (with the spreadsheets and drive scopes). It contains a refresh_token, so the controller refreshes its own access and keeps working indefinitely. Keep the creds file private and never commit it.

git clone https://github.com/sncfoundation/sheets-operator && cd sheets-operator
git clone https://github.com/sncfoundation/demos            # templates (incl. sep3) live here
cp /path/to/google-oauth-authorized-user.json creds.json    # your creds; never commit

# create your own self-healing "September 3rd" sheet from the template, one command:
SHEETSOP_TEMPLATES=demos/sep3 SHEETSOP_CREDS=creds.json \
  python3 sheetsctl.py apply my-sep3 --template sep3

apply creates a new sheet, makes it public, registers it in the control plane, and reconciles it once. Then you want a controller to heal it continuously:

docker build -t sheets-operator:1 .
docker run -d --restart unless-stopped \
  -e SHEETSOP_CONTROL=<your-control-plane-id> -e SHEETSOP_TEMPLATES=/templates -e PYTHONUNBUFFERED=1 \
  -v $PWD/creds.json:/creds/creds.json:ro \
  -v $PWD/demos/sep3:/templates:ro \
  sheets-operator:1 run --interval 10

And verify:

docker ps                        # sheets-operator should be Up
docker logs -f sheets-operator   # expect: reconciled my-sep3 (sep3)

Now open your sheet, break something, and within a few seconds it reassembles.

Two easy traps:

An operator as a container scheduled by… a spreadsheet

Here is the nesting doll the whole thing was built for. The controller is just a container. So its canonical home is a Sheeternetes Deployment. Which means:

You end up with an operator scheduled by a spreadsheet that manages spreadsheets. The Deployment looks ordinary, just with a secret for the creds and an env var pointing at the control plane:

{ "name": "sheets-operator", "image": "sheets-operator:sep3", "replicas": 1,
  "cpu_req": 100, "mem_req": 128,
  "env": "SHEETSOP_CONTROL=<control-plane-id>",
  "secret_files": "gcreds:/creds/creds.json" }

The creds arrive as a Secret that the kubelet mounts into the container at runtime. They are never baked into the image and never end up in git. Execution, as always, stays on the node. The sheet is the control plane, never the executor.

And the final layer of absurdity: there is a third, cluster sheet where the whole Sheeternetes structure (Deployments/Nodes/Pods/Events/Images) lives as tabs, plus a Sheetfana dashboard. Open it read-only and you can watch the operator running as a pod, with its own image living in cells right next to it. A spreadsheet scheduling the operator that heals a spreadsheet. The recursion is left as an exercise for the reader.

A few findings

What this actually is, seriously

It is a joke about a Russian singer, sure. But it is also a working, compact example of what an operator is and how reconcile differs from “rolling back edits”:

That is exactly how real operators work in Kubernetes. It is just that here the managed resource is a public Google Sheet with a singer’s face, and anyone can verify the self-healing with their own hands.

How we put images (including the operator’s own image) into cells and boot a whole DOOM out of them is in the companion article.

Join in

All open source and alive. The community is international and English-speaking.

I’ll flip the calendar. It reconciles.

Companion piece: DOOM that lives inside a spreadsheet. Also on dev.to and Habr (RU). Join the community — Slack, Telegram, LinkedIn. ← Back to the blog