Published in


How to Build a School Website with Strapi CMS using Vanilla Javascript

In this article, you will build the frontend and backend of a school website using Strapi, HTML, CSS, and standard Javascript.

Author: Dennis Muasya

This tutorial will teach you to build the frontend and backend of a school website using the Strapi API, HTML, CSS, and Vanilla Javascript. There won’t be any framework in it. Considering the target population, the design will be straightforward and uncluttered. I’ll be talking about a school website I created using backend services in this blog post. I’ve previously worked with local JSON data, and it’s challenging to update and delete the material.

Strapi is a free and open-source Headless CMS that allows for quick and easy API design and content management. You will learn how to use vanilla JavaScript and Strapi CMS to create a school website.


Make sure your computer has the following installed before we start.

  • Node.js: Due to the fact that NPM and Strapi are both built on Nodejs, this is the first tool you will require. Download it from this page. The needed NodeJS version ranges from 14.19.1 to 16.x.x.
  • NPM: This is a package manager for Node. The Nodejs binary is included with it. NPM >= 6.x is the necessary version.
  • IDE: Integrated Develepment Environment such as Microsoft Visual Studio Code, Android Studio, and Sublime Text.
  • A basic understanding of asynchronous JavaScript.

What is REST API?

The REST API, often known as a RESTful API, divides a transaction into several tiny components. Every module deals with a fundamental aspect of the transaction. Although this modularity offers developers a great deal of freedom, it might be difficult for developers to create a REST API from scratch. Several businesses already provide models for developers to use; the most well-liked models are those offered by Strapi. Commands are used by a RESTful API to access resources. A resource representation is the status of a resource at any particular timestamp.

The REST API in Strapi enables access to the various content types via API endpoints. When a content type is created using Strapi, API endpoints are automatically created. When making a query to an API endpoint, API parameters can be used to filter the results. There are no relations, media fields, components, or dynamic zones by default when using the REST API. Fill up particular fields by using the populate argument.

How to Read DOCS

When you are familiar with the tool you want to use, the official documentation is the best place to start. When working with something new, repress the urge to jump right in and read the manual instead. You will also make time and effort savings as your skills as a developer advance. You can learn about many different subjects by reading. You will be better able to understand the next topic by knowing more about one area of software development.

Endeavor to go through each example in a Getting Started lesson. Before moving on, be sure you understand the foundational ideas of a new language or system.

Finally, familiarize yourself with the code. Reading the documentation alone probably won’t be enough to understand what the program is doing. A little glance at the source code can have a significant impact. Utilize each and every piece of code by copying it, reading it, and determining what it does. Try out the code yourself to see how it works. Start it over again. Break it. then choose a resolution.

How to Work With Strapi CMS

Use this GitHub link to clone the school’s website. The final step is to add the common JavaScript files in order to access the data from Strapi. To save the school website, decide where to put it on your computer.

  1. On your terminal, enter the following command:
git clone
  1. Change the directories to school website once the cloning is finished.
cd SchoolWebsiteStrapi
  1. Enter the following code into the terminal to construct a new Strapi app into a backend folder.
npx create-strapi-app backend --quickstart

This results in the creation of a new Strapi app in a backend folder. The —quickstart flag instructs Strapi to use SQLite as its preferred database. When given the option to utilize a different database, omit the flag and select that database instead.

The length of time it takes to complete the installation will depend on how quickly your network is.

  1. After finishing that, run the next snippet to start Strapi in development mode.
strapi develop

You should see your browser launch at http://localhost:1337/admin/auth/register. If not, manually launch your preferred browser. It will display a sign-up form similar to the one below.

Strapi Dashboard Login
  1. Now, enter your details in the form. This step is important for subsequent logins to the admin dashboard. Your dashboard should now appear like this:
Strapi Welcome Page

On this page, your APIs are listed in the upper-left corner. It should only contain the Users API for the time being.

  1. To build the grade endpoint, choose “Content-Type Builder” from the sidebar.
  2. After being redirected, select “Create new collection type” and give it the display name “Grade”. Despite the fact that the term is singular, Strapi pluralizes it by default. The modal screen should look like this:
Strapi Modal Screen

Add New Grade

The fields for this collection can be chosen on a new screen that should appear after clicking “Continue.” From the list, select the “Text” field, then give it a name.

Add New Grade

When creating a new grade, make sure this information is compulsory by selecting “Advanced options” and checking the “Required field” box.

Required Field

You’re done creating the grades endpoint.


HTML Structure with Meaningful Classes

HTML is a powerful tool that gives your code superpowers if you want to utilize it. The built-in behaviors in HTML allow you to reduce the amount of explicit code you need to utilize. By organizing your papers so that they work well and look good, you may make your content accessible to more people and software.

The project demystifies fundamental HTML tags and properties while instructing you on how to write semantic, meaningful HTML. It helps you ensure that your pages (including elements like navigation) are properly arranged and sectioned while also showing you how to use the language’s unique features for presenting quotes, figures, dates, and timings.

By design, HTML is a tolerant language that permits the execution of even subpar code. Our school website won’t render without components like , , , and . Certain browsers won’t correctly display pages without these auxiliary elements.

<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>School Website - Strapi CMS</title>
<link rel="stylesheet" href="css/minified/style.min.css">

<!-- Modal on page load -->
<div class="modal" id="modal-one" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-header">
<h2>Namaste !</h2>
<a href="#modal-one" class="btn-close" aria-hidden="true">×</a>

<div class="modal-body">
<p>This is the Moi Forces Academy Website but it's <br />

By following the few straightforward guidelines below, we can maintain our code well-organized.

  • The indentation of nested elements is required.
  • For elements, attributes, and values, lowercase is preferred.
  • Use either single or double quote marks, but be sure you use them both consistently.
  • It is recommended to ignore the Boolean attribute values for complete organization.

When we decide on a technique that we like. It must be adhered to strictly, applied everywhere, and kept separate.

<!-- acheivements section -->

<section class="achieve">

<!-- achieve container -->
<div class="achieve__container">
<h1 class="achieve__h1"></h1>
<div class="achieve__section">
<div class="achieve__sectionList">
<img class="achieve__imgIcon" src="./img/ach1.png" alt="achieveIcon" />
<h3 class="achieve__h3"></h3>
<p class="achieve__p"></p>

<div class="achieve__sectionList">
<img class="achieve__imgIcon1" src="./img/ach2.png" alt="achieveIcon" />
<h3 class="achieve__h31"></h3>
<p class="achieve__p1"></p>

<div class="achieve__sectionList">
<img class="achieve__imgIcon" src="./img/ach3.png" alt="achieveIcon" />
<h3 class="achieve__h32"></h3>
<p class="achieve__p2"></p>

<div class="achieve__sectionList">
<img class="achieve__imgIcon" src="./img/ach4.png" alt="achieveIcon" />
<h3 class="achieve__h33"></h3>
<p class="achieve__p3"></p>

<!-- End achieve container -->


<!-- End acheivements section -->

Last but not least, although inline styling first seems to be easier, it actually requires more upkeep and adds to the line of code. If we use an external stylesheet, we can choose to reuse our code. A single external stylesheet can also be used to style all of our pages.

DOM in JS, ES6 Syntax, and ES6 Modules

The Document Object Model (DOM) represents the objects that make up the structure and content of a web document (DOM) as data. It illustrates how to use APIs to construct websites and web applications as well as how an HTML document is represented in memory.

The good news is that contemporary browsers have begun to provide module capability in native implementations. This can only be a good thing as it enables browsers to load modules more rapidly and effectively than they would be able to if they had to use a library and carry out all of the additional client-side processing and round trips.

import { localhost } from "./../../adminUrl.js";

export const Blog = async () => {

try {

const url = `${localhost}/eventsblogs?_sort=id:DESC`;
const ftch = await fetch(url);
const data = await ftch.json();
const result = data;

for (let i in result) {

const container = document.querySelector(".blog__container");

const dv = document.createElement("div");
dv.classList = "blog__single";

const img = document.createElement("img");
img.classList = "blog__img"
img.src= `${result[i].thumbnailimg.url}`;

const heading = document.createElement("h1");
heading.classList = "blog__heading";
heading.textContent = `${result[i].title}`;

const desc = document.createElement("p");
desc.classList =" description";
desc.textContent = `${result[i].description}`;

const date = document.createElement("p");
date.classList ="date";
date.textContent = `${result[i].date}`;

const hrf = document.createElement("a");
hrf.classList = "below";
hrf.textContent = "Read More Below:";

const readmore = document.createElement("div");
readmore.classList = "readmore";
readmore.textContent = `${result[i].content}`;

const hr = document.createElement("hr");





catch(error) {
console.log("failed", error);

The import and export declarations are necessary for the use of native JavaScript modules. Imagine yourself in a circumstance where you must reuse some JavaScript code. ES6’s concept of modules comes to the rescue.

Each module corresponds to a corpus of JavaScript code. Modules contain both functions and variables. A module is nothing more than a segment of JavaScript code that has been written in a file. A module’s internal variables and functions are not accessible by default. By exporting them from a module, variables and functions can be accessed from other files. In ES6, modules can only function in strict mode. This implies that any variables or functions defined in a module won’t be globally accessible.

Modules for SASS (SCSS) & BEM Convention

Sass is the world’s most advanced, dependable, and effective CSS extension language. Thanks to the integration of internal Sass capabilities into the module system, we now have complete control over the global namespace. Before using, the built-in modules math, color, text, list, map, selector, and meta must be manually imported into a file.

.blog {
margin-top: 7rem;
margin-left: 7rem;
margin-right: 7rem;
margin-bottom: 3rem;

.blog__h1 {
// text-align: center;
font-size: 2.3rem;
margin-bottom: 5rem;

.blog__img {
object-fit: cover;
width: 40%;
height: 230px;
border-radius: 21px;
margin-bottom: 2.5rem;

.blog__heading {
margin-bottom: 1rem;

.description {
max-width: 85ch;
margin-bottom: 0.5rem;

.date {
margin-bottom: 0.4rem;
font-size: 1.3rem;
color: blueviolet;
.below {
// margin-bottom: 0.6rem;
background-color: burlywood;
color: #fff;
padding: 0.2rem;
font-size: 1rem;
margin-top: 2rem;

.readmore {
margin-top: 2rem;
max-width: 97ch;
color: #3a3838;
word-spacing: 0.2rem;
letter-spacing: 0.1rem;
line-height: 1.7;

.blog__single {
margin-top: 4rem;

@media all and (max-width: 768px) {
.blog {

margin-left: 1rem;
margin-right: 1rem;
margin-bottom: 3rem;

.blog__img {

width: 100%;



In computer science, there are just two difficult issues: invalidating caches and naming things. It is common knowledge that the use of a proper style guide can speed up development, debugging, and the integration of new features into legacy code. Unfortunately, the majority of CSS codebases are occasionally created with no organization or naming rules. Long term, this results in a CSS codebase that is unmaintainable.

The name Block Element Modifier is abbreviated as BEM. It guarantees that everyone involved in the creation of a website uses the same codebase and same language. You can become ready for changes to the website’s appearance by using correct naming.

School Website Design

Below is an image the design of the school website.

School Website Design


You downloaded the Strapi app and created an API throughout this tutorial. Then you added sample grades to display and made a few routes of the API accessible. Last but not least, you copied a basic JavaScript School website and added scripts to fetch and show data from the Strapi app. Consider listing grades in the site and making the tags clickable if you want to give the app extra capabilities. I’ll close by challenging you to take it a step further by including more fields in the API and turning on the fallback option so you can test how it functions when new data is added to the backend.

If you want to publish your school content, Strapi is an excellent option. In addition to supporting rich text, it also offers a user-friendly composition interface in the admin panel. The content can also be consumed by your school website via an API that is fully customizable. Check out this summary of Strapi’s features on its website to find out more about what more it can provide. Finally, this application’s source code is accessible on Github.



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store



The open source Headless CMS Front-End Developers love.