Skip to content
Swift IdeasStart a build
Swift Ideas
Start a build
Back to the work

Pharmaceutical quality consultancy (GxP)

SwiftGxP

A consultancy site, and the training platform behind its paywall.

SwiftGxP homepage hero on a dark navy grid: an 'RP & RPi Support' pill, the headline 'Getting it right doesn't have to be complicated', a gradient consultation button and an AI Training button.

Project facts

Problem
A regulated consultancy with one enquiry route, and a training plan that needed an audit trail rather than a course player.
Approach
Seven service pages, 16 reviewed articles and a training platform with Stripe checkout, gated quizzes and certificates.
Result
The site is live at swiftgxp.com. The training platform is built and stays behind a login until launch.
Client
SwiftGxP
Where
United Kingdom
Year
2026
Status
Live
Work
Brand websites, Web platforms

Our role

  • Site rebuild
  • Programmatic service pages
  • Structured data
  • Analytics and consent
  • LMS product definition
  • LMS build (Supabase and Stripe)
  • Content governance

Built with

Next.js 15.5 (App Router), React 19, TypeScript, Tailwind CSS v4, Framer Motion, Supabase (Postgres, RLS, Auth, Storage), Stripe Checkout (REST, signed webhooks), Resend, Google Analytics 4 (consent-gated), Vercel Analytics, node:test

The problem

SwiftGxP sells Responsible Person support, GDP consultancy, WDA(H) applications and audits to UK pharmaceutical businesses. The buyers are quality managers and directors who read carefully and distrust vague claims, and the old site had one enquiry route: an email link at the bottom of the page.

The consultancy also wanted to sell training. The first plan was a hosted course platform, but controlled training in a GxP setting needs evidence: who completed what, when, with what score, and who changed the course. That needs its own records, not a course player embedded in a page.

Every regulatory statement on the site carries the consultant's professional name. Content could not be published because it ranked; it had to be correct first.

What we did

We rebuilt the site in Next.js with one page per service line, each with its own FAQ, a page trail and structured data that tells Google what the service is, links into a topic-filtered article library, and an enquiry form we count on our side even when cookies are declined. Google Analytics loads only after the visitor accepts cookies.

The training platform was scoped in a written decision record before any database existed: roles, what is in and out of the first version, the pass mark, certificate fields and the audit events. It was then built one task at a time, with each task backed by its own test file.

Publishing runs through a checklist. Private and pre-launch pages are kept out of search engines, and every regulated post is reviewed by the consultant against authoritative sources before we ask Google to list it.

What we considered

The decisions behind the build, with the reasoning and the evidence for each.

SearchOne page per service, each described to Google in structured data

Buyers search for the role they need to fill, such as a GDP consultant or a Responsible Person, not for a consultancy. Each service line gets a page that answers that search in full, with structured data generated from one shared module so the markup cannot drift.

  • 7 service routes: GDP consultant, Responsible Person, WDA consultant, regulatory, QMS, ISO and lead auditor
  • src/lib/schema.ts builds Organization + ProfessionalService, WebSite, Service, BreadcrumbList, FAQPage and BlogPosting nodes
  • Course schema generated from the LMS catalogue for the training pages
  • Live sitemap: 32 URLs; /api/, /auth/, /admin/ and /training are disallowed in robots.txt
ContentA review step before anything goes to Google

Regulatory content is only an asset when it is correct. The publishing checklist makes domain review a step, restricts factual sources, and keeps the site inside the specialisms the consultant actually holds.

  • 16 articles in a topic filter: WDA(H), MAH, GDP, GMP and AI
  • Authoritative sources only: gov.uk and MHRA, the Human Medicines Regulations 2012, EMA and the European Commission
  • Competitor blogs are used for content-gap research and are never cited
  • A British English spelling test fails the build on 'behavior', 'personalized' or 'programs' in visible copy
DataAnalytics after consent, enquiries counted without it

A Google Analytics lead count misses every visitor who declines cookies, which on a business-to-business site is a large share. The site asks for consent before GA4 loads, and separately reports each delivered enquiry to our own monitoring on the server, with no personal data.

  • Consent stored under one localStorage key; gtag is injected only on 'granted'
  • A cookie settings button lets visitors change their answer later
  • Landing path held in memory for the visit only, so it needs no cookie or consent
  • An enquiry reached through a reload or a new tab is logged as unattributed, never credited to the form page
StrategyA training platform scoped by a written decision record, not a feature list

Course platforms grow into HR systems if nobody draws the line. The MVP decision record names four roles, lists what ships and what waits, and models organisations and seats in the schema so a later release does not need a migration rewrite.

  • Roles: guest, learner, organisation manager (read-only reporting) and SwiftGxP admin
  • In MVP: catalogue, Stripe Checkout, course player, per-module resources, quizzes, certificates, reporting, audit log
  • Deferred: SCORM and xAPI, subscriptions, seat pools, coupon UI, HRIS integration, offline playback
  • Seed course 'AI Essentials for Regulated Life Sciences' in five modules
TestingProgress that has to be earned

Completion evidence is worthless if a learner can skip to the end. Module access is gated on the previous module's required activities and quiz result, and the pass mark is stored per quiz so it can change without code.

  • Default pass mark 80%, held per quiz and module
  • The next module opens only after completion or a pass
  • Certificates carry learner, course title and version, completion time and a unique evidence ID
  • 38 test files; 24 are named for the ticket they prove, from SWI-272 to SWI-452
ShowHide the other 3 decisions
SecuritySigned payments and short-lived media links

We call Stripe directly rather than through its code library, so the check that each payment notice really came from Stripe is written by hand and tested. Paid course media is never public: the server checks enrolment, then issues a link that expires.

  • Stripe-Signature parsed and checked with HMAC-SHA256 and timingSafeEqual
  • Protected resources live in non-public Supabase buckets
  • Signed URLs last 5 minutes and are issued only after an enrolment or role check
  • Resource link generation and downloads are written to the audit log
DataAn audit trail sized for inspection

Training records in a GxP business can be requested at inspection years later. Every event that changes a learner's status is logged, and exports of the trail are themselves recorded.

  • Events for enrolment, lesson and module completion, quiz attempts, certificate issue, admin publication and resource access
  • Audit export register records requester, scope, format and event count
  • Seven-year retention expiry computed as a generated column
  • The register stores no raw exported content
DesignBrand purple, used sparingly

The brand guides set a purple and navy pair. The site uses the gradient for primary actions and the hero, and keeps service and article pages on cream and white so dense regulatory text stays readable.

  • Gradient: 135deg from #b44aff to #202c84
  • Section padding clamp(4rem, 8vw, 8rem); transitions at 150, 250 and 400 ms
  • Montserrat for headings at 600, Poppins for body from 300 to 600
  • Cream #faf8f5 behind long-form pages

Colour and type

  • Brand purple#B44AFFPrimary actions, links and gradient start
  • Brand navy#202C84Gradient end and headings
  • Deep navy#151C52Darkest primary step
  • Accent 600#9B3DE0Hover and pressed states
  • Charcoal#1E1E1EBody text and logo wordmark
  • Cream#FAF8F5Long-form page background
  • GDP Consultant UK

    MontserratHeadings

    Weights 400 to 700 loaded; headings default to 600. Taken from the SwiftGxP brand guides.

  • Specialist GDP compliance support for wholesalers and MAHs.

    PoppinsBody copy and interface

    Weights 300 to 600. The light weight is used for the hero subheading on the dark ground.

By the numbers

service pages with structured data for the service, FAQs and page trail
7
Source: Counted on the live site
reviewed articles in a topic-filtered library
16
Source: The live blog index, which shows '16 of 16 articles'
test files covering the site and the training platform
38
Source: Counted in the project's test suite. 24 files are named for the task they prove
commits, January to September 2026
168
Source: The project's commit history

Where it landed

The rebuilt site is live at swiftgxp.com with seven service pages, 16 articles, analytics that waits for cookie consent, and enquiries counted in our own reporting whether or not cookies are accepted.

The first version of the training platform is built behind a login: catalogue, Stripe checkout and enrolment, course player, gated quizzes, certificates, organisation reporting, automatic emails and the audit trail. The training section stays out of search and sends visitors to sign-in until launch.

We have not published traffic or enquiry figures here. Server-side enquiry counting started on 24 September 2026, which is too recent for a fair before-and-after comparison.

Start a build like this