We started with a bookmarks file nobody ever opened
The first commit in our repository is an empty Laravel app from 30 March 2026, and its message is "Innitial commit". We left the typo in. Rewriting history to fix one letter felt like more trouble than the letter.
The real start came a week later, on 6 April. One commit that day added 7,910 lines across 73 files, and with it the app could open a browser's bookmarks.html file in a three-pane explorer and fetch a clean reader copy of a page that refused to load inside the app. A second commit filled 12 gaps in the tests, among them the home page and logging out, and a third added a logo and favicons. In its config the app was called "Sketch Me In".
We're a very small team, and this log is where we write down what we built and when, starting with that week.
Why a bookmarks file
Every browser can export its bookmarks to a single HTML file, and almost nobody ever opens it. Ours was big, far more than a browser's bookmark manager is built to scroll through.
So the first goal was small. You drop in the file and see the folders on the left, the links in the middle and the page itself on the right. Nothing saved articles yet and there was no reading list, because all we wanted was to look through what we already had.
Two decisions worth writing down
The explorer reads your file in your own browser. A visitor without an account can browse their bookmarks, and the file never leaves their computer. That explorer is public, so anyone can open any bookmarks.html file without an account.
Every address is stored once. Links go into one shared table of addresses with the utm_ tracking tags stripped, which makes example.com/post?utm_source=newsletter and example.com/post the same row. When two people bookmark the same article there is one row for it, and anything we learn about the page is kept on that row.
A reader view, as a fallback
The right-hand pane loaded each page in a frame, and plenty of sites refuse to be framed (the design note from that day used X as its example). For those sites the server fetches the page, keeps the article text, cleans out scripts and stores the result with the address. Because the copy is stored with the address and not with whoever asked for it, the next person who saves the same link gets it straight away.
Two safety rules were there from the start. The fetcher refused private network addresses, and reader requests had a rate limit.
We built the reader as a workaround for blocked previews, and that week we didn't think of it as much more than that.
Import meant replace
Importing a file replaced everything you had. The plan for that week says "clear and replace" in so many words, and with one file and no browsers syncing into the library it was the simplest thing that worked.
It also meant an imported file had no idea where its bookmarks came from. Of the choices we made that week, it's the one we'd make differently.
The next chapter is Teaching the browser to talk to Reading Rewind.
More from the build log
-
18,918 orphaned bookmarks and the rule they taught us
On 2 October 2026 we found 18,918 orphaned bookmarks in our own library, left behind by a deleted source. Now every bookmark set in Reading Rewind has a source.
-
How we cut a 115-second sync to 4 seconds
Measured speed-ups in Reading Rewind: a full re-sync from 115 s to 4.2 s, a 5,000-link import from 7.5 s to 0.8 s, and lighter clicks across the app.
-
Locking the doors on a small read-later app
How we approached security in 2026: safer link fetching, single-use pairing links, rate limits on the busy parts of the app, and security headers.