<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: tutututu</title>
    <description>The latest articles on Forem by tutututu (@restu_muhammad_d32f98b653).</description>
    <link>https://forem.com/restu_muhammad_d32f98b653</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3812402%2Fc6491c1c-3afb-4e53-b608-e64de7f17c4d.jpg</url>
      <title>Forem: tutututu</title>
      <link>https://forem.com/restu_muhammad_d32f98b653</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/restu_muhammad_d32f98b653"/>
    <language>en</language>
    <item>
      <title>I'm tired...</title>
      <dc:creator>tutututu</dc:creator>
      <pubDate>Sun, 08 Mar 2026 04:08:14 +0000</pubDate>
      <link>https://forem.com/restu_muhammad_d32f98b653/im-tired-2d99</link>
      <guid>https://forem.com/restu_muhammad_d32f98b653/im-tired-2d99</guid>
      <description>&lt;p&gt;I've sent out hundreds of job applications through platforms like JobStreet, Glints, and LinkedIn, and rarely heard back. Not even a rejection email.&lt;/p&gt;

&lt;p&gt;The reason? My CV was buried under thousands of other applicants. On most job platforms, HR receives a massive pile of applications through an internal dashboard, and if your CV isn't near the top, it's practically invisible.&lt;/p&gt;

&lt;p&gt;I thought: what if applications landed directly in HR's email inbox instead? An email feels personal. It stands out. It doesn't get lost in a dashboard full of 500 other applicants. So I built lokerbaru.id (&lt;a href="https://lokerbaru.id" rel="noopener noreferrer"&gt;https://lokerbaru.id&lt;/a&gt;) — a job board where applications go straight to the employer's email, making every application feel more personal and significantly more visible.&lt;/p&gt;

&lt;p&gt;I built lokerbaru.id using the MERN stack (MongoDB, Express, React, Node.js) — but with significant additions:&lt;br&gt;
&lt;strong&gt;Frontend&lt;/strong&gt;: React 19 + Vite =&amp;gt; Fast dev experience with HMR; React's component model made it easy to build complex multi-role UIs (Job Seeker, Employer, Admin)&lt;br&gt;
&lt;strong&gt;Backend&lt;/strong&gt;: Express 5 + Node.js =&amp;gt; Lightweight and flexible — perfect for building a REST API with middleware-heavy architecture&lt;br&gt;
&lt;strong&gt;Database&lt;/strong&gt;: MongoDB + Mongoose =&amp;gt; Schema flexibility was key — job listings, user profiles, articles, and subscriptions all have very different shapes&lt;br&gt;
&lt;strong&gt;Caching&lt;/strong&gt;: Redis =&amp;gt; Implemented SWR (Stale-While-Revalidate) caching to handle high traffic without overloading the database&lt;/p&gt;

&lt;p&gt;🧗 Challenges&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Building a Multi-Role System from Scratch&lt;br&gt;
Infoloker isn't just one app — it's three. Job seekers browse and apply, employers post and manage listings, and admins moderate everything. Each role has its own dashboard, permissions, and data flow. Designing the auth middleware to cleanly separate these roles without duplicating code was one of the hardest architectural decisions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Making Applications Feel Personal (Email Delivery)&lt;br&gt;
The core differentiator — sending applications via email — sounds simple, but getting it right was tricky. I had to handle email formatting, file attachments (CVs), error handling for invalid addresses, and rate limiting to prevent abuse. Making sure emails didn't land in spam folders was an ongoing battle.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Performance at Scale with Redis Caching&lt;br&gt;
Early on, the app was slow when loading job listings because every request hit the database. I implemented a Stale-While-Revalidate (SWR) caching pattern with Redis — the frontend shows cached data instantly while the backend refreshes it in the background. This dramatically improved perceived performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Security Hardening&lt;br&gt;
As a job platform handling personal data (CVs, emails, phone numbers), security couldn't be an afterthought. I implemented:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Helmet for HTTP security headers&lt;br&gt;
Rate limiting to prevent brute-force attacks&lt;br&gt;
MongoDB sanitization to prevent NoSQL injection&lt;br&gt;
HPP (HTTP Parameter Pollution) protection&lt;br&gt;
Input validation with Yup on every endpoint&lt;br&gt;
HTML sanitization to prevent XSS in rich-text content&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Payment Integration&lt;br&gt;
Integrating Midtrans for premium subscriptions meant handling webhooks, payment verification, subscription expiry via cron jobs, and graceful error states — all while keeping the UX smooth.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deployment &amp;amp; DevOps&lt;br&gt;
Deploying a full-stack app across two platforms (Fly.io + Vercel) introduced challenges: CORS configuration, environment variable management, Docker containerization for the backend, and ensuring the SPA routing worked correctly on Vercel.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;✅ Results&lt;br&gt;
Full-stack production app deployed and live&lt;br&gt;
3 user roles with dedicated dashboards (Job Seeker, Employer, Admin)&lt;br&gt;
Direct-to-email applications — the core differentiator&lt;br&gt;
Premium subscription system with real payment integration&lt;br&gt;
Article/blog CMS with rich text editing&lt;br&gt;
Real-time notifications for application updates&lt;br&gt;
Analytics dashboard for admins with Recharts visualization&lt;br&gt;
Multi-language support (Indonesian &amp;amp; English)&lt;br&gt;
Redis-powered caching for fast page loads&lt;br&gt;
Comprehensive security middleware stack&lt;/p&gt;

&lt;p&gt;here's the link: &lt;a href="https://lokerbaru.id" rel="noopener noreferrer"&gt;https://lokerbaru.id&lt;/a&gt;&lt;br&gt;
and also here several screenshots of my project:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjreny44231kq2h4c3vxl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjreny44231kq2h4c3vxl.png" alt=" " width="800" height="1625"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F16o0of51s3ii02a8dpe9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F16o0of51s3ii02a8dpe9.png" alt=" " width="800" height="1625"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F33mmidwyf8mycvdjv9ih.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F33mmidwyf8mycvdjv9ih.png" alt=" " width="800" height="1625"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqtzblojrr6dcbex7b2e8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqtzblojrr6dcbex7b2e8.png" alt=" " width="800" height="1625"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqqmh104ekuyz19csqag6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqqmh104ekuyz19csqag6.png" alt=" " width="800" height="1625"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>programming</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
