DEV Community

Mittal Technologies
Mittal Technologies

Posted on

From Localhost to Production: A Developer's Website Hardening Checklist for 2026


Every developer has that moment. You've been running the app on localhost for weeks, everything's fine, .env files are loose, CORS is wide open because who cares, it's just you and your terminal. Then deploy day comes and suddenly all that comfortable looseness becomes a liability. This developer's website hardening checklist for 2026 is basically the list we run through every single time before flipping something from dev mode to production, because muscle memory alone isn't enough anymore.

I say this as someone who's shipped that exact .env file to a public repo before. Once. Never again but once was enough to build this checklist out properly instead of trusting memory.

For context, this list comes out of running deploys for a website development company Ludhiana clients hire specifically because we treat this stuff as process, not vibes. Doesn't matter how experienced the individual dev is, checklists catch what tired brains miss at 2 AM before a launch.

Environment Variables: The Boring Check That Saves You

First thing, always: grep your entire codebase for anything that looks like a secret before you even think about deploying.

grep -rn "API_KEY\|SECRET\|PASSWORD\|TOKEN" --include="*.js" --include="*.ts" .
Enter fullscreen mode Exit fullscreen mode

This catches the obvious stuff, but the sneakier problem in 2026 is framework specific. If you're on Next.js, double-check that anything without the NEXT_PUBLIC_ prefix genuinely isn't referenced anywhere in client-side code. It's an easy mistake to make when you're refactoring fast and forget which file runs where.

// This leaks to the browser bundle if used client-side
const dbPassword = process.env.DB_PASSWORD; // fine in API routes, disaster in components

// This is the safe pattern for anything the client legitimately needs
const publicKey = process.env.NEXT_PUBLIC_API_KEY;
Enter fullscreen mode Exit fullscreen mode

CORS: Localhost Habits Don't Survive Production

On localhost, it's tempting to just slap Access-Control-Allow-Origin: * on everything and move on with building features. That habit needs to die before deploy.

// Localhost comfort, production liability
app.use(cors({ origin: "*" }));

// What should actually ship
app.use(cors({
  origin: process.env.NODE_ENV === "production"
    ? ["https://yourdomain.com"]
    : ["http://localhost:3000"],
  credentials: true
}));
Enter fullscreen mode Exit fullscreen mode

I've seen this exact wildcard survive into production more times than I'd like to admit, usually because it got set during early testing and nobody circled back to tighten it. It's worth adding a pre-deploy grep for this pattern specifically.

Rate Limiting Isn't Optional Anymore

This one didn't used to make every checklist, but with AI-driven scraping and credential stuffing attempts up significantly this year, it's non-negotiable now. Even a basic implementation goes a long way.

import rateLimit from "express-rate-limit";

const limiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 100,
  message: "Too many requests, slow down."
});

app.use("/api/", limiter);
Enter fullscreen mode Exit fullscreen mode

Pair this with stricter limits specifically on auth routes, since login endpoints are the most common target for automated attempts.

Database Query Safety: Still the Classic Mistake

SQL injection feels like a solved problem until you find it in a client's supposedly modern codebase. It usually hides in places nobody thought to check, like a search feature bolted on late in development.

// Vulnerable, still shows up more than you'd expect
const query = `SELECT * FROM users WHERE email = '${userInput}'`;

// Parameterized, the way it should always be written
const query = "SELECT * FROM users WHERE email = $1";
db.query(query, [userInput]);
Enter fullscreen mode Exit fullscreen mode

If you're on an ORM like Prisma or Drizzle, this risk drops significantly by default, but raw queries still creep in during performance optimization work, so it's worth a manual scan before shipping. Honestly, this is the kind of thing any decent web developer Ludhiana team should be scanning for reflexively, ORM or not.

Authentication Token Storage

Storing JWTs in localStorage is convenient and also a genuinely bad idea for anything handling sensitive data. It's vulnerable to XSS in ways httpOnly cookies simply aren't.

// Convenient but vulnerable to XSS token theft
localStorage.setItem("token", jwt);

// Safer approach
res.cookie("token", jwt, {
  httpOnly: true,
  secure: true,
  sameSite: "strict"
});
Enter fullscreen mode Exit fullscreen mode

I get why localStorage is tempting, it's simpler to work with in a lot of frontend setups. It's just not worth the tradeoff once real user data is involved.

Headers You're Probably Missing

Security headers are cheap to add and genuinely useful. This is one of those checks that takes five minutes and prevents entire categories of attack.

app.use((req, res, next) => {
  res.setHeader("X-Content-Type-Options", "nosniff");
  res.setHeader("X-Frame-Options", "DENY");
  res.setHeader("Strict-Transport-Security", "max-age=31536000; includeSubDomains");
  next();
});
Enter fullscreen mode Exit fullscreen mode

If you're on Next.js, this can go in next.config.js instead, which is cleaner and easier to maintain across the whole app. A clean, well-structured web design in Ludhiana teams often build from scratch tends to make this kind of config easier to audit too, versus a messy patchwork of inherited templates and plugins.

Dependency Audit Before Every Deploy

Run this before every production push, not just occasionally.

npm audit --production
Enter fullscreen mode Exit fullscreen mode

Fix what's flagged as high or critical severity at minimum. It's tedious, sure, but outdated dependencies are consistently one of the top causes of breaches we've had to clean up after the fact. This kind of gap is exactly what a proper cybersecurity audit should catch if your own process misses it.

Working With Someone Outside Your Own Codebase

Even with a solid personal checklist, there's real value in bringing in outside review before anything customer-facing goes live. It's not about the code being bad, it's about blind spots that come from staring at the same codebase for weeks straight. A second review from a cyber security company in Ludhiana or wherever your team's based tends to catch the stuff you've genuinely stopped seeing.

Final Thought

None of this is exciting work. It's grep commands and header configs and double-checking things you're pretty sure you already did right. But localhost forgives sloppiness in ways production never does, and the gap between "works on my machine" and "safe in production" is exactly where these checks live.
Ship carefully. The bots are definitely watching your DNS propagate.

Top comments (0)