Frontend Development Introduction for AI Era
From my experience, almost all front-end development work can be done with AI tools. But there are many front-end technologies and new concepts appear all the time. For back-end developers, it’s easy to get confused and hard to understand or debug code written by AI.
This article does not focus on deep explanations or principles of front-end technology. Instead, it will make some key front-end concepts clear.
Once you know these basic ideas, you can easily use AI tools to build front-end pages. You can also learn as you go, and quickly master the basic skills for front-end development.
In a narrow sense, the front end means web pages running in a browser, which work together with the back-end to form the classic client-server (C/S) or browser-server (B/S) structure.
Broadly, the front end includes any user interface, such as mobile apps, PC desktop software, or mini programs. But this article is mainly about web front-end.
This article will answer the following questions:
- How do HTML, CSS, and JavaScript work together?
- What are the features of JavaScript? How does it run?
- What is Node.js?
- What is the difference between JavaScript’s module systems (require, import/export)?
- What is the relationship between TypeScript and JavaScript?
- Why do we need frameworks like React or Vue? What are their features?
- What is Next.js? How is it related to React?
- What is server-side rendering (SSR)? How is it different from client-side rendering (CSR)?
How do HTML, CSS, and JavaScript work together?
People often say HTML, CSS, and JavaScript are the “three pillars” of front-end. Each has its own job:
HTML (HyperText Markup Language) defines the page’s structure and content, for example, a title here or a button there.
CSS (Cascading Style Sheets) controls the page’s style and layout, for example, making the button red, setting the font size, or arranging elements.
JavaScript controls the page’s behavior and interactions, such as what happens when a button is clicked, or how to fetch data from the back end and update the page.
Let’s see a simple example to show how these three work together:
<!DOCTYPE html>
<html>
<head>
<title>Counter Example</title>
<style>
/* CSS: Define styles */
.container {
text-align: center;
margin-top: 50px;
}
.counter {
font-size: 48px;
color: #333;
margin: 20px 0;
}
button {
font-size: 16px;
padding: 10px 20px;
margin: 5px;
cursor: pointer;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 4px;
}
button:hover {
background-color: #45a049;
}
</style>
</head>
<body>
<!-- HTML: Define structure -->
<div class="container">
<h1>Simple Counter</h1>
<div class="counter" id="count">0</div>
<button onclick="increment()">Increase</button>
<button onclick="decrement()">Decrease</button>
<button onclick="reset()">Reset</button>
</div>
<script>
// JavaScript: Define behavior
let count = 0;
function increment() {
count++;
updateDisplay();
}
function decrement() {
count--;
updateDisplay();
}
function reset() {
count = 0;
updateDisplay();
}
function updateDisplay() {
document.getElementById('count').textContent = count;
}
</script>
</body>
</html>Save this code as counter.html and open it in your browser. You’ll see a counter with three buttons to increase, decrease, or reset the number.
This example shows how the three parts work together: HTML defines what elements are on the page (the title, number, and three buttons). CSS sets their styles (centered, font size, button color). JavaScript controls what happens when you click a button (change the number and update the display).
Introduction to JavaScript
JavaScript is an interpreted language. You do not need to compile it. The interpreter runs the code directly, just like Python. The most famous JavaScript engine is Chrome’s V8 engine.
JavaScript is single-threaded, but it can do many things at once using event loops and async functions (like callbacks, Promise, async/await). This is different from the traditional multi-threading model.
To run JavaScript in the browser is very simple: open the browser's developer tools (press F12), switch to the Console tab, and type JavaScript code to execute.
What is Node.js
Many people think JavaScript is only for the frontend, but that’s not true. Node.js allows JavaScript to run on the server, so JavaScript can be used for full-stack development.
Node.js is not a new language. It is a JavaScript runtime environment.
It brings Chrome’s V8 engine to the server, and it gives JavaScript the ability to work with the file system, network, and processes. Node.js still uses JavaScript syntax but also lets you do backend development.
Here are some examples:
// Frontend JavaScript: working with the DOM
document.getElementById('btn').addEventListener('click', () => {
console.log('Button was clicked');
});
// Frontend JavaScript: sending HTTP requests
fetch('/api/users')
.then(res => res.json())
.then(data => console.log(data));// Backend JavaScript (Node.js): creating an HTTP server
const http = require('http');
const server = http.createServer((req, res) => {
if (req.url === '/api/users') {
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify([
{id: 1, name: 'Zhang San'},
{id: 2, name: 'Li Si'}
]));
}
});
server.listen(3000, () => {
console.log('Server is running at http://localhost:3000');
});// Backend JavaScript (Node.js): reading and writing files
const fs = require('fs');
// Read file
fs.readFile('data.txt', 'utf8', (err, data) => {
if (err) throw err;
console.log(data);
});
// Write file
fs.writeFile('output.txt', 'Hello Node.js', (err) => {
if (err) throw err;
console.log('File written successfully');
});JavaScript in the browser runs in a sandbox. It can only use browser APIs like window and document.
Node.js is like other backend languages. It can use system tools, read and write files, and work with databases. But you do not have window or document objects in Node.js.
After installing Node.js, you can run JavaScript with the node command:
node script.jsIsn't this similar to Python? Yes, both are interpreted languages. You run them directly with an interpreter, no need to compile.
JavaScript Module Systems
When you write backend code, you often split your code into several files and use import or require to bring in needed modules.
JavaScript also has a module system, but because of history, there are two main module systems. This can be confusing for beginners.
The first one is CommonJS. This is the module system Node.js used first. You use require() to import modules, and use module.exports or exports to export them:
// math.js - export module
function add(a, b) {
return a + b;
}
function subtract(a, b) {
return a - b;
}
// export multiple functions
module.exports = {
add,
subtract
};// main.js - import module
const math = require('./math.js');
console.log(math.add(1, 2)); // 3The second one is ES Modules (also called ES6 modules). This is the official JavaScript module standard. You use import to import, and export to export:
// math.js - export module
export function add(a, b) {
return a + b;
}
export function subtract(a, b) {
return a - b;
}// main.js - import module
import { add, subtract } from './math.js'; // named import
console.log(add(1, 2)); // 3
console.log(subtract(2, 3)); // -1Main differences between the two systems:
CommonJS require() loads modules synchronously. This is better for server-side code, since files are stored locally and load quickly. You can call require() anywhere in your code, even inside if statements to load modules only when needed.
ES Modules import loads modules asynchronously. This is better for browsers, because files are downloaded from the network. The import statement must be at the top of your file, not inside functions or if statements (but you can use dynamic import: import() as a function).
In Node.js, CommonJS is used by default. To use ES Modules, add "type": "module" in your package.json.
In the future, ES Modules will replace CommonJS and become the official JavaScript module system.
TypeScript vs JavaScript
TypeScript is a superset of JavaScript. It adds a type system to JavaScript, which helps you find type errors during development and makes your code better.
TypeScript code will be converted to JavaScript before running, because browsers and Node.js only understand JavaScript.
Here is a comparison:
// JavaScript: no type checking
function add(a, b) {
return a + b;
}
add(1, 2); // 3
add("1", "2"); // "12" (string concatenation, maybe not what you want)// TypeScript: with type checking
function add(a: number, b: number): number {
return a + b;
}
add(1, 2); // 3
add("1", "2"); // compile error: type mismatchTypeScript uses the tsc command (TypeScript Compiler) for type checking and conversion:
# Install TypeScript
npm install -g typescript
# Compile a TypeScript file
tsc app.ts
# This generates app.js. All type information is removed. Only JavaScript is left.The final app.js file is just plain JavaScript, and can run in browsers or Node.js.
The biggest advantage of TypeScript is type safety. It finds type errors at compile time, not when your program is running. Typings also help your code editor suggest and autocomplete code. In large projects, type information is also great documentation. That’s why more and more projects, especially in big companies, use TypeScript.
What are React and Vue Frameworks
If you can build web pages using HTML, CSS, and JavaScript, why do we need frameworks like React and Vue?
Problems with Writing Apps in Plain JavaScript
Making complex apps with plain JavaScript has a few big problems:
First, DOM operations are hard to manage. Every time you update the page, you need to change the DOM by hand:
// Update the style of a user list
function renderUsers(users) {
const container = document.getElementById('user-list');
container.innerHTML = ''; // Clear it
users.forEach(user => {
const div = document.createElement('div');
div.className = 'user-item';
div.textContent = user.name;
container.appendChild(div);
});
}This is fine for a few pages, but if your page is complex, the code quickly becomes hard to maintain.
Second, managing data (state) is messy. Data is scattered everywhere, making it hard to track what changes:
let userList = [];
let currentPage = 1;
let isLoading = false;
// ... more global variables
// After changing data, remember to update all related DOM
function addUser(user) {
userList.push(user);
renderUsers(userList); // Update user list
updateUserCount(userList); // Update the count
checkEmptyState(userList); // Check if need to show empty state
}Last, code reuse is difficult. You have to write HTML, CSS, and JavaScript separately. It's hard to package a function, like a search box, into a reusable component.
Imagine a big project with code that is not organized into modules—it will be messy and hard to maintain.
Frameworks like React and Vue are created to solve these problems:
They give a clear way to organize code, make components easy to build and reuse, and make managing state easier, so building complex apps is much simpler.
The React Framework
React is a frontend library made by Facebook (Meta). Its key ideas are component-based design and declarative programming.
React code is very simple. A typical React component looks like this:
import { useState } from 'react';
import './Counter.css'; // Import CSS
// A counter component
function Counter() {
// Use a Hook to manage state
const [count, setCount] = useState(0);
// Use JSX to describe the HTML
return (
<div className="counter">
<p>Current count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increase</button>
<button onClick={() => setCount(count - 1)}>Decrease</button>
</div>
);
}
export default Counter;React uses a functional style. You can write HTML using JSX, right inside your JavaScript.
This Counter will be rendered as HTML + CSS + JavaScript on the page, and users can interact with it.
Isn't this way of coding clearer and easier to maintain than writing plain HTML, CSS, and JavaScript separately?
The Vue Framework
Vue is another popular frontend framework. Its main ideas are progressive design and reactive data.
Vue focuses on "reactive data binding." When you change data, Vue automatically updates every part of the page that uses that data.
Vue also uses components, but its way of organizing code is different from React. Vue uses single-file components (.vue files) that put HTML, CSS, and JavaScript together in one place for easy maintenance:
<template>
<!-- Template: HTML -->
<div class="counter">
<p>Current count: {{ count }}</p>
<button @click="increment">Increase</button>
<button @click="decrement">Decrease</button>
</div>
</template>
<script>
// Script: JavaScript
export default {
// Data
data() {
return {
count: 0
}
},
// Methods
methods: {
increment() {
this.count++;
},
decrement() {
this.count--;
}
}
}
</script>
<style scoped>
/* Style: CSS (scoped means it only affects this component) */
.counter {
text-align: center;
padding: 20px;
}
</style>Vue puts a component's HTML, CSS, and JavaScript together in one file, making the code more organized.
React and Vue solve similar problems. Which one to use depends on your habits and the needs of your project.
Next.js: The React Full-Stack Framework
If React and Vue are front-end frameworks, what is Next.js? How is it related to React?
Next.js is a full-stack framework built on top of React. React only helps you build UI, but to make a complete app you also need routing (page navigation), server-side rendering (SEO), API routes (backend interfaces), code splitting (faster loading), image optimization, and more.
Next.js includes all these features. The most important thing is, with Next.js you can use JavaScript or TypeScript to build both the frontend and backend.
Next.js Folder Structure
Next.js uses file-based routing—your folder structure is your routing structure:
my-nextjs-app/
├── app/
│ ├── page.tsx # Homepage, route /
│ ├── about/
│ │ └── page.tsx # About page, route /about
│ ├── blog/
│ │ ├── page.tsx # Blog list, route /blog
│ │ └── [id]/
│ │ └── page.tsx # Blog detail, route /blog/:id
│ |
│ └── api/ # API routes folder
│ ├── users/
│ │ └── route.ts # API endpoint /api/users
│ └── posts/
│ └── route.ts # API endpoint /api/posts
|
├── public/ # Static assets (images, fonts, etc.)
├── package.json
└── next.config.js # Next.js config fileEven though they are in the same project, the code inside the app/api/ folder is backend code. It runs in the Node.js environment, so it can access the database, file system, and other server resources:
// app/api/users/route.ts - Backend API code
import { NextResponse } from 'next/server';
// This code runs on the Node.js server, not in the browser
export async function GET() {
// Can access the database
const users = await db.query('SELECT * FROM users');
return NextResponse.json({ users });
}
export async function POST(request: Request) {
const body = await request.json();
// Can read and write files
await fs.writeFile('data.json', JSON.stringify(body));
return NextResponse.json({ success: true });
}Other files in the app/ folder (like page.tsx) are page components. They can run with server-side rendering (SSR) or client-side rendering (CSR).
So, as a backend developer, you will find the Next.js project structure familiar: the api/ folder is like your controller layer, just written in JavaScript/TypeScript and running in Node.js.
Server-side Rendering vs Client-side Rendering
One key feature of Next.js is Server-Side Rendering (SSR). This is different from traditional React or Vue apps.
Traditional Client-Side Rendering (CSR)
Traditional React/Vue apps use only client-side rendering. The server returns an almost empty HTML file:
<!DOCTYPE html>
<html>
<head>
<title>My React App</title>
</head>
<body>
<div id="root"></div> <!-- This is empty -->
<script src="/bundle.js"></script> <!-- All content loads through JS -->
</body>
</html>The browser downloads this HTML, then downloads bundle.js. The JavaScript runs and creates the page content, then puts it inside the #root element.
There are two main problems with this method:
First, users see the page content slowly. They must wait for the JavaScript to download, parse, and run before they see anything.
Second, it is not good for SEO. Search engines see only an empty HTML file, so your pages are hard to discover.
Server-Side Rendering (SSR)
Next.js supports server-side rendering. Here, the server runs your React component code and creates complete HTML before sending it to the browser:
<!DOCTYPE html>
<html>
<head>
<title>My Next.js App</title>
</head>
<body>
<div id="root">
<h1>Welcome to my blog</h1>
<ul>
<li>Post 1: Getting Started with Next.js</li>
<li>Post 2: Deep Dive into React Hooks</li>
<li>Post 3: Best Practices with TypeScript</li>
</ul>
</div>
<script src="/_next/static/chunks/main.js"></script>
</body>
</html>The browser gets a complete HTML file, so users see the content right away and search engines can read the page content.
Summary
The front-end tech stack can look complex, but it is easier to understand if you see the relationships:
- HTML, CSS, and JavaScript are the basic trio. They handle structure, style, and behavior.
- JavaScript is the main language for frontend. TypeScript is a safer version that helps during development.
- Node.js lets JavaScript run on the server, so you can make backend apps.
- React and Vue are UI frameworks. They help you build with components and manage state, making it easier to build complex apps.
- Next.js (and Nuxt.js for Vue) are full-stack frameworks. They add full-stack features on top of React or Vue and let you write frontend and backend code with JavaScript.
As a backend developer, knowing about these frontend concepts gives you the power to use AI tools and easily build frontend pages.