Intro
Back when I wrote this website throughout the 2021 summer, The principle was more oriented to my previous "microservice" arhitecture instead of a more practical approach like now. I still find the idea interesting, but I personally think for a portfolio website it is not needed, and with Next.js
's amazing featureset, I can do everything that I need from the same Next.js
app!
This part year I've spent a lot of time experimenting with different/new approaches to creating web applications and I've made many projects which you can see on my GitHub.
The Old Design
The project was structured as a monorepo with these packages:
frontend
-Next.js
frontendagenda
- Background Cron job for YouTube and GitHub dataidentify
- Auth server foragenda
spotify
- Spotify statistics
What's even more funny is that the entire project has been converted to Typescript except for the agenda
microservice as even while I was coding it I didn't really understand how it worked so therefore i didn't want to touch it :)
By having everything so seperate from each other, it was hard to keep everything synced with each other (Type Definitions, etc.) so I left most types for API responses as any
which is never good for a senior professional typescript mastermind like how I am now.
My website was also using a MongoDB database connected to each needed package with a basic library to interact with the database, there was no set schema, so no type definitions, etc...
The New Design
From the months i've experimented and developed a solid understand of Next.js
's features, I decided to swap out the monorepo approach and stick with a single application.
I recently discovered the T3 Stack which creates a Next.js
application containing:
Typescript
- Superior programming language
Typescript Type for Gear Page1export interface DeviceProps {2 icon: IconType;3 name: string;4 description: string;5 specs: { prefix: string; suffix: string }[];6}
tRPC
- End-to-end typesafe APIs made easy
tRPC router example1export const appRouter = createRouter()2 .transformer(superjson) // Safely serialize JavaScript expressions3 .merge("blog.", blogRouter) // Add Blog Routes4 .merge("spotify.", spotifyRouter) // Add Spotify Routes5 // Example of queries which were merged above ^^6 .query("getStatistics", {7 async resolve({ ctx }) {8 return ctx.prisma.youTubeStatictic.findFirst();9 },10 })11 .query("getProjects", {12 async resolve({ ctx }) {13 return ctx.prisma.gitHubProject.findMany();14 },15 });
Prisma
- Great easy-to-use ORM
Prisma Schema1model Comment {2 id String @id @default(uuid())3 userId String4 user User @relation(fields: [userId], references: [id], onDelete: Cascade)5 postSlug String6 post Post @relation(fields: [postSlug], references: [slug], onDelete: Cascade)7 comment String8 createdAt DateTime @default(now())9}
NextAuth.js
- Easy authentication for Next.js
NextAuth.js provider1export const authOptions: NextAuthOptions = {2 providers: [3 GithubProvider({4 clientId: process.env.GITHUB_ID,5 clientSecret: process.env.GITHUB_SECRET,6 }),7 // ...and more providers, etc.8 ],9};
...and from experimenting with it on my own on smaller projects, I decided to rewrite my website using this Tech Stack.
From what I've also seen, the website has proved to be much faster and much more responsive compared to my previous approach and this is what I've wanted. The purpose of my website is to show how my best work would look like, and I've never been more happy regarding the quality of my website.
Change of Database
Like I mentioned before, I used to use MongoDB, but now I switched to an SQL called PostgreSQL
, I just like it much more because of how well it integrates with Prisma
and the idea of using schemas/tables in Postgres instead of documents in Mongo.
Background Job Changes
Before I used to use agenda
to fetch my YouTube and GitHub statistics using a cron
schedule, but as fun as interesting as that system is, I decided to change my approach.
Each cron job has its own API route with its own security key, I then have a GitHub routine action which makes a request to the cron job with the security key, and if it is correct, it executes the code needed for the background job.
Cron Job Example1const handler: NextApiHandler = async (req, res) => {2 try {3 const { secret } = req.query;45 if (!secret || secret !== process.env.GITHUB_JOB_SECRET)6 return res.status(401).json({ message: "haha no" });78 // do job9 } catch (error: any) {10 console.log(error);11 return res12 .status(500)13 .json({ message: error.message || "Unknown Error" });14 }15};
Hosting
Before I used to host this website on my Kubernetes Cluster on my home network, but since my living arrangements are changing (I am in the United Kingdom to study and living in Romania with parents), my server cluster is currently offline, I plan to get it back working better than ever around October/November.
Because of this problem, I need to do what I said I've said I'll never ever do to myself, host my services online...
Welcome to the cloud!
Well that was before I discovered Railway, which is essentialy Vercel, but orchestrates everything together with Docker (such as a Database, etc.).
Well what about to cost? The free plan does give you a 5$ per month credit, but only 500 working hours per month (which if you don't know, is less hours than how much a month is), and it had pretty low resources allocated to each container. So I just inserted my credit card and it upgrading my containers to 8GB ram and 8 core CPU!
What is even better about Railway is that I still get the 5$ free credit each month so I am not even paying anything for my website!
Conclusion
Apart from all that, I've mostly spent upgrading the website to match my current coding standards, aka using better principles for coding, and so on.
Thank you for reading this more technical blog post, make sure to check out my other posts while you're at it!
Cheers!