about

loading...

~/boxhouse/dev-diary/book-page

Book page

  • jekyll
  • javascript
  • paged.js

Problem statement

The boxhouse needed a way to host my books.

Four months ago, I began writing my first book, the gumgum galaxy. I decided to format it like an actual book–with margins and header/footer content–and intended to host that PDF on my website.

Sub-problems

I wanted boxhouse’s reader to have a layer of security on top. I don’t want my books to be scraped, nor do I want them downloaded.

Obviously, it’s difficult to avoid these things on the modern internet. But I wanted to at least record intent. Scraping is one of those funny things that’s legit until someone tries to prevent it, then it gets a little more complicated.

Background knowledge

In the lead up to my work on boxhouse, I’d done some searching and found solutions. I believe the main one was ghostwriter.

More broadly, my thought process was “I have this file that’s basically images, I want to make it difficult to siphon up those images”.

────── ‧⋆✧˚₊‧⋆.✧˚₊‧⋆‧ ──────

Key lessons

The boxhouse is one of my canvases

I don’t need to force content into more traditional formats. The boxhouse itself is part of my aesthetic–and so how I’ve decided to design it is part of my content. This book looks so much cooler now that it has a visual relationship with the page.

Progress tracking has a strategic value when using AI as a tool.

During this process, I updated my git repo quite often. That wasn’t enough though. My changelog idea really solidified things, and ensured that I was focused–and knew how to ensure that Claude was focused.

Recordkeeping on process and reflections on what’s going well/not well are strategic for me, as they helped me think things through, and for Claude, as my documentation behaved as its compass.

Given the strategic importance, I wouldn’t trust anyone other than me to both store and maintain this document (so, no using external solutions to manage your recordkeeping).

Also, see my discussion (link) on persistence (/link). That links to this observation. Recordkeeping facilitates attention.

Ask what’s necessary from a package; ask if that should be reproduced by Claude

Paged.js has a lot of solid components that I needed. They were sullied by certain features–that were effectively bugs to me. Claude had enough context to just reproduce the feature I needed, which efficiently dealt with the issues we were spiralling around.

25 March 2026

Attempt one: PDF-to-JS pipeline

I gave the following prompt to Claude:

Hi Claude ٩(ˊᗜˋ*)و♡ I want to implement my book page for my website. REQUIREMENTS: -> I want it to be difficult to download my book. It's a PDF. I want to use JavaScript to protect it from simplistic/easy download. -> I want the website to maintain its cohesiveness. This should be simple--whatever the JavaScript solution is gets embedded in a window container. ASSET: -> The copy of my book is in "assets/books".

I used Opus, as this strikes me as a bit of a heavier lift.

What went wrong

The initial implementation was pretty good, but there were a couple bugs:

(i) something was up with the JavaScript’s rendering; each time I clicked the next page button, the render would grow, until it hit a pretty good size. (ii) progressing the pages had a distracting white flash.

I spent the afternoon trying to work with Claude–and ended up wasting a lot of my usage for the week!

I learned a couple pretty important things from this though.

What I learned

First: The site’s layout (with a grid and a couple columns) causes a lot of problems. It likely sits a little too high in the site’s structure–it’s useful for pages that require a lot of metadata (so, posts, galleries, etc.), but superfluous for something like my book page–which just has a date and content warning.

Second: My PDF idea kinda sucked. I think I’ll keep doing it, because it’s fun to format a book. As I kept trying to adjust, though, it became increasingly evident that my PDF idea was one of, if not the major, problem.

I was the bug! (𖦹ᯅ 𖦹)

Attempt two: MD-to-JS pipeline

How I got here

I had to ask myself some questions and think them through–which I did recursively.

First, what don’t I like about the current implementation? Well, it’s too heavy for one. Less important, you can’t really read it.

Answer: it betrays the natural aesthetic of my website as I’ve been curating it! My PDF idea was vestigial–much like books themselves. My website lets me control way more about how I present my writing.

It made more sense to collect my book into a MD. I also went to the more decorative pages and removed the background with an alpha layer, so they’re just transparent PNGs now.

Two, should I be taking more control from Claude? This isn’t the first time I’ve had an issue with a strict adherence to the layout’s grid (the directory sidebar navigator was a struggle that ended with “just lift it outta the body, then it won’t be fighting with the DOM” so…).

Answer: yeah probably. I’ve worked with Claude a lot on this website, and it’s definitely time for me to take more control. So, less “do this” prompts, and more “look at these half-written files, can you finish them” problems.

Process

I put my idea by Claude and got a list of files I’ll need to work on:

  • default.html
  • book.html
  • components.scss
  • book.js
  • I can definitely handle the first three, but the last I’ll have to hand off to Claude.

    I studied a mini report Claude wrote me on the initial implementation so I could better understand what had to go in each file, and I went off ᕙ(•̀ ᗜ •́)ᕗ

    Not really, first I went to go transfer my GIMP files into MD (… (ˉ▽ˉ;)…) and also scan some assets. Then, I went off ᕙ(•̀ ᗜ •́)ᕗ

    ꒷꒦꒷꒦꒷꒷꒦꒷꒦꒷꒷꒦꒷꒦꒷

    24 March 2026

    I worked with Claude to understand what files I needed, and consequently which I could handle on my own. This turned out to be: book.html, book-page.html, and components.cscc.

    I handled the three file’s quite alright–building them up from scratch. It was a useful experience!

    I passed off to Claude to build book.js, and then encountered two bugs:

    1. my sidebar borked.
    2. For some odd reason, the JavaScript file couldn’t find my book’s md–even when fed the character-for-character path.

    BORKED SIDEBAR 𓂃˚✦₊˚

    For the first bug, I went ahead and dived into the sidebar code. This lived in layout.scss. I’m not entirely sure what caused the bug (the initial pane grew wide), but setting the width fixed things.

    As I debugged this, I got much more familiar with the code and began to master it. A strange thing I need to get used to is not annotating everything–and keeping a lessons learned doc–et voila, c’est ici. ٩(˘◡˘)۶

    My takeaway is a little bit strange: I need to read both abstractly and literally as I assess code. Example: grid-template-columns: 15rem 3rem 3rem 2.5rem; gap: 0; means “for the items in the finder, the columns are this long”. I say abstract, because gap: 0 is so obscure (gap? Where? Well, I wouldn’t know anyways, since it has no value! What!).

    Now I’m posed with a slightly different thing though: the date on my sidebar is not right (3.12…. I read that as third of December… no year!).

    Shyow, let’s go ahead and find out where the sidebar pulls data from. This would be HTML.

    Actually… I should commit to git (•̀⤙•́)

    Nyaow…. I just whipped together a quick favicon. I’m gonna sit on the font import though. Anyways. What I’m looking for isn’t in default.html (ó﹏ò。)

    Okay, actually, I’m sure it’s in sidebar-tree.js. Yep (٥⁀▽⁀ )/

    Key detail: the columns are populated from sidebar.html outputs. This is really good to know, because I need to harmonize this sidebar with the toolbar (my solution for mobile).

    Okie donzo. Claude had added an entire function for automatically having the bar open on a post… Really interesting. Eyes are important, spiritually speaking, and they have a lot of importance in contemplation. Vision corrupts the mind–but also, Claude completely missed the mark! Claude doesn’t have a mind though… so I guess it can’t really get corrupted in the same way that men can be corrupted. (-ω-) zzZ

    Alright, pretty sure the date issue is in sidebar.html, but I’ll go after I finish passing through this script.

    Now that I’ve passed through that, maybe a little task for me is to code in a click to close feature.

    I’d be dealing with event listeners for clicks on the title bar–same mechanism that already exists just backwards. I wonder if “this should also go backwards” is a deeper design philosophy that I hadn’t considered.

    ANYWAYS. SIDEBAR.HTML. Easy fix, as I thought. But now I need to go readjust the sidebar again.

    But before I move on… I don’t like how the words display–the w is confusing. It seems to be hard-coded though… Well! I tried to just add an append and that wasn’t good! Borked the whole json.

    Searching around has me nowhere; it would appear there’s a plugin somewhere appending the w on… but I can’t figure it out. I’ll ask Claude later.

    With regards to the click to close: I think the code responsible for click to open is: document.addEventListener('click', function (e) { var sidebar = document.querySelector('.window-sidebar'); if (!sidebar) return; var inSidebar = sidebar.contains(e.target); var inFlyout = flyout && flyout.contains(e.target); if (!inSidebar && !inFlyout) { collapseToRoot(); } });

    Basically, this adds a listener to the DOM for a click. Then, it creates the variable sidebar, which holds the DOM… element? of the .window-sidebar. If the sidebar isn’t hit by the event, return (so, go back to the top). Otherwise, create two variables for in the sidebar…

    Oh, nevermind.

    I think it would look something like this: document.addEventListener('click', function...? (e) { var inSidebar = sidebar.contains(e.target); var sidebar = document.querySelector('.window-sidebar'); if (!sidebar && !inSidebar destroyFlyOut();

    I’m not sure, I’ll put this by Claude later.

    BORKED JS NOT READING MDPATH

    For the second, I waited for my Claude usage to reset. This project has been steadily eating up usage… Now… Claude returns in three minutes but let’s go ahead and try to debug this. It’s very strange.

    When I try to load my book to debug/adjust, I get the error that the mdPath doesn’t exist. Which makes no sense, because I’m using the literal character for character. So something’s happening somewhere in the logic. Let’s read the scrippppp.

    From the outset, it’s sorta funny. The issue is literally at the first step of the pipeline. Okay, I actually have no clue. I’ve tried to comment out some things that might’ve been causing the issue, but I think the issue is actually that I haven’t set up the page… I don’t really know how to.

    I prompted Claude with:

    Hewo Claude ପ(๑•̀ᴗ•̀)* Can you help me set up the proper page infrastructure to load in my book the gumgum galaxy? Relevant files: [list of relevant files]. It's doing its thing... Output required: 5%. Not bad. I can definitely play around from here on out. I need to reserve my remaining use for the week to facilitate my launch .·°՞(っ-ᯅ-ς)՞°·. But, for now, here's what I'm looking at (lol) . ## MD no longer borked... but nothing's working ( ´_ゝ`) I decided to start with one of the most glaring visual issues: the background image isn't loading. I went to Claude, which was surprisingly not very useful. This seems like a really simple issue. Since that doesn't seem as straight forward as I like, I figured I'd switch to the biggest issue--nothing's actually rendering (lol). I recognized from the outset that this issue stems from the cscc not having any way to handle the header images. I think. So I had Claude walk me through that first. Claude's currently trying to figure this out. Interestingly, I've only hit 18% usage. Okay! Lots of progress! I had to switch to an Opus instance... for an issue that was really simple. Basically: Claude placed the book element in the HTML in the wrong place. Or maybe I did, I don't think it really matters (∩^o^)⊃━☆ So we've jumped over one hurdle: everything is rendering. But now... ## Things less borked but still borked just weirdly All of the pages fly by out of order. And things still aren't centred... I tried to parse things through, but I can't seem to figure out what's going on. There are some strange issues more generally--one being the bg-image isn't loading either. It's late but I really want to understand what's going on... anyways. # 25 March 2026 Couldn't really sleep cuz I was annoyed at this. Which is a little bit interesting! I was right to be frustrated, because my intuition was **correct**, and this is a really good learning experience about Claude. I can intuitively understand how these technologies (html, css, js) layer on top of each other--especially in the instance where I'm feeding an md into JS and asking it to display on the screen. Obviously, this displace will be caught in a container somewhere. I spent my morning's usage with Claude trying to troubleshoot this. I still have two main issues: 1. The actual pages are still on the left grain of the stage. 2. My background image for the page isn't visible ## Moving the pages to the centre of the screen I had a sense that the issue I was dealing with wasn't in javascript, nor css. I'd been testing around a lot and wasn't seeing anything interesting--some dramatic things, but not interesting. Also, I'd googled around to see if others have had a similar type of problem, and not really. So, **I must be the bug .·°՞(っ-ᯅ-ς)՞°·.**. And yeah, because I was relying too heavily on Claude. The solution: add a container div in the root page (book-page.html). That's it. My intuition said as much, but I didn't quite know how to get there. Now, I'm looking at a page that's muuuuuuuuch more in line with what I want. ## Revealing the background image This is really important, as it's my book cover without any additional editing. Also, the aesthetic of my edited photography behind my book is precisely what I find appealing about this whole concept! The photo does actually load--I got here with Claude, issues, again, in the html pages (a trend here ( ฅ'ω'ฅ)). But now, something's up. If I spam reset the page, I see the image render in. More elegantly, if I check the devtools, I'll see it there too, but that's really lame. So: something's covering the entire background. What's also worth noting is whatever's covering the background _isn't_ covering my polygons. So, to use z-index as a bit of a metaphor: background image = <1, whatever this cover is = 2, polygon/book stage = 2>. I went ahead and moved the div from the book-page.html to book.html, and it does seem load in stronger--still crushed by something. I believe it's actually being denied by book.js... but it's not actually explaining to me what's going on which is frustrating--just that it isn't loading. I do know, though, that book.js will go through the md and remove all yaml. This is just a little bit puzzling because that yaml is in the HTML file... but materially, I know two things: 1. the DOM receives the image and even loads it sometimes 2. something is denying it. I get the feeling this has to do with how I've embedded the content... it's not strictly inside a container. Which is a little bit nuts but also whatever man. Kind of whatever? I want opacity. Why is this so hard? But I wonder if I need to return to my initial concept, and ask if booked.js is even the right tool for the job. I've actually confirmed my feeling: I played around with how the content is loading, and I can see the background now--but the actual book is gone. A more nested structure might actually solve a lot of problems--but I'm nervous that opacity is an issue. ## What I have to go back to Claude with Unfortunately, all of this ridiculous tweaking to the JS has broken the page render--so, my book is being served, but very wrongly. It goes on my back... badly. I'll have to get Claude to revert whatever it had done. I also think it'll be good to review what the hell it was doing and write a little summary here, so I can be sure to internalize this. ... To my surprise, this situation has not been resolved. I hit my usage trying to figure it out which is very frustrating. The JavaScript for paged.js is pretty esoteric and abstract, so I don't feel confident in tackling it on my own. Which is precisely why I'm going to spend the next couple hours tackling it on my own =ᵒᴥᵒ=. Before Claude went back to bed, it did get one of my images to display. This leaves me with two problems I can easily articulate: 1. section images are not being rendered as their own pages. 2. There is a disconnect between the render and the page controls. As an aside, it's pretty clear that all of this is coming from an issue rooted in me: I was way too quick to run to Claude to ask what was happening, instead of just testing things on my own. So really, this is just contrapasso. I was too quick with my questions, so now I sit alone with 'em and stew. Shooooooooooooo I'm gonna go ahead and stir the pot for a while ᕦ(ò_óˇ)ᕤ._ Which didn't get me very far. I can interpret the pipeline, and I understand the general gist of what's going on, but implementation of the header as image is difficult because of how paged.js is working. It seems to be unnecessarily heavy--crushing styles and other data. I'm also thinking this is somewhat to do with how Jekyll functions. I have some downtime now, so I might actually just see if there's a different way to implement this that's lighter weight than paged.js... or just try to work with what I have. IT'S DONE. I WAS RIGHT ♪(´▽`) ## Rough-but-functional book page I keep a changelog now that acts as a bit of an institutional memory for Claude and I. I don't let Claude edit this, I maintain it. I also keep my instructions in here as well. I had put in my key takeaways for today that I probably need to examine whether page.js is actually the right tool for my job. Clauded picked up on that, and suggested that it just implement a simpler pagination script. This was the fix! Paged.js was not fit for purpose. ### What was wrong with paged.js? It had too much overhead. I assume that its advertised use doesn't align with what I was trying to do. In its pipeline, it crushes certain specified CSS variables, and overrides them with !important. I was trying to fight against the tools design. ### A fantastic Claude use-case Paged.js was conceptually what I wanted. During my head-slamming with it, I had a couple moments where I thought "oh wow this is going to be perfect." Reality, though, is paged.js had _components_ that I wanted. Claude is my tool for distilling those components so I can have them on-hand. With those distilled components, I have a lot more control and leverage over how I use available tools. This has implications for other packages, and it may be useful baking the question into my development methodology: Do I need this package, or do I just need one thing from this package? Can Claude rewrite what I need from this package so I have full control? Very neat. Very fun (◡ ‿ ◡ ✿) ## Final cleanup Just a few more stylistic items that'll just be touching the HTML and SCSS. 1. I need to design a better way to display the content warning. I'd also like it to have a dismiss button. 2. Implement the book's metadata somewhere (I also need to explore what metadata other than date (´-ω-`)). 3. I'm probably going to write a discussion on the Gum Gum Galaxy. I see myself doing that with any book I write. So, I'll want a little window pointing towards the discussion. 4. (and most tricky/spooky), the cover image is still a bit too long. It clips the bottom of the book's container. I need to fix that. My immediate repsonsibility is the content warning. Otherwise, the other stuff can get shoved into an array of todos for this page. # 27 March 2026 Today, I'm going to tackle the content warning and the date. These are the final touches. I've already prompted Claude on this and I have code sitting for me to implement, so I'm gonna give it a go. ## Content warning I require the content warning to sit atop the book window upon loading the page. There needs to be a button to dismiss it, and it should't reappear without reloading. The code Claude provided worked well, so that was cool. My only issue was the placement, but now I'm rather seasoned at this so I could handle that on my own sorta (人 •͈ᴗ•͈) Though I'm not entirely clear on certain tags (and whether they're event called tags...) like position and display. These are quite abstract and hard to pull apart. But it's done, and it works better than I had anticipated&emdash;it covers the entire page and the book controls until the user dismisses the warning. # 28 March 2026 My last job for this page is to add the date. Claude also provided me this code, so it's just implementing it.