Filari
Case study · Education website rebuild on Next.js + Strapi

How UNIVO School of AI, an AI certification school, got a course website its own team can run

UNIVO School of AI teaches live, faculty-led AI courses. On its old site, every fee, date and faculty change needed a developer. Filari audited the live server, planned a rebuild beside it, and moved the site onto Next.js and Strapi, with 73 of 73 checks passed.

univoeducation.com/schoolofai
UNIVO School of AI home page with all 15 programmes Programme search filtered to Business AI for HR and Talent Management programme page with curriculum
Apply Now form with OTP request
Enrolment order summary with launch offer and coupon field
Live
73/73checks passed
Screens from the rebuilt site. Programme dates and fees shown are UNIVO's 2026 preview content.
Problem
01

Every change needed a developer

Every fee, date and faculty change lived inside the code, on a Cloudflare-only stack UNIVO's own server could not run.

Solution
02

A rebuild beside the live site

A rebuild on Next.js 16, Strapi 5, MySQL 8 and S3, beside the live site, with all 15 courses moved across.

Result
03

A site the team runs itself

73 of 73 checks passed, pages respond in 66–115 ms, and the team edits every course from an admin panel.

15 + 83Courses and modules moved into the CMS
10Faculty profiles the team can edit
22/22Media files on S3 as WebP
3Logins: admin, student, faculty
In short

A Next.js Strapi website for a school that teaches AI

UNIVO School of AI runs live, faculty-led AI certification courses. Its website kept all course content in a code file and ran on a Cloudflare Workers stack, so every change needed a developer. Filari rebuilt it as a Next.js 16 site with a Strapi 5 CMS, MySQL 8 database and S3 media, migrated 15 courses, 83 modules and 10 faculty profiles, and passed 73 of 73 UAT, security and accessibility checks without touching the live site.

Key takeaways

  • 01Filari rebuilt UNIVO School of AI's website on Next.js 16.1.6, Strapi 5.39, MySQL 8 and Amazon S3, to the client's exact version list.
  • 0215 courses, 83 modules and 10 faculty profiles moved from a code file into a CMS the UNIVO team edits without a developer.
  • 03The new build passed 73 of 73 checks: 35 UAT, 13 security and 25 accessibility.
  • 04Pages respond in 66–115 ms, and all 22 media files are WebP on S3.
  • 05The rebuild ran in a separate folder on the same server, and the live site's restart count stayed unchanged throughout.

Project snapshot

A course website rebuild with a CMS the school runs itself

UNIVO School of AI
Client
UNIVO School of AI, part of UNIVO Education
Industry
Education: live AI certification courses
Project type
Website rebuild with a headless CMS
Filari's role
Audit, rebuild, migration, Salesforce leads, testing, handover
Technology
Next.js 16, Strapi 5, MySQL 8, Amazon S3, Salesforce
Timeline
Confirm

Our approach

  1. 01AuditRead the live server, read-only
  2. 02PlanRebuild instead of migrate
  3. 03Protect liveBackup, swap, rules, separate folder
  4. 04Rebuild15 courses, 83 modules, 10 faculty into Strapi
  5. 05IntegrateOTP check and Salesforce leads
  6. 06Test73 UAT, security and accessibility checks
  7. 07Hand overPlain-English docs, 204 tracked tasks
01
The problem

A course website that only a developer could change

UNIVO School of AI, part of UNIVO Education, offers AI certification courses taught through live classes with faculty, applied projects and a structured curriculum. Learners find a course on the website and enquire through a form that goes to the sales team.

The UNIVO team wanted to change a course fee. On the old site that meant a developer editing a code file and redeploying. The same was true for dates, faculty profiles, FAQs and every other piece of content.

·

All course, faculty and FAQ content sat in one code file.

·

The data lived on Cloudflare, not on UNIVO's own server, and images sat inside the project folder.

·

There was no student or faculty login.

What UNIVO wanted

  • Edit every course, module, faculty profile and FAQ without a developer.
  • Keep all data on UNIVO's own MySQL database and all media on S3 as WebP.
  • Add student, faculty and admin logins.
  • Build it all without disturbing the live site.
02
The audit

What the server audit found

Before writing any code, our team connected to the live server read-only and checked what was really running. The documents described a standard Next.js site. The server told a different story.

ExpectedFound on the server
A Next.js appNext.js on Vite + Cloudflare Workers, via a tool called vinext
MySQL databaseCloudflare D1 (SQLite); MySQL not installed
Node 20Node 22 required by the live code
Images on S3Images in the project folder
A stable server3.8 GB RAM, no swap, live process already restarted 9 times
The live code imported modules that only work on Cloudflare. It could not be moved. It had to be rebuilt.From Filari's server audit, 10 September 2026

So the plan changed from a migration to a rebuild: a clean Next.js 16 project with the same design and the same content, on standard code that runs on UNIVO's own server.

03
Live stays live

Rule one: don't touch the live site

UNIVO asked for the new build on the same server, so learners would keep using the live site while we worked beside it. We set rules before the first line of code and checked them at the end.

1

The live folder is read-only. The live process is never restarted.

2

All new work lives in a separate folder, with its own processes, port and web route.

3

Nothing is hardcoded. Every URL, key and path comes from one config file.

4

No secret ever goes into git or the browser. Every image is WebP.

Before starting, the team backed up the live site, added swap memory, and installed MySQL 8 and Node 20 alongside the live Node 22. At handover, the live site still answered every page, and its restart count was the same 9 it had been on day one.

04
What we built

Rebuilding it the standard way

The new site runs on the exact versions UNIVO specified: Next.js 16.1.6, Strapi 5.39, Node 20, MySQL 8 and Amazon S3. Here is what the team and learners get.

01

A CMS the UNIVO team runs

Change a fee or date without a developer

Courses, modules, faculty, live classes, resources, FAQs and site settings are all edited in the Strapi admin panel. Changes appear on the site within 60 seconds.

For: UNIVO content and admissions team
Strapi 5 admin panel: editing an AI course for UNIVO School of AI
02

15 course pages, built ahead of time

Fast pages that search engines can read

Each course page is generated at build time with its curriculum, fee card, faculty and FAQs, then refreshed from the CMS. Course pages respond in about 115 ms.

For: prospective learners
AI for HR and Talent Management course page on the rebuilt UNIVO School of AI site
03

Three separate logins

Each person sees only what they need

Admins log in to the CMS, students log in with their mobile and a one-time code, and faculty log in with email and password to see their own classes.

For: admins, students, faculty
Student and faculty multi-role login portal with mobile OTP verification
04

Media on S3, always WebP

Lighter pages, nothing stored on the server

Every uploaded image is converted to WebP and stored in UNIVO's S3 bucket. In testing, a 9 KB JPG became a 3 KB WebP, 69% smaller.

For: everyone who loads the site
Amazon S3 media asset manager with automatic WebP compression
05

Settings in one place

Move or rebrand without hunting through code

No URL, key, path or email address is written into the code. Everything comes from one configuration file, so changing it once changes it across the site.

For: UNIVO IT and future developers
NEXT_PUBLIC_BASE_PATH=/schoolofai
STRAPI_URL=••••••
S3_BUCKET=••••••
OTP_TEST_BYPASS_ENABLED=false

What a learner sees on the new site

UNIVO School of AI home page listing all 15 programmes
Home

All 15 programmes in one place, each pulled from the CMS, so a new course appears without a code change.

Programme search filtered to the Business track
Find a programme

Learners filter programmes by track, such as Business, and reach the right course faster.

Programme page with curriculum, fee card and faculty
Programme page

Curriculum, fee card, faculty and FAQs, all editable by the UNIVO team in Strapi.

Apply Now form with OTP
Apply

A verified mobile number and a saved lead before anything is sent to Salesforce.

05
Enquiries

From enquiry to Salesforce, without losing a lead

A learner presses Get AI Certified Now, enters their details and verifies their mobile with a one-time code. The number is checked in the browser and again on the server. The enquiry is saved first, then sent to Salesforce.

DetailsName, mobile, course
OTPCode sent to the mobile, checked on the server
SavedLead stored in MySQL first
SalesforceLead forwarded to the sales team
StatusResult recorded on the lead
Apply Now enquiry form on the UNIVO School of AI site, with mobile number and OTP request
If Salesforce is down, the lead stays in the database marked as failed. No enquiry disappears.How the lead flow is designed

Found in our own review, then fixed

UNIVO asked that test numbers starting with 23 skip the OTP during UAT. Our security review found that the lead code checked for "starts with 23" but not for "are we in UAT". In production, a real learner whose number began with 23 would have seen a thank-you message while their lead never reached Salesforce. The check was fixed before handover, and the bypass is now switched off in production by three separate checks.

06
Results

Proving it works, before anyone relied on it

UNIVO School of AI now has a course website its own team can update, running on its own server and storage, with enquiries flowing to Salesforce and a full record of how every part works.

Enquiries after launchMetric pending
Content changes made without a developerMetric pending

Checks passed, by type

UAT35/35
Security13/13
Accessibility25/25

What else was verified

  • Leads, students and enrolments return 403 without a token
  • No API token or secret in the browser bundle
  • Nightly database backup at 2 a.m.
  • Live site pages all returned 200, restart count unchanged
Source: Filari UAT report, 11 September 2026.
07
Handover

Handing it over so nobody depends on one person

Every part of the system is written down in plain English: the audit, the architecture, each CMS field, every API, deployment steps, the security checks and the test plan. A project tracker followed 204 tasks, and a credentials handover moved every secret safely to UNIVO.

Where AI helped, and where people led

Tools to confirm

Human-led, AI-accelerated. Our team made every design and architecture decision and reviewed every change. The tools used will be listed once confirmed.

What we learned

Read the server before you quote a migration. UNIVO's documents described a standard Next.js site, but the server ran Cloudflare-only code. Checking first turned a migration that would have failed into a planned rebuild. For course websites, the content model matters more than the pages: once courses, modules and faculty are records in a CMS, the school can run its own site.

What's next: automatic retry for leads that fail to reach Salesforce, a shared rate limiter if the site scales to more than one process, and a planned upgrade window for Strapi and Next.js. Confirm

For tech teams

Under the hood

Stack, architecture and engineering decisions

Stack by layer

Frontend

Next.js 16.1.6
Static course pages, 60-second refresh

SCSS + Tailwind
The live design ported exactly

CMS

Strapi 5.39 on Node 20
Programmes, faculty, sessions, resources, leads, students, enrolments

Custom OTP + lead APIs
Rate-limited, bypass off in production

Data & media

MySQL 8, localhost only
Nightly backup at 2 a.m.

Amazon S3, WebP
No media stored on the server

Architecture

The browser talks only to the Next.js server. Next.js renders pages and exposes small same-origin API routes for OTP and leads, which call Strapi on localhost. Strapi reads and writes MySQL, stores media on S3 and forwards verified leads to Salesforce.

Browser Nginx Next.js 16pages + BFF routes Strapi 5localhost MySQL 8 Amazon S3 OTP gateway Salesforce

Engineering decisions

DecisionWhyImpact
Rebuild, not migrateThe live code imported Cloudflare-only modules that cannot run on NodeA clean, standard codebase UNIVO can host anywhere
Build beside live, not over itThe live site had to keep runningLive restart count unchanged through the project
Save the lead before calling SalesforceA Salesforce outage must not lose an enquiryFailed sends stay in the database, marked failed
Browser never calls the CMS directlyAPI tokens in a JS bundle are publicZero secrets in the browser bundle
Nothing hardcodedURLs and keys change between beta and liveOne config file drives every environment
Audit the test-number bypassCode that looks right can fail silentlyFixed a bug that would have hidden real leads
FAQ

Questions teams ask before a rebuild

The old UNIVO School of AI site ran Next.js on a Cloudflare Workers toolchain and imported modules that only work on Cloudflare. That code cannot run on a standard Node server, so Filari rebuilt it as a clean Next.js 16 project with the same design and content.

Yes. Courses, modules, faculty, live classes, resources, FAQs and site settings are all edited in the Strapi admin panel. Changes appear on the website within about 60 seconds, with no code change or deployment.

Filari built the new site in a separate folder on the same server, with its own processes, port and web route. The live folder was treated as read-only, and the live process's restart count was checked before and after to confirm it was never disturbed.

A learner enters their details and verifies their mobile with a one-time code. The enquiry is saved in the database first, then sent to Salesforce, and the result is recorded. If Salesforce is down, the lead stays in the database marked as failed.

Filari ran 73 checks on the new build: 35 UAT tests covering versions, data, media, OTP and pages, 13 security checks and 25 accessibility checks. All 73 passed, and the live site was confirmed unaffected.

Strapi gives non-technical staff an admin panel for structured content like courses and modules, and MySQL keeps that data on the client's own server. Together they replace content that was previously hardcoded in a file.