Build Your Own Website
Open access website building
All of the files for this website are free to view and download via the GitHub link on this site. I’m also providing a full set of beginner templates and a step-by-step guide here so you can build your own website with little to no experience.
Website building is often presented as difficult, or hidden behind paywalls and subscriptions. That can lock people out of having a website of their own through no fault of their own. My goal is to make the basics clear, slow, and genuinely beginner-friendly — so you can leave with a working site you control. This was in a sense a goal of making this website, the other uses are incidental.
What you are making
You are making a multi-page website hosted for free using GitHub Pages. The website is just a collection of files (mostly HTML and CSS) stored in a GitHub repository.
- HTML files (
.html) = the content and structure (text, headings, links) - CSS files (
.css) = how it looks (fonts, colours, spacing, layout) - JavaScript files (
.js) = optional behaviour (scroll bar, animations)
Think of it like: HTML = the building, CSS = the design, JS = the moving parts.
Your website folder structure
Your GitHub repository (your online folder) will look like this:
your-website/
index.html
pages/
about.html
projects.html
cv.html
more.html
stylesheets/
base.css
js/
main.js
assets/
images-and-files-go-here.png
cv.pdf
The most important file is index.html. It is your homepage.
GitHub Pages looks for it first.
Step-by-step: GitHub Pages
-
Create a GitHub account
Go to GitHub and sign up. Choose a username you are happy to show publicly. -
Create a repository (this is your website folder)
On GitHub, click the + top-right → New repository. -
Name it
Two options:- Easy option: call it
my-website(or anything). - Classic personal site option: call it
yourusername.github.io.
- Easy option: call it
-
Set it to Public
Public repositories can be hosted for free with GitHub Pages. -
Create
index.html
In your repository:- Click Add file → Create new file
- Name it exactly:
index.html - Copy/paste the template from below
- Scroll down → click Commit changes
-
Create folders in GitHub
There isn’t always a “New folder” button. Instead:- Click Add file → Create new file
- In the filename box type:
pages/about.html - This creates a folder called
pagesautomatically - Paste the template → commit changes
-
Create your CSS file
Makestylesheets/base.cssusing the same method:- Create new file:
stylesheets/base.css - Paste the CSS template from below
- Commit changes
- Create new file:
-
Create JavaScript (optional)
Makejs/main.js:- Create new file:
js/main.js - Paste the JS template from below
- Commit changes
- Create new file:
-
Turn on GitHub Pages
In the repository:- Go to Settings
- Click Pages in the left sidebar
- Under Build and deployment, select Deploy from a branch
- Select branch:
mainand folder:/ (root) - Click Save
-
Visit your website
GitHub will show a website link in the Pages settings. It may take a minute to go live, then refresh.
Optional: yourname.com instead of github.io
Your site works perfectly on a free GitHub address. If you want, you can buy a domain like yourname.com
and connect it to GitHub Pages.
Step 1: buy a domain
Buy a domain from a provider you trust (examples: Namecheap, GoDaddy, Cloudflare Registrar, etc.). Search for the domain you want and purchase it.
Step 2: add the domain to GitHub Pages
- Repository → Settings → Pages
- Find Custom domain
- Type:
yourname.com(orwww.yourname.com) - Save
Step 3: update DNS at your domain provider
DNS is what “points” your domain to GitHub. Your domain provider has a DNS page. GitHub Pages will show you exactly what to add. Commonly you add:
- A records for
yourname.com - CNAME record for
wwwpointing to your GitHub Pages address
DNS changes can take time to spread across the internet. GitHub will confirm when it’s connected.
Templates (copy and paste)
Below are starter templates for every file. They contain no personal content and are designed to be reused. Copy each block into the matching file in your repository.
Recommended order:
1) index.html,
2) stylesheets/base.css,
3) pages in pages/,
4) js/main.js.
Template 1 — index.html (homepage)
This file goes in the root of your repository (not inside pages/).
It links to the shared CSS and JavaScript using paths that work from the root.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Home</title>
<link rel="stylesheet" href="stylesheets/base.css"/>
</head>
<body>
<div id="scroll-progress"></div>
<header class="site-header fade-in">
<div class="header-inner">
<a class="brand" href="index.html">Your Name</a>
<nav class="site-nav">
<ul class="nav-pill">
<li><a class="active" href="index.html">Home</a></li>
<li><a href="pages/projects.html">Projects</a></li>
<li><a href="pages/cv.html">CV</a></li>
<li><a href="pages/about.html">About</a></li>
<li><a href="pages/more.html">More</a></li>
</ul>
</nav>
</div>
</header>
<main class="container">
<h1 class="page-title fade-in">Welcome</h1>
<section class="card fade-in">
<p style="max-width:70ch;">
This is a simple starter website you can host for free using GitHub Pages.
Replace this text with your own introduction.
</p>
<p style="max-width:70ch; margin-top:14px;">
Tip: keep paragraphs short and readable. Use clear headings and consistent navigation.
</p>
<p style="margin-top:14px;">
<a class="btn" href="pages/more.html">Learn how to build this</a>
</p>
</section>
</main>
<footer>
<div>© Your Name</div>
</footer>
<script src="js/main.js"></script>
</body>
</html>
Template 2 — pages/about.html
This file goes inside the pages/ folder. Because it is one folder deeper,
it links to CSS/JS using ../.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>About</title>
<link rel="stylesheet" href="../stylesheets/base.css"/>
</head>
<body>
<div id="scroll-progress"></div>
<header class="site-header fade-in">
<div class="header-inner">
<a class="brand" href="../index.html">Your Name</a>
<nav class="site-nav">
<ul class="nav-pill">
<li><a href="../index.html">Home</a></li>
<li><a href="projects.html">Projects</a></li>
<li><a href="cv.html">CV</a></li>
<li><a class="active" href="about.html">About</a></li>
<li><a href="more.html">More</a></li>
</ul>
</nav>
</div>
</header>
<main class="container">
<h1 class="page-title fade-in">About</h1>
<section class="card fade-in">
<p style="max-width:70ch;">
Write a short introduction here: who you are, what you do, and what you care about.
</p>
<p style="max-width:70ch; margin-top:14px;">
You can add links, a short CV summary, interests, or anything else.
</p>
</section>
</main>
<footer>
<div>© Your Name</div>
</footer>
<script src="../js/main.js"></script>
</body>
</html>
Template 3 — pages/projects.html
This is a simple projects page that uses repeated “project cards”. You can add as many as you want.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Projects</title>
<link rel="stylesheet" href="../stylesheets/base.css"/>
</head>
<body>
<div id="scroll-progress"></div>
<header class="site-header fade-in">
<div class="header-inner">
<a class="brand" href="../index.html">Your Name</a>
<nav class="site-nav">
<ul class="nav-pill">
<li><a href="../index.html">Home</a></li>
<li><a class="active" href="projects.html">Projects</a></li>
<li><a href="cv.html">CV</a></li>
<li><a href="about.html">About</a></li>
<li><a href="more.html">More</a></li>
</ul>
</nav>
</div>
</header>
<main class="container">
<h1 class="page-title fade-in">Projects</h1>
<section class="card fade-in">
<h2 style="margin-bottom:8px;">Project Title</h2>
<p style="max-width:70ch;">
Write 3–6 sentences explaining what you did, what tools you used, and the result.
</p>
<p style="margin-top:12px;">
<a href="#">Optional link</a>
</p>
</section>
<div style="height:16px;"></div>
<section class="card fade-in">
<h2 style="margin-bottom:8px;">Another Project</h2>
<p style="max-width:70ch;">
Add more project cards like this. Keep the layout consistent.
</p>
</section>
</main>
<footer>
<div>© Your Name</div>
</footer>
<script src="../js/main.js"></script>
</body>
</html>
Template 4 — pages/cv.html
This page includes a button to download a CV PDF. If you don’t have a PDF yet, remove the button.
If you do, place it in assets/ as cv.pdf.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>CV</title>
<link rel="stylesheet" href="../stylesheets/base.css"/>
</head>
<body>
<div id="scroll-progress"></div>
<header class="site-header fade-in">
<div class="header-inner">
<a class="brand" href="../index.html">Your Name</a>
<nav class="site-nav">
<ul class="nav-pill">
<li><a href="../index.html">Home</a></li>
<li><a href="projects.html">Projects</a></li>
<li><a class="active" href="cv.html">CV</a></li>
<li><a href="about.html">About</a></li>
<li><a href="more.html">More</a></li>
</ul>
</nav>
</div>
</header>
<main class="container">
<h1 class="page-title fade-in">CV</h1>
<section class="card fade-in">
<p style="max-width:70ch;">
Add a short summary of your background here.
</p>
<p style="margin-top:14px;">
<a class="btn" href="../assets/cv.pdf" download>Download CV (PDF)</a>
</p>
<p style="max-width:70ch; margin-top:14px; color: var(--muted);">
Tip: if the download button does not work, check the file path and make sure your PDF is inside the assets folder.
</p>
</section>
</main>
<footer>
<div>© Your Name</div>
</footer>
<script src="../js/main.js"></script>
</body>
</html>
Template 5 — pages/more.html (minimal page)
If you’re copying this guide, you already have a more.html.
But if you want a clean “More” page without the big tutorial, use this minimal template.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>More</title>
<link rel="stylesheet" href="../stylesheets/base.css"/>
</head>
<body>
<div id="scroll-progress"></div>
<header class="site-header fade-in">
<div class="header-inner">
<a class="brand" href="../index.html">Your Name</a>
<nav class="site-nav">
<ul class="nav-pill">
<li><a href="../index.html">Home</a></li>
<li><a href="projects.html">Projects</a></li>
<li><a href="cv.html">CV</a></li>
<li><a href="about.html">About</a></li>
<li><a class="active" href="more.html">More</a></li>
</ul>
</nav>
</div>
</header>
<main class="container">
<h1 class="page-title fade-in">More</h1>
<section class="card fade-in">
<p style="max-width:70ch;">
Add anything you want here: links, resources, FAQs, guides, etc.
</p>
</section>
</main>
<footer>
<div>© Your Name</div>
</footer>
<script src="../js/main.js"></script>
</body>
</html>
Template 6 — stylesheets/base.css (shared styling)
This single CSS file controls the look of every page (fonts, colours, layout). All pages link to it. When you change this file, your whole website updates.
:root{
--bg:#F8FAFC;
--surface:#FFFFFF;
--text:#0F172A;
--muted:#475569;
--border:#E2E8F0;
--accent:#1D4ED8;
--accent-hover:#1E40AF;
--header-bg:#0B1220;
--header-text:#FFFFFF;
--radius:14px;
--container:980px;
--s1:8px;
--s2:16px;
--s3:24px;
--s4:40px;
--font: system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial,
"Apple Color Emoji","Segoe UI Emoji";
}
*{margin:0;padding:0;box-sizing:border-box}
html,body{overflow-x:hidden}
body{
font-family:var(--font);
background:var(--bg);
color:var(--text);
line-height:1.7;
}
.container{
max-width:var(--container);
margin:0 auto;
padding:0 var(--s2);
}
.site-header{
background:var(--header-bg);
position:sticky;
top:0;
z-index:1000;
box-shadow:0 1px 0 rgba(255,255,255,0.08);
}
.header-inner{
max-width:1100px;
margin:0 auto;
padding:12px 16px;
display:flex;
align-items:center;
justify-content:space-between;
gap:12px;
}
.brand{
color:var(--header-text);
text-decoration:none;
font-weight:800;
letter-spacing:.2px;
}
.site-nav .nav-pill{
list-style:none;
display:flex;
gap:10px;
padding:6px 8px;
border-radius:9999px;
background:rgba(255,255,255,0.06);
}
.site-nav .nav-pill a{
color:var(--header-text);
text-decoration:none;
padding:8px 12px;
border-radius:9999px;
opacity:.92;
font-weight:650;
transition:background .2s ease, transform .15s ease, opacity .2s ease;
}
.site-nav .nav-pill a:hover{
background:rgba(255,255,255,0.10);
transform:translateY(-1px);
opacity:1;
}
.site-nav .nav-pill a.active{
background:rgba(255,255,255,0.16);
opacity:1;
outline:1px solid rgba(255,255,255,0.18);
}
.page-title{
text-align:center;
font-size:clamp(1.9rem,3.2vw,2.4rem);
font-weight:900;
letter-spacing:-0.01em;
margin:var(--s4) 0 var(--s3);
}
.page-title::after{
content:"";
display:block;
width:96px;
height:2px;
background:var(--border);
margin:var(--s1) auto 0;
border-radius:999px;
}
.card{
background:var(--surface);
border:1px solid var(--border);
border-radius:var(--radius);
box-shadow:0 12px 30px rgba(15,23,42,0.08);
padding:var(--s3);
}
a{color:var(--accent);text-decoration:none}
a:hover{color:var(--accent-hover);text-decoration:underline;text-decoration-thickness:2px}
a:focus-visible{
outline:3px solid rgba(29,78,216,0.25);
outline-offset:3px;
border-radius:6px;
}
.btn{
display:inline-flex;
align-items:center;
justify-content:center;
padding:12px 16px;
border-radius:9999px;
background:var(--accent);
color:#fff;
font-weight:850;
text-decoration:none;
border:1px solid transparent;
box-shadow:0 12px 26px rgba(29,78,216,0.18);
transition:transform .15s ease, background .15s ease;
}
.btn:hover{background:var(--accent-hover);transform:translateY(-1px);text-decoration:none}
.btn:active{transform:translateY(0)}
footer{
margin-top:var(--s4);
padding:var(--s3) 0;
border-top:1px solid var(--border);
color:var(--muted);
text-align:center;
}
/* scroll progress bar */
#scroll-progress{
position:fixed;
top:0;left:0;
height:3px;
width:0%;
background:var(--accent);
z-index:2000;
transition:width .15s ease-out;
}
/* fade-in */
.fade-in{
opacity:0;
transform:translateY(16px);
transition:opacity .6s ease-out, transform .6s ease-out;
will-change:opacity,transform;
}
.fade-in.visible{opacity:1;transform:translateY(0)}
@media (max-width:760px){
.header-inner{flex-direction:column;align-items:flex-start}
.site-nav .nav-pill{flex-wrap:wrap}
}
@media (prefers-reduced-motion: reduce){
*{transition:none !important; animation:none !important;}
}
Template 7 — js/main.js (scroll bar + fade-in)
This file controls the scroll progress bar and fade-in animation. If you don’t want animations, you can delete this file and remove the script tags from your HTML pages.
// Scroll progress bar
window.addEventListener("scroll", () => {
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
const scrollHeight = document.documentElement.scrollHeight - document.documentElement.clientHeight;
const progress = scrollHeight > 0 ? (scrollTop / scrollHeight) * 100 : 0;
const bar = document.getElementById("scroll-progress");
if (bar) bar.style.width = progress + "%";
});
// Fade-in on scroll
document.addEventListener("DOMContentLoaded", () => {
const observer = new IntersectionObserver((entries, obs) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add("visible");
obs.unobserve(entry.target);
}
});
}, { threshold: 0.1 });
document.querySelectorAll(".fade-in").forEach(el => observer.observe(el));
});