Build a Blog from Scratch

Stack: HTML + CSS + JavaScript

Build a Blog from Scratch: Vanilla JavaScript Tutorial

Master web fundamentals by building a complete blog with pure HTML, CSS, and JavaScriptโ€”no frameworks needed. This tutorial teaches core web development concepts including DOM manipulation, local storage, and dynamic content rendering. Perfect for beginners learning JavaScript or developers wanting to understand what frameworks do under the hood.

What You'll Build

  • Fully functional blog with posts and categories
  • Dynamic content loading with vanilla JavaScript
  • Local storage for data persistence
  • Responsive design with pure CSS
  • Markdown-like formatting for posts
  • Search and filter functionality

Core Web Development Skills You'll Learn

  • DOM Manipulation: Create, read, update, delete elements with JavaScript
  • Event Handling: User interactions without jQuery
  • Local Storage API: Client-side data persistence
  • CSS Flexbox & Grid: Modern responsive layouts
  • JavaScript Modules: Organize code without build tools
  • Template Literals: Dynamic HTML generation
  • Array Methods: Filter, map, and reduce for data manipulation

Prerequisites

  • Basic HTML knowledge (tags, attributes, structure)
  • CSS fundamentals (selectors, properties, box model)
  • JavaScript basics (variables, functions, conditionals)
  • Code editor (VS Code recommended)
  • Modern web browser with developer tools

Time Commitment: 4-6 hours. Perfect weekend project to solidify your JavaScript fundamentals.

Why Learn Vanilla JavaScript?

Before reaching for React, Vue, or Angular, understanding vanilla JavaScript is crucial. Frameworks come and go, but core JavaScript skills remain valuable. Building without frameworks teaches you how the web actually worksโ€”DOM APIs, event loops, and browser capabilities. This knowledge makes you a better developer regardless of which framework you eventually use.

This tutorial focuses on modern JavaScript (ES6+) features and best practices. You'll write clean, maintainable code that runs directly in the browserโ€”no build step, no dependencies, just pure web development. Learn more about modern JavaScript features.

Build a Blog from Scratch

Build a blog the old-school way with pure HTML, CSS, and vanilla JavaScript - no frameworks, no dependencies, no complexity. This approach strips away all the abstractions to reveal the fundamental web technologies that power everything. You will gain deep understanding of the DOM, CSS layouts, event handling, and client-side storage while creating a fully functional blog. Perfect for learning the foundations, understanding what frameworks do under the hood, or when you need a lightweight solution that loads instantly and runs anywhere without a build step.

Web Development Blog Setup: Installation and Project Configuration

1

Create project folder structure

You will create a clean folder structure for your vanilla JS blog - no frameworks, just pure code you understand completely.
AI Prompt
Create a well-organized folder structure for a vanilla HTML/CSS/JavaScript blog

Set up the following directories: root directory with index.html, /css for stylesheets (style.css, reset.css), /js for JavaScript files (main.js, posts.js, utils.js), /data for blog post data (posts.json), /assets for images (images/, icons/), and /posts for individual post HTML pages

Initialize a git repository with git init and create a .gitignore file

Add a README.md with project description and setup instructions.
2

Configure VS Code with Live Server

You will set up VS Code with Live Server for instant browser refreshes - save a file, see the changes immediately.
AI Prompt
Configure VS Code for efficient vanilla web development

Install the Live Server extension by Ritwick Dey for hot-reloading during development

Add Prettier extension for code formatting and ESLint for JavaScript linting

Create .vscode/settings.json with formatting preferences (2-space indent, single quotes for JS, format on save enabled)

Install additional helpful extensions: HTML CSS Support, JavaScript (ES6) code snippets, Path Intellisense, and Auto Rename Tag

Configure Live Server settings to open on port 5500 and auto-refresh on file changes.
3

Create semantic HTML layout

You will build semantic HTML with proper tags like header, nav, and main - good structure from the start matters.
AI Prompt
Build a semantic HTML5 structure in index.html

Include proper doctype, html lang attribute, head section with meta charset UTF-8, viewport meta tag for responsiveness, title tag, and links to CSS files

Create semantic structure with <header> containing site logo and navigation <nav>, <main> with <section> for blog post listing, <aside> for sidebar (categories, recent posts, search), and <footer> with copyright and social links

Use semantic tags like <article> for blog posts, <time> for dates, <h1>-<h6> for headings hierarchy

Add proper ARIA labels for accessibility

Include meta tags for SEO (description, keywords, author).

Database and Environment Configuration for Web Development

4

Vanilla CSS or Tailwind CDN

You will choose between vanilla CSS for full control or Tailwind CDN for utility classes - no build tools needed.
AI Prompt
Choose between vanilla CSS or Tailwind CSS for styling

For vanilla CSS: create css/reset.css with CSS reset (normalize.css or custom reset), then css/style.css with CSS custom properties for colors, fonts, spacing, and breakpoints

Organize CSS with sections: global styles, typography, layout (header, nav, main, footer), components (cards, buttons, forms), and utilities

For Tailwind: add Tailwind CDN link in HTML head: <script src="https://cdn.tailwindcss.com"></script>, configure custom theme in a <script> tag if needed

Implement a mobile-first approach with clear responsive breakpoints. Choose a readable font stack with web-safe fallbacks (e.g., system-ui, -apple-system, "Segoe UI", Roboto, sans-serif).
5

Set up ES6 modules structure

You will organize your JavaScript with ES6 modules for clean code - async/await makes data fetching simple.
AI Prompt
Set up a modular JavaScript architecture using ES6 modules

Create js/main.js as the entry point with type="module" in the script tag

Build js/posts.js module for post-related functions (fetchPosts, renderPostList, renderSinglePost, filterPostsByCategory, sortPostsByDate)

Create js/utils.js for utility functions (formatDate, truncateText, slugify, escapeHTML, debounce)

Use export/import syntax to organize code

Implement async/await for data fetching

Add error handling with try/catch blocks

Set up event delegation for dynamic content

Include comments and JSDoc annotations for better code documentation

Ensure compatibility with modern browsers (ES6+).
6

Choose JSON file or localStorage

You will use JSON files as your blog database - fetch API loads everything without needing a backend.
AI Prompt
Choose and implement a data storage solution for blog posts. Option 1 (JSON file): Create data/posts.json with an array of post objects, each containing id, title, slug, author, date (ISO format), excerpt, content (markdown or HTML), category, tags, and featuredImage. Fetch data using fetch() API in JavaScript. Option 2 (localStorage): Store posts in localStorage with a "blogPosts" key, implement functions to addPost(), getPost(id), getAllPosts(), updatePost(id), deletePost(id)

For demo purposes, create a seed data script that populates initial posts. Structure each post with unique IDs, timestamps, and all necessary metadata

Consider using both: JSON for initial data, localStorage for user preferences (theme, viewed posts, bookmarks).

Building Blog Features: Core Functionality and Admin Panel

7

Build header, main, footer sections

You will build a sticky header and responsive layout with CSS Grid or Flexbox - post cards look great on any device.
AI Prompt
Build a complete page layout with header, main content, and footer. Header: Create a sticky/fixed navigation bar with site logo/title, navigation menu (Home, About, Categories, Contact), search input, and optional theme toggle (light/dark mode)

Style the header with flexbox or grid for alignment. Main: Design the main content area with a blog post grid/list using CSS Grid (3 columns on desktop, 2 on tablet, 1 on mobile) or flexbox

Each post card should display featured image, title, excerpt, author, date, category badge, and read more link

Add hover effects with smooth transitions. Footer: Include copyright notice, social media icons (GitHub, Twitter, LinkedIn), navigation links, and optional newsletter signup

Ensure all sections are responsive and maintain proper spacing with margin/padding.
8

Display posts dynamically with JavaScript

You will load blog posts from JSON and render them dynamically - template literals and instant filtering, no page reloads.
AI Prompt
Implement dynamic blog post listing using JavaScript

Create a renderPostList() function that fetches posts from data source, maps through the array, and generates HTML for each post card using template literals or createElement()

Each card should display: thumbnail image with alt text, title, truncated excerpt (150-200 chars), author name, formatted date (e.g., "January 15, 2024"), category tags, and a "Read More" link with proper URL

Add loading state (skeleton screens or spinner) while fetching data

Implement pagination (10 posts per page) with previous/next buttons or infinite scroll

Add filtering by category/tag with filter buttons that update the displayed posts

Include a search functionality that filters posts by title or content in real-time

Use CSS classes for styling and ensure smooth fade-in animations when posts load.
9

Create individual post pages

You will create individual post pages with readable typography and good spacing - make your content enjoyable to read.
AI Prompt
Create individual post pages at /posts/post-slug.html or implement a single-page application approach with URL parameters

For separate HTML files: Generate a template with header, post container, and footer

For SPA approach: Use URL hash (#post/slug) or query parameters (?post=slug) to identify posts, then dynamically render post content in the main element. Display full post with: large featured image, title in <h1>, author info with avatar, publication date, estimated reading time, full content with proper typography, category and tag badges, social share buttons (Twitter, Facebook, LinkedIn), and author bio section

Add navigation links to previous/next posts

Implement a "Back to Blog" button

Handle 404 errors for non-existent posts

Use meta tags to update page title and description for each post

Add a comments section placeholder or integrate a third-party commenting system like Disqus or Facebook Comments.
10

Integrate marked.js or similar

You will use Marked.js for markdown, DOMPurify for security, and Prism.js for syntax highlighting - all via CDN.
AI Prompt
Integrate a markdown parser to render blog post content from markdown format

Add marked.js library via CDN in HTML: <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> or install via npm

Configure marked.js options: enable GFM (GitHub Flavored Markdown), sanitize HTML to prevent XSS attacks using DOMPurify (<script src="https://cdn.jsdelivr.net/npm/dompurify/dist/purify.min.js"></script>), set custom renderer for code blocks with syntax highlighting using Prism.js or highlight.js

Store post content as markdown in posts.json, then convert to HTML when rendering: const html = DOMPurify.sanitize(marked.parse(markdownContent))

Style markdown elements in CSS: headings hierarchy, blockquotes with left border, code blocks with dark background and monospace font, inline code with light background, lists with proper indentation, links with hover effects, and images with max-width 100% for responsiveness

Add copy button to code blocks for better UX.
11

Image Optimization & Lazy Loading

You will optimize images for web and add lazy loading - native browser features make images load fast without extra libraries.
AI Prompt
Implement image optimization and lazy loading for better performance.

Organize images in /assets/images/ directory with subdirectories for featured images, thumbnails, and inline content images.

Optimize all images before adding to project: compress images using tools like TinyPNG, ImageOptim, or Squoosh, convert large images to modern formats (WebP with JPG/PNG fallback), resize images to actual display size (no 4K images for 400px cards), aim for file sizes under 200KB for featured images, under 100KB for thumbnails.

Implement responsive images using srcset and sizes attributes: <img src="image-800.jpg" srcset="image-400.jpg 400w, image-800.jpg 800w, image-1200.jpg 1200w" sizes="(max-width: 600px) 400px, (max-width: 1000px) 800px, 1200px" alt="descriptive text" loading="lazy">.

Add native lazy loading to all images below the fold with loading="lazy" attribute for instant performance boost with zero JavaScript.

For featured images in posts.json: store multiple image sizes and formats: { "featuredImage": { "jpg": { "small": "/assets/images/post-1-400.jpg", "medium": "/assets/images/post-1-800.jpg", "large": "/assets/images/post-1-1200.jpg" }, "webp": { ... } } }.

Create a JavaScript utility function to generate responsive image HTML with proper srcset based on data structure.

Add CSS for image loading states: placeholder background color or blur-up effect using low-quality image placeholder (LQIP) technique.

Implement intersection observer for custom lazy loading if more control needed over loading behavior and animations.

For inline images in markdown: ensure marked.js outputs images with loading="lazy" by customizing the renderer.

Add proper alt text to all images for accessibility and SEO, use descriptive filenames for images (post-react-hooks-tutorial.jpg not IMG_1234.jpg).

Optional: implement an image lightbox/modal for viewing full-size images when clicked using vanilla JavaScript or a lightweight library like GLightbox.
12

Make mobile-friendly with media queries

You will design mobile-first with media queries and CSS Grid - responsive layout without complex calculations.
AI Prompt
Implement comprehensive responsive design using CSS media queries and mobile-first approach

Define breakpoints: mobile (320px-767px), tablet (768px-1023px), desktop (1024px+)

For mobile: Stack layout vertically, hamburger menu for navigation (implement with JavaScript toggle), full-width post cards, larger touch-friendly buttons (min 44x44px), adjust font sizes (base 16px, scale down if needed)

For tablet: 2-column grid for post listings, expanded navigation menu, adjust spacing and padding

For desktop: 3-column grid, fixed sidebar, larger featured images, optimal line length for readability (60-80 characters)

Use CSS techniques: flexbox with flex-wrap, CSS Grid with auto-fit/auto-fill, percentage-based widths, max-width for content containers (1200px), relative units (rem, em, %), clamp() for fluid typography

Test with Chrome DevTools device emulation. Optimize images with srcset for different screen resolutions

Ensure tap targets are large enough and text remains legible at all sizes

Add viewport height units (vh) for full-screen sections where appropriate.

Testing Your Web Development Blog Application

13

Manual testing checklist

You will create a testing checklist for all functionality - manual testing catches quirks automated tests miss.
AI Prompt
Create a comprehensive manual testing checklist document (TESTING.md or testing-checklist.html)

Organize testing into categories: Functionality Testing (all links work, navigation menu functions, post filtering works, search returns correct results, pagination navigates correctly, theme toggle persists), Visual Testing (layout displays correctly on all devices, images load properly, fonts render correctly, colors match design, spacing and alignment are consistent, no content overflow), Browser Compatibility (test on Chrome, Firefox, Safari, Edge, check CSS Grid/Flexbox support, verify ES6 module support or add fallbacks), Performance Testing (page load time under 3 seconds, images are optimized, no console errors or warnings, smooth animations at 60fps), Accessibility Testing (keyboard navigation works, ARIA labels present, sufficient color contrast ratio 4.5:1, screen reader friendly, semantic HTML structure), SEO Testing (proper meta tags, descriptive alt text for images, semantic heading hierarchy, clean URLs)

Create a spreadsheet or checklist template with pass/fail columns for each test case.
14

Test homepage loads and displays posts

You will test that the homepage loads posts correctly - check DevTools console and test with cache disabled.
AI Prompt
Perform your first comprehensive test of the homepage

Test that page loads successfully: index.html loads without errors in browser console, all CSS files load correctly (check Network tab), JavaScript files load without errors, page renders within 2-3 seconds

Verify blog posts display: posts fetch from data source successfully, correct number of posts render on initial load (10 posts if paginated), each post card displays required fields (title, excerpt, image, date, author, category), images load with proper alt text, dates format correctly (human-readable), excerpt text truncates at correct length with ellipsis

Test post card interactions: hover effects work smoothly, "Read More" links navigate to correct post pages, clicking category tags filters posts, all links are clickable with proper cursor

Check for visual issues: layout is aligned correctly, no overlapping elements, consistent spacing between cards, responsive grid adjusts to viewport. Open browser DevTools console and verify no JavaScript errors

Test with browser cache disabled to ensure fresh load performance.
16

Test on mobile, tablet, desktop

You will test on different screen sizes using DevTools and real devices - mobile menu and images should work smoothly.
AI Prompt
Conduct thorough responsive design testing across all device sizes

Use Chrome DevTools Device Mode to test various screen sizes: Mobile (375x667 iPhone SE, 390x844 iPhone 12/13, 360x800 Galaxy S20), Tablet (768x1024 iPad, 820x1180 iPad Air), Desktop (1366x768, 1920x1080, 2560x1440)

For mobile testing: verify hamburger menu icon appears and functions correctly (toggle open/close with smooth animation), test that menu closes when clicking outside or on a link, ensure post cards stack vertically in single column, check that images scale properly without stretching, verify touch targets are large enough (minimum 44x44px), test that no horizontal scrolling occurs, confirm font sizes are readable (minimum 16px for body text), test form inputs are easy to tap and use

For tablet testing: verify 2-column post grid displays correctly, check navigation expands to full menu or remains as hamburger based on design, test portrait and landscape orientations, ensure sidebar adjusts or stacks appropriately

For desktop testing: verify 3-column grid layout, test hover effects on interactive elements, ensure maximum content width is maintained (not too wide), verify fixed/sticky elements work correctly, test window resizing smoothly transitions between breakpoints

Test on real devices if possible: iPhone, Android phone, iPad, various desktop browsers

Check for visual issues: text overflow, image distortion, misaligned elements, broken layouts at breakpoint transitions

Test landscape and portrait orientations on mobile/tablet

Verify touch gestures (swipe, tap, scroll) work smoothly on touch devices.

Deploying Your Web Development Blog to Production

17

Deploy to GitHub Pages or Netlify

You will deploy to GitHub Pages or Netlify for free hosting with HTTPS - no server config needed.
AI Prompt
Deploy the vanilla HTML/CSS/JavaScript blog to a hosting platform

For GitHub Pages: create GitHub repository, push code to main branch, go to repository Settings > Pages, select source branch (main) and root directory, save and wait for deployment (GitHub provides URL like username.github.io/repo-name), configure custom domain if available (add CNAME file)

For Netlify: create account at netlify.com, drag and drop project folder for manual deploy OR connect GitHub repository for automatic deployments, configure build settings (none needed for vanilla sites), set publish directory to root or dist if using build tools, deploy site (Netlify provides random URL like random-name-123.netlify.app), configure custom domain in Netlify DNS settings, enable HTTPS (automatic with Netlify). Post-deployment checklist: test deployed site URL loads correctly, verify all pages are accessible, check that images and assets load (use absolute paths or root-relative paths, not relative paths like ./images/), test navigation works across all pages, verify fetch() requests work (ensure JSON data is accessible), check browser console for errors on live site, test on mobile device using live URL, verify SEO meta tags are present in page source, test social media sharing with proper Open Graph tags, add site to Google Search Console for SEO, create and submit sitemap.xml. Optional improvements: set up continuous deployment so git push automatically deploys, configure cache headers for performance, add analytics (Google Analytics or Plausible), set up form handling if contact form exists (Netlify Forms or Formspree).