---
title: "Node.js + Vanilla JS Lightweight Tools"
aliases: [nodejs-proxy, vanilla-js, lightweight-tools]
tags: [nodejs, vanilla-js, proxy, lightweight, no-build]
sources: [01 Projects/3m-portal, 01 Projects/ferrero-ac-creator, 01 Projects/homepage]
created: 2026-04-15
updated: 2026-04-15
---

# Node.js + Vanilla JS Lightweight Tools

For simple client tools that don't need a frontend build step. Node.js serves static files and acts as a proxy for third-party APIs.

## Key Takeaways
- Use when: no React needed, no TypeScript, no build pipeline
- `server.js` does two things: serve static HTML/JS/CSS files + proxy `/api/*` to third-party APIs
- No Docker — just `node server.js` or `npm start`
- No transpilation, no bundling — open file in browser or hit localhost directly
- This pattern is for simple client-facing portals and utility tools

## When to Use
- Wrapping a third-party API that has CORS restrictions
- Small client portals (translation tools, booking tools)
- Rapid prototypes that don't need SSR or TypeScript

## Key Details

### server.js Structure
```js
const http = require('http')
const fs = require('fs')
const path = require('path')
const https = require('https')

const server = http.createServer((req, res) => {
  if (req.url.startsWith('/api/')) {
    // Proxy to third-party API
    proxyRequest(req, res)
  } else {
    // Serve static files
    serveStatic(req, res)
  }
})
server.listen(3000)
```

### CORS Proxy Behavior (3M Portal)
- Strips/rewrites `Location` headers on 301/302 → returns 401 (prevents auth redirect loops)
- Injects CORS headers on all `/api` responses
- Masks sensitive data (passwords) in logs

## Projects Using This Pattern
- [[01 Projects/3m-portal/3M OMG Portal|3M OMG Portal]] — Node.js CORS proxy for One2Edit API (:3000)
- [[01 Projects/ferrero-ac-creator/Ferrero AC Booking Tool|Ferrero AC Booking]] — Node.js server for Box API + CSV download (:3456)
- [[01 Projects/homepage/Homepage Dashboard|Homepage Dashboard]] — Node.js static server for YAML-configured dashboard

## Comparison: When to Choose What
| Need | Choose |
|------|--------|
| No CORS issues, pure static | Open `index.html` directly (Ferrero "Download CSV" mode) |
| CORS proxy needed | `node server.js` |
| Auth + complex logic | FastAPI (Python) |
| SSR + complex routing | Next.js |

## Gotchas & Lessons
- `sessionStorage` (not `localStorage`) for auth tokens — clears on browser close (3M Portal)
- Always mask passwords in proxy logs
- 301/302 from API = auth failure in One2Edit — convert to 401 at proxy level
- These tools have no test suite — test manually

## Related
- [[wiki/tech-patterns/one2edit-api|one2edit-api]] — uses this proxy pattern
- [[wiki/tech-patterns/fastapi-python-docker|fastapi-python-docker]] — heavier alternative
