Development
The Technical Architecture of Firewood
From design to backend, my first full stack project
Firewood is an innovative independent blog navigation site with automated data fetching and manual curation. The backend, built with Node.js and Nest.js, includes modules for article management and scheduled tasks. AI technology is used for content classification, and SvelteKit is chosen for frontend development. Deployment is done via Docker Compose and Cloudflare Pages, with an emphasis on performance optimization. Building Firewood has provided valuable insights and a deeper understanding of backend development processes.
- #independent blog
- #Node.js
- #Nest.js
- #web development
- #SvelteKit
18
Firewood is an independent blog navigation site that's different from similar products. Data is automatically fetched and categorized, but there are also manually curated recommendations. In an age where writing and reading long articles have become rare skills, we hope to establish a traffic channel for authors and readers.
For a more sentimental and literary introduction to Firewood, please visit "Still Believe in the Power of Words: Independent Blog Navigation Site ”Firewood Officially Launched”. This article mainly introduces the website's technical architecture.
Background
After completing an introductory Node.js tutorial, I wanted to independently build a complete backend project to overcome my fear of backend development—it’s not very intuitive to debug—and to gain a comprehensive understanding of backend development.
Before this, I'd created an interface using Node.js to fetch and return image EXIF data, which had been running on my blog for a long time. But this was a very simple project, just using Express for routing, extracting information, and returning information. Although I later added database read/write operations, it remained a small tool and not a true backend project. For more on this project, please visit "Fetch EXIF Upgraded" and "Using ChatGPT to Create a Node.js API".
The idea of an independent blog navigation site had always been in my mind, and in terms of complexity, it was very suitable for beginners. There are automated crawler tasks, CRUD operations with the database, and more features can be added later.
Backend
I chose the Node.js tech stack for the backend and used the Nest.js framework.
Nest integrates many useful modules, making interactions with the database, authentication, and authorization easy to handle. Additionally, Nest’s documentation is very detailed, which is important.
Firewood’s backend is divided into several Modules: blog, auto, auth, and user.
auth and user handle user registration, login, and protection of authorized interfaces—namely, data CRUD operations.
The blog module contains two controllers: article and website, responsible for CRUD operations on articles and blog data.
auto is for scheduled tasks that regularly fetch article updates, check accessibility, and collect statistics.
The fetching is based on RSS files. If articles not in the database are found, their data is extracted, processed, and stored in the database.
Because the database uses MongoDB, there isn't a strong correlation between articles and websites. Therefore, access statistics for each article are summarized daily, not in real-time.
Since the longevity of most independent blogs is short, the backend checks the accessibility of all articles monthly and marks unreachable pages. Future versions will display expired articles.
AI
Simply presenting fetched information directly is inefficient, as everyone's interests differ. So, I used Baidu’s API to classify, tag, and summarize the fetched articles. The tags and classification information you see on the homepage are automatically done.
Frontend
This time, I intentionally didn't use the more familiar React but chose SvelteKit, which has a good reputation in the frontend community, to force myself to learn a new framework.
Svelte has almost no runtime, so the final package won’t include a lot of JS files. Its reactivity feature means I don’t need to write methods like useState().
But Svelte's drawbacks are obvious. Its ecosystem is not as mature as React’s, and there isn’t enough documentation and resources. Whether dealing with authentication or deployment, there are not many ready-made references, so you have to build everything from scratch.
The frontend structure is relatively simple. Besides the part visible to visitors, there's a management backend that requires login access.
Deployment
Nest.js and MongoDB are started and interfaced through Docker Compose on a server, while the frontend is deployed via Cloudflare Pages.
Initially, Svelte ran on the same server as Nest.js, with DNS resolution handled by DNSpod. Until a few days ago, I received an email from DNSpod notifying me of discontinued resolution due to violations.
So I moved DNS resolution and the frontend to Cloudflare, no longer considering visitors from mainland China.
Performance Optimization
Most frontend optimization is provided by Cloudflare, mainly caching. A large number of visits in a short period won’t hit the backend, reducing backend pressure.
Previously, I also made an optimization worth mentioning.
Firewood is a 100% SSR site. Even the interfaces are double-wrapped through an API Route, so user requests don’t expose backend URLs.
The fetching frequency is every 4 hours during the day, meaning data updates aren’t very frequent. If each visit required an interface request, it would put considerable pressure on the server.
So, I set up a caching logic in Svelte’s hooks.server.ts. This file handles all requests Svelte receives. If requests are processed to cache data to Redis, most visits wouldn’t need to hit the backend.
I had completed this feature but then discovered a new issue: if someone visits the first page and the data gets cached to Redis, and then the data updates, the second visitor reading the first page would get the cached data, while the second page would show the updated data.
This could result in the second visitor seeing duplicate data across two pages. Although solvable, after moving to Cloudflare, the Redis cache became unnecessary.
Insight
Building a project yourself gives you a deeper understanding of each process. The thought process in backend development is very different from frontend. Previously, I only dared to work on simple projects that didn’t rely on the backend. Now, even without professional backend support, I’m not intimidated. Worst case, I’ll figure it all out by myself.