404wolf.com

Overview
 

404Wolf.com's cover image
Here, I discuss the process I took to construct my website, and showcase many of its unique features and quirks. I explain my stack choice, how the posts are managed, and present my custom in-site editor. I also talk briefly about some specific struggles when building the website, like creating a good backup protocol and getting my markdown to parse properly and in a very specific way.
personal

Making 404Wolf.com

Inspiration

I began working on this website during my second week of my batch at Recurse Center, an amazing open-ended programming retreat based in Brooklyn, NY. I initially was planning on working on various other ongoing projects, such as an English flashcard generating service, but decided that I wanted to have a good place to document my progress on everything else. I started by making a simple homepage, and then when determining how to integrate a post/blog system fell down the rabbithole of learning my first stack and javascript for the first time. I could've used Wordpress, but I thought it would be a good chance to learn how to do it from scratch.

Choosing frameworks

One of the main goals of this website was to let me break into web UI. Priorly I'd experimented a bit with templated HTML, but had never had done much javascript. I find that I'm very fast to pick up on programming languages, and had trouble finding a well paced course for JS basics. What I found after some research is Harvard's CS50 React Native course's first video, where they speed-teach the language (which is public and can be found here) to be super helpful. I also read over the learnxinyminutes.com website to get a brief overview of the syntax. I've found that javascript (and, later, typescript), is weird, and not quite like other languages I've used. In some ways it's functional, especially with such flexible lambdas and promises. Yet, in others, it's object-orianted. Everything is a descendent of a primitive object, much like Python, and you can have "classes," but using it functionally is a lot more straightforward than in Python in my opinion.

For the actual frontend itself, I ended up going with React after some research, since it seemed to be decently beginner friendly, and I liked the idea of a composable component based system. At the time I didn't know about React component libraries like MUI, so I ended up building everything from the ground up.

Since I knew I was going to want a backend for things like managing the posts on my website, I did a bit of research on how to set up a webserver for the project. I could've used express or django to serve the site and an API, but a Recurse batch-mate introduced me to NextJS, which I found super easy to setup and very interesting in principle. What's great about NextJS is how it let me host the website for free with Vercel too. NextJS is an interesting framework that blends React for the frontend with Node's Express for the backend, so that you can write your backend would-be API code in the same file directory, and even files, as your frontend code.

Originally, I made my website pages pull from a folder of markdown files which I edited and directly commited to Github. However, at Recurse I ended up meeting someone who introduced me to Prisma and Postgresql. Postgres is a relational database system, an extension of SQL, and Prisma is a popular Javascript ORM (object-relational-mapping framework, used for querying the database with JS-style calls instead of literal SQL queries). I stored the posts and some resources in AWS S3 blob storage (flat ID to file storage), which at first was a pain to set up but got easier as I tinkered with the settings and began to understand how it (and auth) worked, referencing the images of my posts with keys that I stored in the database.

For styling, I originally was planning on just using basic CSS, but after stumbling upon tailwind in a React tutorial I was using, decided that it would be worth giving it a shot. It was simple to get set up, and made styling the website much easier and faster. Tailwind is a "utility-first" styling framework that provides a ton of useful classes that pre-pack styles so that you can do the styling directly in HTML instead of ever needing any CSS, sort of like bootstrap. For example, to add a bit of padding to the left of a div, you can simply add the class "pl-3". It has classes for pretty much every possible CSS style, and has predetermined discrete choices for sizes and colors (which can be customized, but in general help development more than hurt).

As I was working on the site, I came across Typewriter.js, a library for simulating typing. I thought it'd be a cool affect to apply to headers on my site, and then later experimented with other animations and animation frameworks a bit.

1typewriter.typeString('Hello World!') 2 .pauseFor(2500) 3 .deleteAll() 4 .typeString('Strings can be removed') 5 .pauseFor(2500) 6 .deleteChars(7) 7 .start();

Post Management

One of the key features of my website is its integrated post management system. Though originally my purpose was to just have a collection of my projects on the site, as a portfolio of sorts, I decided to also add the ability to post blogs too. All posts on the site are of a specific type, either project or blog. By going to the pattern matched URL https://404wolf.com/posts/<type>s, you can view all posts of a specific type. Each post has a specific schema, which is used to generate a grid of tiles that present post previews.

1interface PostData { 2 coverUrl: string | null; 3 coverAlt: string | null; 4 id: string; 5 title: string; 6 description: string; 7 date: string; 8 tags: string[]; 9}

href
href

The posts themselves store this metadata in the postgres database, and have corresponding markdown files in S3. When the page is loaded to view a post, the S3 markdown is prefetched, and is rendered client side. I use react-markdown to render the markdown, with some custom overrides to handle images and codeblocks. Discussed in this blog I wrote more extensively, I've also added image blocks to markdown, to allow for groups of many images to show up inline in the rendered markdown.

Post editor

Post editor
Post editor
Editable S3 text area
Editable S3 text area
To edit my posts, I decided to add an integrated editor into my website. This is because I want the website to automatically handle storage of associated post resources (images, files, markdown versions, etc.), rather than having to manually deal with uploading things to S3 and directly using the hard S3 links. My goal was to be able to reference the resources by keys (unique IDs I assign to them) directly in the markdown, and by integrating the editor into the website I've made it possible to have a what-you-see-is-what-you-get markdown editing system where the markdown automatically replaces aliases live. The actual post-editing page is quite complex since it includes many different fields to enter metadata for the project post, a split screen viewing panel, and a resource panel. The most notable part, seen in the Editable S3 text area image above, is I've made a component to directly edit an AWS S3 file with simple text area entry that is capable of displaying images and other artifacts as rendered markdown.

Exporting/importing

Export tree
Export tree

In general, I don't like locking myself into ecosystems, so from the beginning I knew I wanted a system to export the contents of the site. This website obviously relies on the hosting of various different cloud providers, which, though reliable, are fail points. When I created the post editing system, I also wrote two basic scripts to upload and download the all the posts and their respective metadata. All files associated with a specific post get stored in a folder alongside the post's markdown, and the metadata is saved as a simple json. Writing these scripts was rather simple, since I'm iteratively doing a database call for each post to download all the resources using the public S3 URL, and my ORM can give me a metadata json automatically.