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 the modules you need.
JavaScript has its own module system. For historical reasons, JavaScript has two module systems. This can be confusing for beginners.
The first one is CommonJS. This was first used by Node.js. 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 items
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 standard now. You use import to bring in modules and export to send them out:
// 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'; // import functions
console.log(add(1, 2)); // 3
console.log(subtract(2, 3)); // -1Main differences between these two systems:
CommonJS's require() is synchronous. It works well on the server (files are local and fast to load). You can call require() anywhere, even inside if statements or functions.
ES Modules's import is asynchronous. It works better in the browser (files come from the network). The import statement must be at the top of the file, not inside statements or functions (but you can use dynamic import with import() function).
In Node.js, CommonJS is used by default. If you want to use ES Modules, add a "type": "module" field in your package.json.
In the future, ES Modules will replace CommonJS and become the main module system in JavaScript.
TypeScript vs JavaScript
TypeScript is a superset of JavaScript. It adds a static type system to JavaScript, so you can find type mistakes while coding and improve code quality.
But TypeScript needs to be converted to JavaScript to run, because browsers and Node.js only understand JavaScript.
Let's compare:
// JavaScript: no type check
function add(a, b) {
return a + b;
}
add(1, 2); // 3
add("1", "2"); // "12" (string join, maybe not what you want)// TypeScript: with type check
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 converting:
# install TypeScript
npm install -g typescript
# compile TypeScript file
tsc app.ts
# this will make app.js. The type info is removed, and it's just plain JavaScriptThe compiled app.js is normal JavaScript code, which can run in browsers or Node.js.
The main advantage of TypeScript is type safety. You can catch type errors while compiling, not just at runtime. Also, type info helps your IDE suggest code and auto-complete more accurately. In big projects, type info also works as documentation. This is why more and more frontend projects are using TypeScript, especially for enterprise apps.
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 Full-stack React Framework
If React and Vue are front-end frameworks, then what is Next.js? How is it related to React?
Next.js is a full-stack framework built on top of React. React only handles building the UI, but to make a real app, you still need features like routing (for navigating pages), server-side rendering (for SEO), API routing (for backend endpoints), code splitting (for faster loading), image optimization, and more.
Next.js includes all of these features. The best part is, you can write both frontend and backend code using JavaScript or TypeScript.
Next.js Project Structure
Next.js uses file-based routing. The folder structure matches your routes:
my-nextjs-app/
├── app/
│ ├── page.tsx # Home page, route is /
│ ├── about/
│ │ └── page.tsx # About page, route is /about
│ ├── blog/
│ │ ├── page.tsx # Blog list, route is /blog
│ │ └── [id]/
│ │ └── page.tsx # Blog detail, route is /blog/:id
│ │
│ └── api/ # API route folder
│ ├── users/
│ │ └── route.ts # API endpoint /api/users
│ └── posts/
│ └── route.ts # API endpoint /api/posts
|
├── public/ # Static files (images, fonts, etc.)
├── package.json
└── next.config.js # Next.js config fileEven though everything is in the same project, code inside the app/api/ folder is backend code. It runs on the Node.js server and 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() {
// You can access the database here
const users = await db.query('SELECT * FROM users');
return NextResponse.json({ users });
}
export async function POST(request: Request) {
const body = await request.json();
// You can read and write files here too
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 will be rendered into HTML and sent to the browser.
As a backend developer, you will find the Next.js project structure very familiar. The api/ folder is like your Controller layer, except you use JavaScript/TypeScript, running in the Node.js environment.
Server-side Rendering vs Client-side Rendering
One important feature of Next.js is server-side rendering (SSR). This is different from traditional React/Vue apps.
Traditional Client-side Rendering (CSR)
Traditional React and Vue apps use client-side rendering. The server sends a mostly 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 with JS -->
</body>
</html>This HTML is downloaded first. Then the browser loads the bundle.js file, runs the JavaScript, generates the page content, and puts it inside the #root element.
There are two problems with this:
First, users see a blank page at first. They must wait for JavaScript to download, run, and load content.
Second, it is bad for SEO. Search engines only see an empty HTML file. They can't get your real page content, which is bad for website ranking.
Server-side Rendering (SSR)
Next.js supports server-side rendering. The server runs your React code and sends back a full HTML file:
<!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: TypeScript Best Practices</li>
</ul>
</div>
<script src="/_next/static/chunks/main.js"></script>
</body>
</html>Now the HTML sent to the browser already has the full page content. Users can see the page right away. Search engines can also see and index your content.
The JavaScript loaded by the <script> tag runs in the browser to handle things like user interaction, showing animations, and loading dynamic data.
Summary
Front-end tech can look complicated, but it's easier to understand once you break it down:
- HTML + CSS + JavaScript are the foundation. They handle structure, style, and behavior.
- JavaScript is the main front-end language. TypeScript is a safer, typed version of JavaScript for a better coding experience.
- Node.js lets you run JavaScript on the server, so you can build backend apps with JavaScript.
- React/Vue are UI frameworks. They help you manage components, state, and build complex apps more easily.
- Next.js/Nuxt.js are full-stack frameworks. They give React/Vue full-stack power, so you can use JavaScript for both frontend and backend in one project.
As a backend developer, knowing these concepts makes it much easier to use AI tools to build front-end pages.