Making classics more accessible
I have a soft spot for mythology and classic stories. I have read most of the books on Abridged Shelf at least once, several of them more than that. But a lot of them are long. Epic poetry is not something you casually get through on a Tuesday evening, and the older translations can be genuinely hard going. The language demands focus, and focus is a resource I do not always have.
So I made shorter versions.
Abridged Shelf is a free library of public domain classics that I have abridged and modernized. Abridged, not summarized. The distinction matters a lot to me. I am not writing study notes or plot recaps. I take the actual text and condense it: the B-plots that do not carry the story, the scenes that spend forty lines describing a shield, those get compressed down into the beats that matter. What is left is still the story, told in its own voice, just tighter.
The other half is the language. A lot of these translations are over a century old, and the English shows it. So I modernize spelling and phrasing into contemporary English. Again, not simplified. This is not a children's edition and I am not dumbing anything down. It is the same book, in language that does not fight you.
I also made some editorial calls. For the Greek epics I use the Greek names rather than the Roman ones that a lot of older translations default to, because if we are reading Homer then it should be Athena and not Minerva. Small thing. Matters to me.
And as a nod to a certain static site generator I maintain, the first book I abridged was the original Strange Case of Dr Jekyll and Mr Hyde. It is already short. Now it is very short. I did a few more by Stevenson after that, mostly because they were quick and I needed to get the workflow right before pointing it at an epic poem.
The abridgment process
I knew from the start that I needed to use AI for this. I also do not entirely trust AI, which is a useful combination of beliefs to hold at the same time. It means you build guardrails.
Without giving away every single secret, the process looks roughly like this:
- Find a translation that is actually good (and complete!) and actually public domain.
- Split it into chapters, which often needs to be done differently for each book.
- Abridge one chapter at a time against a very strictly defined spec.
- Run automated QA before I ever read it.
- Read it myself.
The per-chapter thing is the important part. Keeping the original chapter structure keeps the work scoped and stops the model from drifting, wandering off, or quietly rewriting the shape of the book. Small window, tight spec, one chapter.
Then comes QA. Before I look at anything, it goes through automated checks run by two different models, deliberately from different families so they do not share the same blind spots. The checks are looking for three failure modes: did we lose something important, did we invent something that was never there, and did the model pull in details it knows about the book from training rather than from the source text in front of it. That last one is the sneaky one. A model that has read the Iliad a thousand times will happily supply a detail that is famous but is not actually present in the original texts.
After the machines are done, I read it. Every chapter. This is why I get a little defensive when people hear "AI" and think slop. I am extremely involved in this process. I built several custom pipelines specifically so I could stay involved without it taking the rest of my life. I may absolutely still miss things though, please let me know if you find a problem. There is a feedback link in the footer.
The audiobooks
It matters to me that the reading side of this is always free. These books are free. My versions should be free too. And they will be. Unlimited. Forever. Free. You don't even need to sign in or sell your soul to ad trackers.
But the process above costs real money to run, and so does the audio. So there is a patron option: pay whatever you think it has been worth, (minimum three dollars to cover transaction fees), and you get the audiobooks. Everyone gets the same perks regardless of amount. You can pay multiple times if you want, but you get nothing extra for it except my sincere gratitude. That is the whole model.
Also! If you're early, you get in for free. The first 25 people to make an account get the Early Adopter tier: same perks as Patrons, forever, no payment required. Free audiobooks for life, just for showing up early. After that it goes back to the patron model above. Sign up at abridgedshelf.com/register
The audiobooks are the part I am most quietly proud of. I am running a very good open source TTS model locally, and the quality is the only thing I have heard that comes close to ElevenLabs, which is fantastic and would also be financially ruinous at this volume. So instead I have three computers in my apartment generating audio. The Odyssey took roughly 25 hours of inference on a beefy workstation. That is why the audiobooks lag behind the text. But the goal is that every book will have an audio version.
As with any project, you learn things. Some of those lessons are unexpectidly disturbing. Apparently this model panics if you give it too much input at once, and before I figured that out, I generated the most cursed audio I have ever heard in my entire life. So I wrote a quick algorithm to split the text down. Simplified: every sentence gets its own WAV file (but I do some smartish stuff for long sentences). For each one I keep the input text, the audio, and a JSON manifest with durations and offsets.
That manifest turned out to be the best accidental decision in the project, because it means I know exactly which sentence is being spoken at any moment. So the site highlights the sentence on the reader view as you listen. So, you can read and listen at the same time, which I love, because sometimes there is a noise in the room or I get distracted and I miss a line and now I don't have to scrub backwards to find it. I just glance at the screen.
It also means verification is possible. Since I know what every WAV file is supposed to say, I can check whether it says it. So there is a verification pass where I transcribe every single generated clip back to text with speech-to-text and compare it against the input. The comparison is deliberately lossy, because you do not want to fail a line over punctuation. For genuine edge cases, mostly homophones where static analysis cannot decide, I hand it to a local text model and ask whether these two things mean the same thing. That was much nicer than maintaining a giant homophone mapping table.
On top of that there is a smoke test during generation that looks at the waveform itself. Is this plausibly speech, or is it noise, or is it just silence? If it fails a few times in a row the job cancels itself, because that usually means something dumb has happened, like running out of disk space. Local AI takes a LOT of disk space. So do WAV files...
I do a lot of spot checks by ear too. And now that the chunking is better, I am going to regenerate some of the earlier books which have artifacts where the sentence splitting wasn't as smart. But again, priorities. I'm using prosumer hardware, not H100s.
How the site is actually built
This is the part I find most fun to talk about.
It started as a plain HydePHP site. Markdown files in, static site out, done. Then I started wanting things: a reading list, remembering where you left off, and eventually audiobooks behind a payment wall. All of which need a backend.
So I wanted Laravel. But I also still wanted Hyde, because Hyde gives me things I did not want to give up. No data models for content. No database for content. Everything in version control. I can build locally and push without touching a remote database. RSS feeds and sitemaps generated for free. Content on disk is just nice to work with.
My first instinct was what I have done before, which is pull the Hyde framework into the Laravel app. But the current stable Hyde is a few versions behind the latest Laravel (v3 is on the way though!), and I wanted the latest Laravel. So I went with option two, which honestly turned out better anyway: inside the Laravel project there is a hyde/ subfolder containing an entire HydePHP project, and that is where all the static content lives.
The site runs on Laravel Cloud, and the Hyde build runs as part of deployment. Laravel then serves the resulting static files, essentially acting as a very small web server written in Laravel, with some wrapper objects around it. Hit the front page and it resolves the right file and returns its contents. There is a tiny bit of overhead in finding the file and booting the framework, but Laravel boots fast, Laravel Cloud is obsessively tuned, and static pages get cached on the edge anyway. It feels indistinguishable from GitHub Pages to me.
Then the obvious problem: I went to all this trouble for dynamic content, and now my pages are static files.
The solution is a token system. Hyde does not know anything about the dynamic parts. It just emits placeholder tokens, and the Laravel controller string replaces them on the way out. So the navbar changes if you are logged in, and the patron link disappears if you already are one, without any Blade recompilation and without any views living on the Laravel side.
That last bit was a deliberate boundary. I did not want views in two places, partly for my own sanity and partly because AI agents kept getting confused about which layer owned what. Making the rule absolute, no views in Laravel, dynamic content only through replacement tokens, fixed it completely.
Caching works nicely with this. Anonymous responses go out with cache headers, so most requests never reach the origin at all. Logged in users skip that header and get a narrower cache that still serves the correct dynamic bits.
Working with agents
On agents: as the great Aaron Francis said at Laravel Live UK, you have to contain them. Give them a frame to work inside.
So I built the frame by hand. The Hyde and Laravel integration, the gateway, the structural rules, all of that I designed and largely wrote myself. Some parts I wrote as pseudocode and handed over for implementation, but the shape was mine.
After that, I mostly stopped reading the generated code. It goes through a review agent running a different model, I glance at whether the right files were touched, and then I validate the actual feature by using it. Anything security related I still read properly, every time. And I do all the QA myself.
The design came later. My original layouts were stock HydePHP, which gives me all the UI elements I need, but it of course does not look very unique. So I did a few design passes with Claude Fable once the structure was solid.
Laravel Cloud
First time using it, no affiliation, and I have to give them a shout out. Laravel is magic for PHP, Laravel Cloud is that same magic applied to hosting. It truly is the Laravel of hosting providers.
Concrete example. My repo was ballooning with WAV files and deploys were crawling, so I compressed everything to MP3 and purged the masters from git. But I still wanted the masters stored somewhere. One button, S3 compatible bucket, done. I could have thrown them on Google Drive, but wanted to be able to send the files through code given I'm running generations on different computers and bringing in a Drive API integration brings a rewally different stack. So wanted Laravel to easily push the masters, semi automatically now and fully automatically later.
That is a pattern I believe in generally: manual first, then semi automatic, then automatic. Each round teaches you which parts are actually annoying and what the next iteration needs. You cannot design that from the armchair.
Stripe setup was also painless, which is not a sentence I expected to write about anything related to payments. But they have really thought through DX.
What's next
I have a long list of books I am excited to add.
The site is free to read and will always be free to read. If you want the audiobooks, three dollars minimum, pay what you think it is worth, and you get access to what will eventually be tens of hours of audio that is genuinely pleasant to listen to and syncs to the text as it plays. I think that is a good deal, but I am biased.
Further out, I would love to build a NativePHP mobile app with offline reading and listening. That sounds like a lot of fun.
Top comments (0)