BUILD 18/30: Programatic Drawing of Word Counting Calendar Blocks

Posted Thursday, November 6, 2025 by Sri. Tagged JOURNAL

Today's progress on the 30 Day Build Challenge is using code to draw a "Pyramid Block" for the Word Counting Calendar! Getting closer!

About the Title Picture: Success! Drew a bunch of blocks in a pyramid shape using PDF-LIB!Screenshot of Visual Studio Code depicting source code that draws a pyramid of 10 blocks, stacked four rows high with debugging guidelines to verify alignment.Screenshot of Visual Studio Code depicting source code that draws a pyramid of 10 blocks, stacked four rows high with debugging guidelines to verify alignment. (full size image)

It has been a long day making small advances in my drawing code. Today's focus was to programmatically draw the pyramid block that's at the heart of the Word Counting Calendar:

Figure 1. A Pyramid Block. The green marks are dimensioning tools that I was using to check spacing between elements.A closeup of the Word Counting Calendar showing a pyramid of word count blocks. Green markup shows the spacing between each element proportionate to the 8x8 point square.A closeup of the Word Counting Calendar showing a pyramid of word count blocks. Green markup shows the spacing between each element proportionate to the 8x8 point square. (full size image)

The main challenge today was to just draw the pyramid from a set of parameters, so I could easily draw it anywhere at any scale. Here's what I got today.

Figure 2. Pyramid Blocks, drawn with debugging guidelines to check alignment in a PDF file. The blue line is the 18pt page margin.Closeup of a Word Counting Calendar Pyramid block of 10 blocks.Closeup of a Word Counting Calendar Pyramid block of 10 blocks. (full size image)

The janky code that draws this looks something like this:This is just an example; several other functions like hguide, vguide, bbDebug, and block are doing calculations as well.

/** draw a 10 block pyramid. return [x1,y1,x2,y2]*/
const pyramid = (xx, yy) => {
const xinc = DIM + GAP;
const yinc = DIM + GAP;
const _rows = 4;
const size = _rows * DIM + (_rows - 1) * GAP;

for (let y = 0; y < _rows; y++) {
const yo = y * yinc;
hguide(yy + yo);
for (let x = 0; x <= y; x++) {
const xo = x * xinc;
vguide(size - xo + xx - DIM);
block(size - xo + xx - DIM, yy + yo); // block does inversion
}
}
return [xx, yy, xx + size, yy + size, size];
};

let xoff = 0;
for (let i = 0; i < 3; i++) {
const [, , , , width] = bbDebug(pyramid(10 + xoff, 10));
xoff += width + 18;
}

There's a lot of arithmetic in here, and it's not very well structured. However, just getting the pyramid to draw according to my expectations is a good start. Next, I can add the text and draw a complete calendar day cell.

Document List

URSYS Web App Template

Embedded TypeScript Apps in Eleventy

A Review of Old Work and Stories

Eleventy Templates for Atom Feeds

Productivity Energy Crash

Workshopping the 'Activity Bingo' Form

Last Run of ETP Notebook Production

Activity Bingo Form Progress

ETP Mini Notebook Printing Press Tour

Identity and Logo Thinking Pass

Unprofessional Business Cards

Word Counting Calendar Reboot

Word Counting Calendar Interim Release

Calendar Layout Code Progress

Super Simple PDF Progress

Articulating Friendship

First skip day due to day trip to Concord, etc.

A PDF-LIB Reference

Programatic Drawing of Word Counting Calendar Blocks

BUILD CHALLENGE COMMENTARY

Another lethargy+nausea day! Perhaps because of this, I was distracted by VERY SMALL annoyances for several hours, but eventually drew a box using the research I'd done yesterday...yay! Once I got going it was more fun to tweak things, though I had forgotten how SLOW I feel I am at doing this kind of work. Resolving off-by-one pixel rendering errors in a reversed page coordinate system...not my favorite activity!

While I find writing this kind of code slow and tedious, it does give me insight into the kind of layout management system works best with the way I think about visual design and hierarchy. It's an interesting way to build my own productivity design language!

It's also one thing to have an API reference, and quite another experience using it. Today's experience helped reinforce PDF system concepts, as expressed by pdf-lib, which will help the coding go faster in the future.

BONUS ACHIEVEMENTS

I'm rather pleased at setting up my Visual Code Theme overrides to use purple and green, as seen in the Title Picture at the top of this post. The comments are already green in this theme (the Dark Theme for Visual Studio), so making the title bar purple while fixing the UX for "active tag". I wrote this up a while ago in a memo VSCODE Theme Tricks.

Shove these settings into your .code-workspace project file under the settings key:

"settings": {
...
"workbench.colorCustomizations": {
// override theme color for the title bar
"titleBar.activeBackground": "#4e256a",
"titleBar.inactiveBackground": "#4e256a40",
"titleBar.inactiveForeground": "#ffffff40",
// override theme color for the focused editor
"tab.activeBackground": "#4e256a"
},
...
}

Having different colors for different editors I have open helps me keep them straight in my head. Also, the tab.activeBackground setting fixes a horrible UX oversight in easily seeing what tab is actually selected.


We chat about personal projects and challenges on the DS|CAFE Community Discord Server every day. Come visit! Maybe you'll make some friends!

You can reach me at Mastodon or Bluesky. Or subscribe to the blog feed to stay up-to-date.