raihan@fullstack:~$
Available · --:--
ngejoblist
$ cat README.md
# Ngejoblist
Job-platform backend built with NestJS, Prisma, PostgreSQL, JWT auth, Cloudinary uploads, Winston logging, and Swagger documentation.
$ tree --dirsfirst -L 2
.
├── src/
│ ├── controllers/
│ ├── services/
│ ├── models/
│ └── middleware/
├── prisma/
├── docker-compose.yml
└── package.json
$ docker compose ps
NestJS 10
TypeScript
Prisma ORM
PostgreSQL
JWT
Cloudinary
Winston
Swagger
Zod
Jest
Category
Internship Requirement
Year
2024
Stack
10 technologies

Ngejoblist

NestJS 10TypeScriptPrisma ORMPostgreSQLJWTCloudinaryWinstonSwaggerZodJest

Overview

Ngejoblist was built as a technical requirement for an internship application. The task was to build a job platform backend using NestJS, demonstrating production-style API structure, authentication, and business logic. This project pushed me beyond coursework into building something that resembled a real product.

Problem

  • The internship application required a technical demonstration — not just a resume, but a working backend system
  • I needed to prove I could build production-style APIs with authentication, authorization, and complex business logic
  • The job platform domain required handling multiple entities: companies, jobs, applications, and users

Goal

  • Build a job platform backend that demonstrates NestJS best practices
  • Implement JWT authentication with role-based access control
  • Add Cloudinary integration for image uploads
  • Document every endpoint with Swagger

Role

I built the entire backend independently.

Team: Achmad Raihan Fahrezi Effendy (Backend Developer)

Architecture

flowchart TD A["NestJS 10 App"] --> B["Auth Module"] A --> C["Users Module"] A --> D["Companies Module"] A --> E["Jobs Module"] A --> F["Applications Module"] B --> G["JWT Guards"] C --> H["Prisma ORM"] D --> H E --> H F --> H H --> I[("PostgreSQL")] J["Cloudinary"] --> E K["Winston Logger"] --> A L["Swagger"] --> A
LayerTechnologyPurpose
FrameworkNestJS 10Modular backend structure
AuthJWT (passport-jwt)Authentication and authorization
ORMPrismaSchema-driven data access
DatabasePostgreSQLPersistent storage
UploadsCloudinaryImage storage and optimization
LoggingWinston + daily-rotate-fileStructured logging with rotation
DocsSwagger (@nestjs/swagger)Interactive API documentation
Rate Limiting@nestjs/throttlerAPI rate limiting
ValidationZodSchema validation
TestingJest + SupertestUnit and integration tests

Key Features

  • JWT Authentication — Register, login, and token refresh with bcrypt password hashing
  • Role-Based Access — Separate permissions for job seekers, companies, and administrators
  • Job Management — CRUD operations for job postings with filtering and search
  • Application System — Job seekers can apply, companies can review applications
  • Image Uploads — Cloudinary integration for company logos and job images
  • Rate Limiting — Throttler middleware to prevent abuse
  • Structured Logging — Winston with daily log rotation
  • Swagger Docs — Interactive API documentation for every endpoint

Technical Decisions

  • NestJS was chosen because the internship required it — this was the project that made me proficient with the framework
  • Prisma was used for schema-first development and type-safe database queries
  • Cloudinary was chosen for image uploads to avoid managing file storage infrastructure
  • Winston with daily rotation was added for production-ready logging

Challenges

  • Understanding NestJS modules, providers, and dependency injection took significant time
  • Designing the application flow between job seekers and companies required careful schema planning
  • Building something that felt “production-ready” without actual production deployment was a mental shift

Outcome

The project was submitted as part of the internship application and demonstrated production-style backend skills. It became the foundation for my NestJS proficiency and influenced how I approach API design.

Final Thoughts

Ngejoblist taught me that building for a requirement is different from building for yourself. When the stakes are higher, the code needs to be cleaner, the decisions need to be more deliberate, and the documentation needs to be more thorough. That discipline carried into every project after.

LET'S CONNECT

© 2026 Achmad Raihan Fahrezi Effendy MALANG · --:-- WIB