Signing in signs everyone else out
A new sign-in ends every other session on the account.
A learning platform for paid, recorded courses where the hard problem is not playing video — it is stopping it from being shared. Every stream carries a watermark unique to the viewer, access depends on where the student is watching from, sessions are locked to one device, and progress is tracked to the second.
I built it twice in 2021: a first version on CodeIgniter 4 in about a month, then a rebuild on Laravel 8 with a real-time admin and stricter, location-aware access control.
One login passed around a class, or one screen recording posted online, and a course stops earning.
Students were meant to watch at a registered study centre, at home, or either — and the platform had to know which.
Blocking every recording is impossible. Making every recording point back to the student who made it is not.
Content organised as modules, lessons and topics, with a course built from a module and a chosen set of lessons.
Admins enrol students one by one or in bulk, each with a policy: study centre only, home only, or both.
DRM playback through short-lived tokens, with a watermark unique to the viewer on every frame.
Centres recognised by their public IP, each with its own watermark design.
Watch position and time tracked to the second, rolled up by course, enrolment, module, lesson and topic.
Attachments per lesson, downloaded through signed links.
Uploads go straight to the video host; a signed webhook registers each video when it has finished processing.
Every admin page updates live as students, enrolments and content change.
One record per student, enrolment and topic, created on first view.
Is the request coming from a registered study centre? If not, the student is treated as watching from home.
A centre-only enrolment cannot stream from home, and the reverse.
When required, home viewing is locked to the IP address and browser recorded at the student’s first sign-in.
The server asks the video host for a playback token valid for five minutes, carrying the viewer’s watermark.
Name, phone, email, username, ID or IP — whichever fields the centre chooses — are written onto the video for that one stream.
Fixed text at a set position, or moving text that relocates at an interval so it cannot simply be cropped out.
Colour, opacity, size and position are configured per study centre, including patterns that repeat across the frame.
The watermark travels with the five-minute playback token, so it cannot be removed on the student’s side.
A new sign-in ends every other session on the account.
The stream page checks its session every 30 seconds and leaves the moment it has been revoked.
Credentials are checked first; the session is then opened through an encrypted, signed link that lasts 30 seconds and only works from the same IP.
Pausing hides the player and leaves full screen, removing the easiest moment to capture a frame.
The player seeks to the furthest point reached and counts how many times a topic was opened.
Position and cumulative watch time are recorded while the video plays — and only while the device is online.
The furthest-watched position never moves backwards, and a topic is marked complete when the video ends.
Completion rolls up by course, enrolment, module, lesson and topic for the admin team.
Model observers fire 43 broadcast events — created, updated, status changed, deleted — over private channels.
A status event fires only when the status actually changed, not on every save.
Admin lists and detail pages refresh their tables and show notices as colleagues work.
Moving a topic or lesson to another module re-points every progress report that depends on it.
Behind it: JSON API controllers kept separate from page controllers, 74 permission gates, 40 validated request types, and bulk user and enrolment import that validates every row and reports errors, saved rows and issues separately.
~15k lines: modules, lessons and topics; DRM streaming with moving watermarks; multiple-choice quizzes with reports; support tickets with replies; email templates; user logs; and a JSON API behind the admin.
Study centres and location policies, device and connection pinning, per-centre watermark designs, second-by-second progress, a real-time admin over private channels, a webhook-fed video library and a clean split between API and page controllers.
A recording can always be made; a recording that names its maker is a deterrent.
Each rule is small, testable and runs in a fixed order before any token exists.
A copied player link stops working almost immediately.
Where a student may watch is a property of what they bought, not of their account.
Scrubbing back to rewatch a section never erases what was already watched.
Pages stay thin; every action is a JSON endpoint the real-time UI can call and refresh.
A video is only added to the library when the host confirms it is ready to play.
Real-time updates and location rules needed a different structure, and the product was young enough to change it.
DRM streaming with per-viewer watermarks and five-minute tokens.
Study-centre, home and device rules enforced before every stream.
Second-by-second progress, resume and completion reports at every level.
A real-time admin with bulk import, permissions and a webhook-fed video library.
I designed, built and coded the platform: the first version on CodeIgniter 4, then the Laravel rebuild — the course and enrolment model, the stream access checks, forensic watermarking, session security, progress tracking, the real-time admin and the video library integration.
Built for Core by Phei & Co, where I was an independent contractor from 2019 to 2022. The product brand is kept confidential. The watermark shown is an illustration with made-up values.
v1 shipped February 2025. Sites, SSL, PHP, databases, backups and WordPress itself are run from the browser, with Stripe billing on top.
Read the case study →SaaS backend · Cloud marketplaceShipped to production. Licences verify offline, so a vendor outage never stops a paying customer, and support moved from engineering to audited operator actions.
Read the case study →Next