\n
Hang up… please wait, we're loading
Databases, authentication, REST APIs, Firebase, Node.js, and serverless — how the internet actually stores and secures your data.
Backends live on servers — you talk to them via HTTP requests.
The backend is the engine room of your app — it processes requests, talks to databases, handles authentication, and sends data back to the browser.
The frontend is what users see. The backend is the server-side code that stores data, handles authentication, runs business logic, and sends data to the frontend via APIs.
Browser renders HTML/CSS/JS. Sends requests. Shows data from backend.
The bridge. Frontend calls API endpoints, backend processes and responds with JSON.
Server code. Reads/writes database, validates data, handles auth, runs business logic.
Node.js runs JavaScript on the server. Express is the most popular Node.js framework for building APIs.
# Create project folder mkdir my-api && cd my-api # Initialize Node.js project npm init -y # Install Express npm install express # Install dev tools npm install -D nodemon # auto-restart on file changes # Add to package.json scripts: # "dev": "nodemon server.js" # Start dev server npm run dev
A REST API is a set of URL endpoints your frontend can call to create, read, update, and delete data (CRUD).
const express = require('express'); const app = express(); // Middleware: parse JSON bodies app.use(express.json()); // CORS: allow frontend to call this API app.use((req, res, next) => { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization'); next(); }); // In-memory "database" (use a real DB in production) let posts = [ { id: 1, title: 'Hello World', author: 'Alice' }, { id: 2, title: 'My Second Post', author: 'Bob' }, ]; // GET all posts app.get('/api/posts', (req, res) => { res.json({ success: true, data: posts }); }); // GET single post by ID app.get('/api/posts/:id', (req, res) => { const post = posts.find(p => p.id === +req.params.id); if (!post) return res.status(404).json({ error: 'Not found' }); res.json({ success: true, data: post }); }); // POST create a post app.post('/api/posts', (req, res) => { const { title, author } = req.body; if (!title || !author) { return res.status(400).json({ error: 'title and author required' }); } const newPost = { id: posts.length + 1, title, author }; posts.push(newPost); res.status(201).json({ success: true, data: newPost }); }); // PUT update a post app.put('/api/posts/:id', (req, res) => { const idx = posts.findIndex(p => p.id === +req.params.id); if (idx === -1) return res.status(404).json({ error: 'Not found' }); posts[idx] = { ...posts[idx], ...req.body }; res.json({ success: true, data: posts[idx] }); }); // DELETE a post app.delete('/api/posts/:id', (req, res) => { posts = posts.filter(p => p.id !== +req.params.id); res.json({ success: true, message: 'Deleted' }); }); // Start server app.listen(3000, () => console.log(' API running at http://localhost:3000') );
Data in tables with rows & columns. Strict schema. Relationships via JOINs. Best for structured data.
Data as JSON documents. Flexible schema. Scales easily. Best for dynamic data.
Firebase Firestore is Google's cloud NoSQL database. It's free to start, has real-time sync, and works directly from the browser — no backend server needed!
// 1. Install Firebase SDK // npm install firebase import { initializeApp } from 'firebase/app'; import { getFirestore, collection, addDoc, getDocs, doc, updateDoc, deleteDoc, onSnapshot, query, where, orderBy } from 'firebase/firestore'; // 2. Initialize (from Firebase Console → Project Settings) const app = initializeApp({ apiKey: process.env.VITE_FIREBASE_API_KEY, authDomain: 'your-app.firebaseapp.com', projectId: 'your-app-id', }); const db = getFirestore(app); // 3. Add a document async function addPost(title, content) { const docRef = await addDoc(collection(db, 'posts'), { title, content, createdAt: new Date(), likes: 0 }); console.log('Added with ID:', docRef.id); } // 4. Get all documents async function getPosts() { const snapshot = await getDocs(collection(db, 'posts')); return snapshot.docs.map(d => ({ id: d.id, ...d.data() })); } // 5. Real-time listener (auto-updates when data changes!) onSnapshot(collection(db, 'posts'), (snapshot) => { const posts = snapshot.docs.map(d => ({ id: d.id, ...d.data() })); renderPosts(posts); // update your UI }); // 6. Query with filters const q = query( collection(db, 'posts'), where('likes', '>', 10), orderBy('createdAt', 'desc') ); // 7. Update a document await updateDoc(doc(db, 'posts', postId), { likes: 11 }); // 8. Delete a document await deleteDoc(doc(db, 'posts', postId));
Authentication = proving who you are. Authorization = what you're allowed to do. In 2026, the gold standard is using OAuth instead of storing passwords yourself.
Firebase Auth lets you add secure sign-in to your app in minutes. Support Google, GitHub, email/password, and more — all with a few lines of code.
import { getAuth, signInWithPopup, GoogleAuthProvider, createUserWithEmailAndPassword, signInWithEmailAndPassword, signOut, onAuthStateChanged } from 'firebase/auth'; const auth = getAuth(app); const provider = new GoogleAuthProvider(); // === Google Sign-In (one-click!) === async function signInWithGoogle() { const result = await signInWithPopup(auth, provider); const user = result.user; console.log('Signed in as:', user.displayName, user.email); // user.uid = unique user ID, use this in Firestore } // === Email + Password Sign Up === async function signUp(email, password) { const userCredential = await createUserWithEmailAndPassword(auth, email, password); return userCredential.user; } // === Email + Password Login === async function login(email, password) { const { user } = await signInWithEmailAndPassword(auth, email, password); return user; } // === Sign Out === const logout = () => signOut(auth); // === Listen to auth state (runs on every page) === onAuthStateChanged(auth, (user) => { if (user) { // User is logged in console.log('Logged in:', user.uid); document.getElementById('user-name').textContent = user.displayName; document.getElementById('login-btn').style.display = 'none'; document.getElementById('logout-btn').style.display = 'block'; } else { // User is logged out document.getElementById('login-btn').style.display = 'block'; } }); // === Firestore Security Rules === // In Firebase Console → Firestore → Rules: // rules_version = '2'; // service cloud.firestore { // match /databases/{db}/documents { // match /posts/{id} { // allow read: if true; // anyone can read // allow write: if request.auth != null; // only logged-in users // } // } // }
OAuth lets users log in with existing accounts (Google, GitHub, Twitter). You never store their password — the provider handles it.
Clerk.com is the 2026 favorite for Next.js apps — beautiful pre-built UI, zero config, free tier.
npm install @clerk/nextjs
Serverless functions let you run backend code without managing a server. You pay only when the function runs (often free for small apps).
// File: /api/send-email.js (Vercel auto-routes this) export default async function handler(req, res) { if (req.method !== 'POST') { return res.status(405).json({ error: 'Method not allowed' }); } const { name, email, message } = req.body; // Send email with Resend.com (free 3000 emails/month) const response = await fetch('https://api.resend.com/emails', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.RESEND_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ from: 'noreply@yourdomain.com', to: 'you@yourdomain.com', subject: `New message from ${name}`, html: `<p><strong>From:</strong> ${email}</p><p>${message}</p>` }) }); if (!response.ok) { return res.status(500).json({ error: 'Email failed' }); } res.json({ success: true, message: 'Email sent!' }); }
API keys and secrets must NEVER be in your frontend code or committed to git. Use environment variables.
# File: .env (NEVER commit this to git!) # Add ".env" to your .gitignore file FIREBASE_API_KEY=AIzaSy... FIREBASE_PROJECT_ID=my-app-123 RESEND_API_KEY=re_abc123... STRIPE_SECRET_KEY=sk_live_... DATABASE_URL=postgresql://user:pass@host/db # In Node.js, access via: # process.env.FIREBASE_API_KEY # In Vite (frontend), prefix with VITE_: # VITE_FIREBASE_API_KEY=... → import.meta.env.VITE_FIREBASE_API_KEY ## .gitignore — protect your secrets ## node_modules/ .env .env.local .env.production dist/ .DS_Store
Build a blog with: