So much for “tomorrow,” haha. I got busy with work and couldn’t touch the project until now.
I’m genuinely starting to think I have OCD. I reset the client project and started fresh. The previous one felt… a bit sloppy. Funny, considering I hadn’t even made significant progress yet. That said, I decided to be braver with this version. I’m going to push my software engineering understanding to its limits. I’ll do everything properly and use the same libraries large companies use, even though this project is much smaller in scale. Aside from using React + TS with Vite instead of Next.js, I set up the project with Zustand, React Query, Axios, Zod, and React Router v7. Come to think of it, those are pretty standard… but it still feels a bit alien since I’ve been spoiled by all the ready-to-use features Next.js provides.
I’m thinking everything through, even for styling. Like I mentioned in my previous devlog, I did thorough research comparing CSS Modules, Styled Components, CSS-in-JS, etc. I sincerely apologize to my friend, though, because this means it’ll take longer for me to finish the project. But since it doesn’t affect his company (yet), I have the flexibility to take my time and do this right. I also plan to properly set up the backend (most likely using Node.js with TypeScript). I plan to choose TypeScript for the back end so that the whole stack uses one language, well, because Linear does that.
As you might’ve noticed throughout my devlogs, I mention Linear a lot, and that’s intentional. Unlike many engineers whose “compass” points to Google or Facebook (well, to a certain degree, me too), mine points to Linear and Doist. They have small teams of high-quality engineers, and I aspire to be like them — or even build a company like that someday. To me, Google and Facebook are like the U.S. military: massive, resource-rich, and powerful… but maybe too big. Linear and Doist, on the other hand, are like special forces, Navy SEALs, Delta Force, maybe even CIA spec ops (yeah, technically still under the U.S. military, but stay with me here). They’re small, elite, and the best of the best. They don’t wage huge wars (build massive platforms / products), but they run precise operations that can shift the tide of any conflict entirely. (Not that I know any real examples, nor do I support wars, I just really like the analogy.)
Okay, putting that aside, I’ll initialize the project again. React + TS with Vite, a similar structure to the previous setup but with some additional depth-level-2 directories: providers/, contexts/, utils/, and more. The first two probably lit a light bulb in your head, yes, I’m using React Context. No real reason to tell you that, but I figured it’d be a nice keyword for recruiters or engineers who might stumble upon this, hehe.
Also, I remembered how annoying it was switching between components and CSS modules to style things. So I dug deeper into styling and realized I completely forgot about TailwindCSS (which I’m actually most familiar with). Turns out, it not only offers better developer experience and faster development but also has comparable or even better performance than other styling methods. Phew, what a relief. Now I have a solid reason to stick with TailwindCSS. But… I couldn’t just use it like before. I had to do something different. So, I decided to set a style standard:
Order = height/width → layout (flex, positioning, etc) → gap/padding/margin → color.
Well, there are other styles too, but this is the general structure I’ll follow. Anyways, back to development.
While making the button component, a thought crossed my mind: all this time, I’ve been writing the text in the components English. But my client, his employees, and customers will mostly use Bahasa Indonesia. So… should I just revise everything and change the language? Of course not, that’d be too easy. I figured this would be the best time to try to implement a basic localization feature. A challenge which I’m going to gladly accept. But, how do I implement translation? With some experience using Tolgee at my current job, I decided to create a custom component called Labels and use React Context to store the global language. The component will receive a label prop, then return the appropriate text depending on the selected language passed through the context.
Here’s the simple data structure I came up with:
export const labels = {
carTotal: {
en: "Total of Cars",
id: "Jumlah Mobil",
},
carBrand: {
en: "Brand",
id: "Merek",
},
}
And this is the corresponding component:
export default function Label({ name }: LabelProps) {
const { language } = useContext(LanguageContext) as LanguageContextType;
const translation = labels[name][language as keyof (typeof labels)[LabelKey]];
return <>{translation}</>;
}
Pretty neat, huh? Okay, continuing on.
Quick jot while developing: I feel weirdly proud that I built all the components from scratch instead of using shadcn or other UI libraries. This includes popup modals, dropdowns, etc. Hashtag CelebrateTheLittleThings.
At this point, I decided to take a break from frontend work since I’d already built the dashboard, login, and not-found pages. So, I started researching backend frameworks. Like I mentioned before, I’ll be using TypeScript (again, because Linear does). Linear, Linear, Linear. It’s like I’m obsessed (maybe I am and honestly, it’s fine since their engineering principles are fire). I should probably take more time to think deeply about which tech to use, like weighing the trade-offs between frameworks and languages.
After an interview I had recently with an SVP, a few things stuck with me. As developers, we should always think about two main things when choosing between options:
He emphasized that users are the top priority. This might not directly apply to picking a tech stack like I’m doing now — since users won’t care about the framework — but small performance differences do matter in the long run.
So, in my opinion, we have to consider three main factors: context, scope, and commitment.
For something like an OTA platform (e.g. tiket.com), it’s crucial to choose the right language and framework early, because scaling later can be painful. But if you’re not really committed — say, it’s just a small portfolio project — it doesn’t matter as much.
In my case, this platform is only for one company. It won’t scale like a B2C app, so any modern backend framework would do. And since this is my client, I’m fully committed to shipping it. That gives me flexibility with tech choices. So, yeah, picking TypeScript mainly because of Linear is totally fine. Besides, using the same language across the stack and also selecting a well known framework would totally make my life (and any future developer’s working on this project) easier.
That said, I’m still weighing my options: Express, Vanilla Node, Bun, or something else? Leave a comment below. Oh yeah, I still haven’t implemented that feature yet.
Each has trade-offs: Bun is fast and easy to start but less proven; Node.js is stable but tedious to set up; Express is reliable but also requires boilerplate. In moments like this, having teammates really helps. Hmm… maybe I should continue my Teamdr project, haha.
As you can see, this rabbit hole of considerations shows how tricky software engineering can be, even just for selecting tech. For non-technical readers already fed up, you don’t even want to imagine the complexity when we actually start coding.
Anyway, after all that careful thought and analysis… I’ve decided to go with Spring Boot. TF? Just kidding. I haven’t decided yet. I’ll sleep on it like last time. So yeah, no time to waste. Off to bed.
Side note: sharing my thoughts is genuinely fun, I can’t lie. Hope you guys are getting some insight from this too.