Stop exposing your secrets. How to properly secure .env in React.js A lot of developers still make these mistakes. Here's what you need to know: The #1 thing most people miss: React apps run in the browser. Anything in your .env file prefixed with REACT_APP_ gets bundled into your JavaScript and is publicly visible. Yes anyone can open DevTools and find it. Best practices to follow: 1- Never store secrets in .env for frontend React API keys, database credentials, payment secrets keep these server-side only. 2- Always add .env to .gitignore Commit .env.example (with empty values) and never push real values to GitHub. 3- Use environment variables only for public config Things like your API base URL or feature flags are fine — not your private keys. 4- Move sensitive logic to a backend (Node.js, Express, etc.) Let your backend handle API calls that need secret keys, then expose safe endpoints to your React app. 5- Validate your .env on startup Use a library like zod or envalid to catch missing variables early. 6- Use secrets managers in production AWS Secrets Manager, Vercel env vars, or Doppler are far safer than relying on flat files. #ReactJS #WebDevelopment #JavaScript #Security #Frontend #DevTips #SoftwareEngineering
Securing .env in React.js: Best Practices for Frontend Security
More Relevant Posts
-
🚀 Node.js 26: The Native Era & Supply Chain Security 🛡️ April 1, 2026 – Node.js 26.0.0 is officially here, and it’s a game-changer for how we build, deploy, and secure backend applications. We are moving from a reliance on external dependencies to a native-first runtime. Here’s why you need to upgrade and what’s new: The Top Three Changes You Need to Know 1. ⚡ Native Fetch & Web Streams: Standardized * The Change: No more external libraries like axios just to make an API call. fetch() and Web Streams are now native to Node.js, matching browser standards. * The Takeaway: Start refactoring your utilities. You get smaller bundles, reduced dependency overhead, and a unified coding experience from React to Node. 2. 🛡️ Production-Ready Permission Model * The Change: A comprehensive security model that allows you to strictly control what filesystem and network resources your Node process can access. * The Takeaway: This is your best defense against supply chain attacks. You must explicitly allow permissions at launch (e.g., node --allow-net=api.com app.js). If a single dependency is compromised, its malicious capabilities are severely contained. 3. 🧠 V8 Engine 14.1 Performance Boost * The Change: Lower latency "for free." This V8 update delivers immediate performance gains in JSON parsing and async execution—making microservices faster and debugging easier. 💡 The 2026 Decision: Native simplicity or third-party convenience? Are you moving your applications to native fetch and strict permissions immediately, or is your workflow still reliant on the ergonomics of the third-party ecosystem? Where do you stand? Discuss below. 👇 #NodeJS #BackendSecurity #TechNews #Javascript #SoftwareEngineering #WebDev #MERNStack #Programming
To view or add a comment, sign in
-
-
I just wanted to see localhost:3000. 😭 Clone repo → run app Simple, right? Nope. Now it’s: • Install Node 22.11.0 • Actually use Bun 🥖 • But only for local • Use pnpm, not npm • Run Docker 🐳 • Add 14 env vars • Clear cache • Delete node_modules • Pray 🙏 And after all that… The app still crashes because one package changed from 4.2.1 → 4.2.2 💀 2010: <script src="app.js"></script> 2026: bun run turbo dev --filter=web Which somehow starts: ⚡ Vite 📦 Next.js 🎨 Tailwind 🧠 TypeScript 🐶 Husky 🐳 Docker …and 7 background processes eating 6GB RAM for spiritual reasons 👻 The worst part? All these tools exist for a reason: • TypeScript catches bugs • Bun is faster • Docker fixes “works on my machine” • Monorepos help big teams We didn’t build a website. We built a tiny operating system wearing a login page. 🤡 And no matter how advanced the stack gets, the final fix is still: rm -rf node_modules Bun is generally faster, Node still has the biggest ecosystem, and Deno focuses on security-by-default — which is exactly why teams now juggle multiple runtimes instead of one. #WebDevelopment #Frontend #NextJS #JavaScript #SvelteKit #RemixRun #NuxtJS #SoftwareEngineering #DevCommunity #FullStack #TechTrends #ProgrammerHumor #OpenSource #ReactJS #ServerSideRendering
To view or add a comment, sign in
-
-
🚀 I recently completed the Next.js section from Jonas Schmedtmann’s Ultimate React Course 2025 and built this project while following along. As part of that, I developed “The Wild Oasis” — a production-style application focused on real-world architecture and authentication. 🔗 Live Demo: https://lnkd.in/dsX6jwGg 💡 What I implemented: • Full authentication system using Auth.js with Google OAuth • Protected routes, session management, and user dashboards • Next.js App Router with nested layouts and dynamic routing • Server Components & Server Actions for better performance • Error handling and loading states using Suspense ⚙️ Tech Stack: Next.js 16, Auth.js, Supabase, React 18 This part of the course really helped me understand how to build secure, scalable, production-ready applications with Next.js. #NextJS #React #WebDevelopment #Frontend #FullStack #JavaScript #AuthJS
To view or add a comment, sign in
-
I struggled with this React concept more than I expected… 👇 👉 Why are my API calls running twice? ⚙️ What you’ll notice You open your network tab and suddenly see this: api/me → called twice api/roles → called twice api/permissions → called twice Just like in the screenshot 👇 Same request, duplicated… again and again. ⚙️ What’s actually happening In React (development mode), if your app is wrapped in Strict Mode, React will run effects twice on purpose. useEffect(() => { fetch("/api/users") .then(res => res.json()) .then(setUsers); }, []); Even though it looks like it should run once… it doesn’t (in dev). 🧠 What’s going on under the hood React basically does a quick cycle: mount → unmount → remount Why? To catch hidden side effects To check if cleanup is handled properly To make sure your logic doesn’t break on re-renders So if your API call runs twice, React is just making sure your code can handle it. 💡 The important part This only happens in development Production behaves normally (runs once) Your side effects should be safe to run multiple times 🚀 Final thought If your network tab looks “noisy” like the screenshot, it’s not React being broken — it’s React being careful. And once you understand this, debugging becomes a lot less confusing. #React #Frontend #JavaScript #WebDevelopment #ReactJS #SoftwareEngineering
To view or add a comment, sign in
-
Most frontend apps are leaking their “secret” API keys… and don’t even know it 🚨 It usually starts with good intentions: 🔹 move keys to .env ✅ 🔹 add .gitignore ✅ 🔹 avoid hardcoding ✅ Feels like you’ve handled security. But here’s the reality 👇 In setups like Next.js, anything meant for the browser (like NEXT_PUBLIC_*) ends up inside your app during build time. So when your app runs: 📦 the key is inside your JS bundle 🔍 visible in DevTools ⚡ extractable The rule is simple: 👉 If it runs in the browser, it’s not a secret. What actually works 🛠️ 🔒 keep API keys on the server 🔁 call third-party APIs from backend 📤 send only required data to frontend (API routes, server actions, BFF => pick your style) Frontend can’t protect secrets. Your Architecture does. #Frontend #JavaScript #WebSecurity #ReactJS #CareerGrowth #WebDev #TechCareers
To view or add a comment, sign in
-
React re-render fixes React performance tips I learned the hard way over 8 years. Not from docs. From debugging slow UIs in production with real users waiting. Here are 5 things I wish someone told me on day one: 𝟭. Stop putting everything in one Context. I've seen apps where one global context holds auth, theme, user data, and cart state. Every update re-renders EVERYTHING. Split your contexts by update frequency. Auth rarely changes. Cart changes constantly. They shouldn't live together. 𝟮. useMemo and useCallback are not free. They have a cost — memory and comparison overhead. I've seen devs wrap every single function in useCallback "for performance." If the component isn't actually re-rendering unnecessarily, you're adding complexity for zero benefit. Profile first. Memoize second. 𝟯. Lazy load below the fold. On a banking platform, we had 40+ components loading on the dashboard. Users only saw 5 on first paint. We implemented React.lazy() + Suspense for everything below the fold. Page load dropped 35%. The trick: wrap lazy components in proper error boundaries, not just Suspense. 𝟰. Key prop abuse kills performance silently. Using array index as key in a list that reorders? React destroys and recreates every DOM node instead of reordering them. On a data grid with 500+ rows, this was the difference between a 200ms and 3-second re-render. Use stable, unique IDs. 𝟱. State colocation > state management libraries. Before reaching for Redux, ask: does this state need to be global? I've refactored apps where 60% of Redux state was only used by one component. Moving state closer to where it's used eliminated 45% of unnecessary re-renders in one project. The fastest React app isn't the one with the cleverest optimization. It's the one that avoids unnecessary work in the first place. What's a React performance lesson you learned the hard way? #ReactJS #JavaScript #FrontendDevelopment #WebPerformance #TypeScript #SoftwareEngineering
To view or add a comment, sign in
-
🚨 Modern JavaScript & React — Just because it works today doesn’t mean it will work tomorrow. With the latest updates in Next.js routing (App Router) and API data fetching in React, things have become more powerful — but also more complex. We’ve moved from: ➡️ Simple fetch calls in components ➡️ To Server Components, Route Handlers, caching layers, and streaming And here’s where many developers get it wrong: They copy what works without understanding: When data is cached vs revalidated The difference between server and client components Why a fetch request works locally but breaks in production How routing behavior changes across versions 💡 Reality check: Your app may run perfectly today… Then suddenly fail after deployment, scaling, or even a minor framework update. That’s not bad luck — it’s a lack of deep understanding. 🔥 The best developers don’t just write code that works… They understand why it works. Because in modern JavaScript: 👉 “Working” is temporary 👉 “Understanding” is permanent FREE API - https://cngapi.netlify.app #JavaScript #ReactJS #NextJS #WebDevelopment #Frontend #APIs #SoftwareEngineering #DevTips
To view or add a comment, sign in
-
-
🔁 𝗤𝘂𝗶𝗰𝗸 𝗥𝗲𝗰𝗮𝗽: API Integration Errors in React — Because We All Google These Anyway Let's be honest — no matter how long you've been writing React, API integration errors have a way of showing up unannounced and ruining a perfectly good Tuesday. This is just a quick, no-fluff refresher. Whether you're six months in or six years in, a fast recap never hurts anyone. Here are the most common ones we run into: ❌ CORS Errors The classic. Your API call works in Postman, breaks in the browser. Almost always a backend config issue — but knowing why it happens saves you 30 minutes of self-doubt. ❌ 401 & 403 — Unauthorized / Forbidden Either your token is missing, expired, or you're hitting an endpoint your role doesn't have access to. Always check headers first before assuming the API is broken. ❌ Network Error / Failed to Fetch Could be the server is down, wrong base URL, or you forgot to handle the case where the user is offline. axios and fetch behave differently here — worth knowing the distinction. ❌ Race Conditions with useEffect You fire two API calls, the slower one resolves last and overwrites the correct data. A simple cleanup function or AbortController fixes this cleanly. ❌ Unhandled Promise Rejections Missing a .catch() or forgetting try/catch in an async function. These silently fail in production and are painful to debug. ❌ Stale Closures in Async Calls Your state inside an async function is a snapshot from when it was created — not the current value. Classic React gotcha that trips up everyone at least once. The goal isn't to teach — it's just to keep these top of mind. Sometimes the best learning is a 2-minute scroll that reminds you of something you already knew. Drop the one that's bitten you the most recently 👇 — curious if Race Conditions are as universal as I think they are 😄 #React #Frontend #WebDevelopment #JavaScript #APIIntegration #ReactJS #FrontendDeveloper #LearningInPublic
To view or add a comment, sign in
-
Every Node.js app eventually hits "I need rate limiting." You Google it. You find express-rate-limit. You install it. Then you realize: → It only works with Express → You also have a Next.js Edge route → And a React frontend making too many API calls → Oh, and you need Redis for production So now you're stitching 4 different libraries together. 😅 That's exactly why I built limiterx. One package. Every runtime. ✅ Express, Koa, Node HTTP ✅ Next.js API routes + Edge Middleware ✅ React hook for client-side throttling ✅ Fetch + Axios wrappers ✅ Redis store out of the box ✅ 3 algorithms: fixed-window, sliding-window, token-bucket And it ships with zero runtime dependencies. Tree-shakeable. TypeScript-first. Works on Node, browsers, Edge, and Bun. Getting started is literally this: npm install limiterx Then: app.use(rateLimitExpress({ max: 100, window: '15m' })) That's it. If you're building anything in JS/TS that talks to an API — this is for you. 🔗 npm: https://lnkd.in/gxbf3Jxt 🐙 GitHub: https://lnkd.in/gxt-RAi3 Drop a ⭐ if this saves you a headache. And share with anyone building Node apps — they'll thank you. #nodejs #javascript #typescript #webdev #opensource #ratelimiting #nextjs #developer
To view or add a comment, sign in
-
Is Redux feeling a bit "heavy" lately? Enter Zustand. 🐻 If you're tired of writing endless boilerplate just to update a single piece of state, it’s time to look at Zustand. Zustand (German for "state") is a small, fast, and scalable state-management solution that uses simplified Flux principles but with a much friendlier API. Why choose Zustand over Redux? ✅ Zero Boilerplate: No more reducers, actions, or types folders. Just define your store and use it. ✅ No Providers: You don’t need to wrap your entire app in a <Provider />. The store is just a hook! ✅ Performance: It only re-renders components when the specific state they use changes—no "zombie child" problems or unnecessary updates. ✅ Simple Async: Handling async actions is as easy as writing a normal function. Zustand vs. Redux in a nutshell: Redux: Opinionated, robust, but requires a lot of setup. Great for massive, complex enterprise apps. Zustand: Un-opinionated, lightweight, and gets you running in seconds. Perfect for most modern React projects. Have you made the switch yet? Let’s discuss in the comments! 👇 #ReactJS #WebDevelopment #JavaScript #StateManagement #Zustand #Redux #Frontend
To view or add a comment, sign in
-
More from this author
Explore related topics
- How to Ensure API Security in Development
- Front-end Development with React
- API Security Best Practices
- Best Practices for Browser Security
- Tips for Improving Security in Software Development
- Ensuring Data Privacy in API Development
- Best Practices for Developer-Driven Security
- Best Practices for DEVOPS and Security Integration
- How to Secure a Development Environment
- Coding Best Practices to Reduce Developer Mistakes
Explore content categories
- Career
- Productivity
- Finance
- Soft Skills & Emotional Intelligence
- Project Management
- Education
- Technology
- Leadership
- Ecommerce
- User Experience
- Recruitment & HR
- Customer Experience
- Real Estate
- Marketing
- Sales
- Retail & Merchandising
- Science
- Supply Chain Management
- Future Of Work
- Consulting
- Writing
- Economics
- Artificial Intelligence
- Employee Experience
- Workplace Trends
- Fundraising
- Networking
- Corporate Social Responsibility
- Negotiation
- Communication
- Engineering
- Hospitality & Tourism
- Business Strategy
- Change Management
- Organizational Culture
- Design
- Innovation
- Event Planning
- Training & Development
Great tips, makes sense to keep secrets safe from prying eyes!