CISNET: IT certification training.
Marketing site + SEO rebuild.

Migrated a Toronto IT certification training company off legacy PHP onto Next.js 16. Pages generated from data, a lead pipeline, and an admin portal, in three months, solo. Search rankings preserved through a 70+ URL redirect map.

CLIENT
IT Training · Toronto
SCOPE
Site + SEO + Pipeline + Admin Portal
SHIPPED
2025-Q4 · 3 MO
ROLE
Solo · Full build
01 / 05THE PROBLEM

Legacy PHP that couldn't grow.

CISNET's site was a hand-coded PHP build from 2014. One person knew where everything lived. Nobody else could ship into it without an outage. Marketing wanted new certification pages, ads into specific groups, and leads captured into a CRM. Every new page meant a risky deploy.

The bigger risk was search rankings. The old site ranked for ~70 cert-related searches, and any redesign that didn't keep those URLs risked tanking organic traffic for months. ~40% of new business came from that traffic.

  • Brittle stack: PHP 5.6, no tests, manual FTP deploys
  • No lead handling: contact form to email, no CRM, no admin view
  • Rankings at risk: 70+ ranked URLs that couldn't break
  • Marketing blocked: no landing pages without engineering
02 / 05THE APPROACH

Next.js 16, pages at scale, and a lead pipeline.

Three tracks over 12 weeks. Track 1 (weeks 1-4): stood up Next.js 16, Supabase, and Vercel, copied the marketing pages over exactly, and tested the redirects. Track 2 (weeks 4-8): 200+ pages, one per certification and city, generated from a single content source, plus a sitemap and structured data that tells Google what each page is. Track 3 (weeks 8-12): the lead pipeline. Facebook lead ads flow in through a verified connection, land in Supabase, show up in the admin portal, and trigger email through Resend. Stripe handles payment for paid courses.

The hardest early call was the redirect strategy. I mapped every old URL by hand instead of using a single catch-all rule. It was slower to build, and Google indexed the new URLs with full ranking value inside 6 weeks instead of 6 months.

  • Foundation: Next.js 16, TypeScript, Supabase, Vercel
  • Pages at scale: 200+, one per certification and city
  • Redirects: 70+ old URLs mapped one by one, not catch-all
  • Structured data: 7 types so Google reads each page right: Course, LocalBusiness, FAQPage, Organization, BreadcrumbList, ContactPoint, WebSite
  • Lead pipeline: Facebook lead ads to verified connection to Supabase to admin portal to Resend
  • Payments: Stripe Checkout for course enrollment
03 / 05THE STACK

Boring, fast, debuggable.

The default stack: Next.js, Supabase, Vercel. A CMS was an option, but the page volume didn't justify the overhead. Page content lives in the repo as MDX, and copy ships through pull requests.

Next.js 16 TypeScript Vercel Supabase Tailwind Stripe Resend FB Lead Ads API MDX Zod React Hook Form Plausible
04 / 05THE TIMELINE

12 weeks. 3 tracks. Scope locked on day one.

Scope locked in week 0. Anything new went onto a v2 list, and none of it shipped during the engagement.

WK 0Kickoff and scope lock. Written spec signed. Redirect map drafted from server logs.
WK 1–4Foundation. Next.js 16 setup, marketing pages copied over exactly, Supabase, Vercel deploys, redirects tested.
WK 4–8SEO. 200+ pages, one per certification and city, 7 structured-data types, sitemap and robots.txt, internal links.
WK 8–12Pipeline. Verified Facebook lead-ads connection, admin portal, Resend email, Stripe checkout and payment handling.
WK 12Cutover and monitoring. Production deploy, DNS swap, redirects live, Plausible, Search Console and Sentry wired up. 14-day support window.
05 / 05THE IMPACT

What it changed.

Numbers from the engagement, technical only. Business KPIs are CISNET's to share.

PAGES AT SCALE
200+
One per certification and city. Indexed within 6 weeks of cutover.
LEGACY URLS KEPT
70+
Mapped one by one. Rankings preserved on every URL.
STRUCTURED DATA
7
Types that tell Google what each page is: Course, LocalBusiness, FAQPage, Organization, BreadcrumbList, ContactPoint, WebSite.
LIGHTHOUSE PERF
98+
Performance score across every marketing page.
ADMIN PORTAL
FULL
Leads, enrollments, content, payments. Built from scratch on Next.js and Supabase.
SHIPPED IN
3 MO
Fixed price. Fixed scope. All 3 tracks shipped as agreed.

Marketing now ships new certification pages through MDX without engineering. Leads are traceable from ad click to enrollment. Ads now target specific group and city combinations that had no landing page before.

The admin portal I built.

The contact-form-to-email setup became a full operations console: lead pipeline, students, enrollments, email campaigns, content, and analytics, built from scratch on Next.js 16 + Supabase. No off-the-shelf CRM, no third-party analytics tax. The team runs the business from here.

CISNET admin portal dashboard: new leads, pipeline, enrollments and revenue KPI cards above a recent-leads list
Pipeline at a glance Live lead and pipeline counts with the latest leads inline. Customer details and month-to-date business figures blurred for this case study.
CISNET admin portal traffic-sources analytics: channel distribution donut with page-views and leads broken down by channel
First-party analytics Channel attribution for page views and leads, from my own event pipeline, no third-party analytics dependency.
CISNET admin portal SEO overview: live Google Search Console clicks, impressions, top queries and top pages
Search Console, in-app Live GSC clicks, impressions, top queries and pages via a service-account API integration I built in.

Early SEO traction.

I took over the SEO operation in late April 2026: rebuilt the content architecture and structured data, fixed the technical foundation (canonicals, redirects, Core Web Vitals), and shipped a free tools and study-resource layer (subnet calculator, practice quizzes, cheat sheets). It's early, and the reach and visibility signals that move first are all up. Measured in Google Search Console across 28-day windows ending April 30 against June 18, 2026:

Search impressions
7,600 to 22,500 per 28 days. Monthly impressions up 108% from April to May.
Ranking pages
5.4×
27 to 145 distinct pages earning search impressions.
Query footprint
855 → 1,000+
Distinct queries the site surfaces for (GSC reporting cap reached).

Source: Google Search Console, sc-domain property, queried live via a service-account API integration I built into the admin portal. Clicks up ~19% over the same window and compounding as the larger footprint matures; off-page authority is the next focus.

Google Search Console 16-month performance for cisnet.ca: 1.66K clicks and 104K impressions, trending upward
16-month trajectory 1.66K clicks · 104K impressions, accelerating in recent months.
Google Search Console page indexing for cisnet.ca: 145 pages indexed, the indexed count rising over time
Indexed footprint 27 → 145 indexed pages as the new architecture matured.
Google Search Console top queries for cisnet.ca, ranking for commercial CCNA terms beyond the brand name
Query footprint Ranking well beyond the brand into commercial CCNA terms.

Live Google Search Console dashboards. Account identity blurred; all metrics unedited.

Pravine turned our organic traffic around. We're ranking for searches that sent us nothing before, and he was genuinely easy to work with.
MP
Mani POps Lead · CISNET
Note: Search performance above is from Google Search Console. Downstream business KPIs (lead-to-enrollment rates, MRR impact) are the client's to disclose and aren't shown here.

Similar work: a legacy stack to migrate, SEO to preserve, lead infrastructure to build. Discuss the project →