NodeCraft Academy

Master backend development with hands-on REST API mentoring from an experienced full-stack JavaScript engineer. Weekly live sessions, code r...
Clark Freeport Zone, PH
Created byProfile picturepettymarshal3e
2 joined
Profile picture
@pettymarshal3eProfile pictureJun 7
Pinned post

Welcome to NodeCraft Academy — Read This First

Hey — welcome aboard. Seriously glad you're here.


This isn't a passive video course you forget about in a week. This is a weekly mentorship where you'll build production-grade REST APIs from scratch, get real feedback, and ship code that actually matters on a resume.


Here's how this works


  1. Follow the course in order. Each week builds on the last. Don't skip ahead — the foundations matter more than you think.

  2. Write every line of code yourself. Copy-pasting teaches you nothing. Type it out, break it, fix it.

  3. Use the Community Chat. Ask questions, share your progress, help others. The best developers I've mentored were the ones who engaged.

  4. Complete every assignment. Each lesson ends with a practical task. These aren't optional — they're where the real learning happens.


What you'll build by the end


A fully deployed REST API with:

  • JWT authentication & role-based access control

  • MongoDB with Mongoose ODM

  • Input validation, error handling, rate limiting

  • Automated tests with Jest & Supertest

  • Swagger documentation

  • Deployed to production on Railway or Render


This is the exact stack companies are hiring for right now.


My commitment to you


I'm here to make sure you don't just learn backend development — you become a backend developer. If you're stuck, post in the chat. I respond to everything.


Let's build.

Profile picture
@pettymarshal3eProfile pictureJun 7

5 Express.js Middleware Patterns Every Backend Dev Should Know

Most junior devs use Express middleware without really understanding it. Here are 5 patterns that separate beginners from production-ready engineers.


1. Request Logging with Context


Don't just log the route — log what matters for debugging:


const requestLogger = (req, res, next) => {
  const start = Date.now();
  const requestId = crypto.randomUUID();
  req.requestId = requestId;

  res.on('finish', () => {
    console.log(JSON.stringify({
      requestId,
      method: req.method,
      path: req.originalUrl,
      status: res.statusCode,
      duration: Date.now() - start + 'ms',
      ip: req.ip,
      userAgent: req.get('User-Agent')
    }));
  });

  next();
};


The res.on('finish') trick lets you log the response status code, not just the request. This is how production APIs do it.


2. Async Error Wrapper


Express doesn't catch async errors by default. This one-liner fixes it:


const asyncHandler = (fn) => (req, res, next) =>
  Promise.resolve(fn(req, res, next)).catch(next);

// Usage
app.get('/users/:id', asyncHandler(async (req, res) => {
  const user = await User.findById(req.params.id);
  if (!user) throw new AppError('User not found', 404);
  res.json(user);
}));


Without this, your server silently swallows errors and clients get hung connections. I've seen this crash production apps.


3. Rate Limiting Per Route


Global rate limiting is lazy. Protect sensitive routes differently:


const rateLimit = require('express-rate-limit');

const authLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 5,
  message: { error: 'Too many login attempts. Try again in 15 minutes.' }
});

const apiLimiter = rateLimit({
  windowMs: 60 * 1000,
  max: 100
});

app.use('/api/auth/login', authLimiter);
app.use('/api/', apiLimiter);


Login gets 5 attempts per 15 minutes. General API gets 100/min. This is how you prevent brute-force attacks without annoying normal users.


4. Response Envelope Middleware


Consistent API responses make frontend devs love you:


const responseEnvelope = (req, res, next) => {
  const originalJson = res.json.bind(res);

  res.json = (data) => {
    originalJson({
      success: res.statusCode < 400,
      data: res.statusCode < 400 ? data : undefined,
      error: res.statusCode >= 400 ? data : undefined,
      timestamp: new Date().toISOString(),
      requestId: req.requestId
    });
  };

  next();
};


Every response now has the same shape. No more guessing on the frontend.


5. Graceful 404 + Error Handler Combo


Always define these last, in this order:


// 404 — catches unmatched routes
app.use((req, res, next) => {
  next(new AppError(`Cannot ${req.method} ${req.originalUrl}`, 404));
});

// Global error handler — must have 4 params
app.use((err, req, res, next) => {
  const status = err.statusCode || 500;
  res.status(status).json({
    error: err.message,
    ...(process.env.NODE_ENV === 'development' && { stack: err.stack })
  });
});


The 404 middleware turns missed routes into proper errors. The error handler catches everything — including those async errors from pattern #2.


---


These aren't clever tricks — they're standard production patterns. If you're building APIs without them, your code has gaps.


I teach all of this (and a lot more) in my REST API mentorship. Link's on my page if you want to go deeper.