Session log — WhatsApp isiXhosa course, plus the login fix that let everyone see it

← All session logs

Session log — WhatsApp isiXhosa course, plus the login fix that let everyone see it

3 May 2026 · Hasmukh with Claude · A new WhatsApp course in isiXhosa goes live on s2l.online, ten lessons pulled from Vimeo. Along the way a long-standing bug surfaced where logged-in learners were being shown the same buttons as guests; that gets fixed too. The top right of the site now swaps to My account once you sign in, with a softly outlined Log out sitting beside it. A leftover “kennjordan” byline that was showing under every page title is hidden. To round things off, a course-add playbook is written so the next course can be built without rediscovering the procedure.

Brief

1. The brief

HasmukhBuild a new isiXhosa course from Vimeo. The lessons are tagged WAxhosa. Call the course WhatsApp isiXhosa.

The shape of the work was the same as the SARS isiXhosa course on 30 April: lessons already exist on Vimeo in isiXhosa, with isiXhosa titles and descriptions. The job was to give them a home on s2l.online so an isiXhosa speaker can find them, take them in order, and have the whole course feel like one course rather than a playlist.

What was different this time was scale: ten lessons instead of six, and almost eighty minutes of content instead of twenty. Not a long form course by any stretch, but enough that putting the wrong order in front of a learner would be obvious.

Step 1

2. A WhatsApp course in isiXhosa, ten lessons

Searching Vimeo for the WAxhosa tag returned ten videos, all isiXhosa, all titled with an Isifundo number from 01 to 10. The numbering told us the order, the durations told us the runtime, and the descriptions provided ready-made isiXhosa copy under each lesson title. No translation work, no re-recording, just stitching.

The lesson list, in order:

#LessonLength
1Isifundo 01 Intshayelelo kunye noCwangciso4 min
2Isifundo 02 Ukuphonononga iThebhu yeSetingi9 min
3Isifundo 03 Ukuphonononga iThebhu yeeNgxoxo6 min
4Isifundo 04 Sebenzisa Ikhamera ye-WhatsApp Kalula6 min
5Isifundo 05 Ukuhlola iThebhu yeeFowuni4 min
6Isifundo 06 Ubuchule Beengxoxo Inxalenye 112 min
7Isifundo 07 Ubuchule Beencoko Inxalenye 216 min
8Isifundo 08 Ukusetyenziswa koLuhlu lokuSasaza kwi-WhatsApp7 min
9Isifundo 09 Ubumfihlo10 min
10Isifundo 10 Khusela i-WhatsApp yakho5 min

Total runtime is roughly 79 minutes. The course is free, level set to free, and surfaces automatically on the isiXhosa courses page next to the existing SARS series, because that listing is built from a language tag rather than a hand-curated list.

OutcomeThe course is live at /whatsapp-isixhosa/, listed alongside SARS2isiXhosa on /courses/xhosa/, and the lesson player loads each Vimeo video in order.
Step 2

3. The login bug we found along the way

Once the course was up, Hasmukh tried it as a learner: register, browse, click through to a lesson. He noticed the top-right button still said Start Learning Free even after he had logged in. That should not happen. Once you are signed in, the site is meant to swap that button for an account link.

The first try was the obvious one: replace the static link in the navigation with the [member-nav mode=cta] shortcode that the membership plugin already provides. That shortcode reads “am I signed in?” and chooses the right label. The change went in cleanly, but the result did not change. The button still said Start Learning Free.

Digging into why the membership plugin thought every visitor was a guest revealed a real bug in the login flow. PageMotor's auth cookie has a specific format: it is signed, with the username, a timestamp, and an HMAC, joined by pipes. The login flow in the membership plugin was writing the cookie in a much simpler form: just the username on its own. The browser kept that cookie quite happily, but every subsequent page load checked the cookie, found it didn't match the expected format, and treated the visitor as a guest. Hasmukh felt logged in (he had clicked Log In and seen a redirect) while the site quietly disagreed.

The fix was to make the membership login sign the cookie the same way the rest of the site does. Same expiry, same domain, same flags, but the value now carries the username, the issued-at timestamp, and the HMAC, in the format every other part of the site already expects. After Hasmukh logged out and back in, the navigation finally swapped to My account.

OutcomeThe membership login now writes a cookie that the rest of the site recognises. Logged-in visitors are recognised as logged in, on every page, on every reload. Worth a note to the EP Suite maintainers so the upstream plugin can adopt the signed cookie format directly.
Step 3

4. Easier log out

With the login state now visible to the rest of the site, the next obvious gap was logging out. Until today, signing out meant finding the small link at the bottom of the profile page. Hasmukh wanted it visible from the top of the page, on every page.

Three options were on the table: a click-to-open dropdown under My account, a single account button with a separate logout link in the profile page, or just two buttons side by side. The decision was the simplest one: two buttons in the top right.

The membership plugin's nav shortcode now returns two list items when a learner is signed in. The first is the existing red My account button, kept exactly as it was. The second is a softly outlined Log out button. The same pair appears in the mobile drawer, so a learner on a small screen can sign out without leaving the page they are on.

The visual balance between the two matters. A red button next to a second red button shouts; a red button next to a plain text link mumbles. The middle ground is a thin grey outline around Log out, transparent fill, dark text. It says “I am clickable” without competing with the primary action.

OutcomeSign out is one tap from anywhere on the site. Sign in is one tap from anywhere on the site. The header reflects login state honestly, on desktop and on mobile.
Step 4

5. The mystery “kennjordan” under every page

While testing the course as a learner, Hasmukh spotted a small italicised line under the page title on the watch page: kennjordan. It was on every page, not just the watch page, sitting between the heading and the body copy. It served no purpose to a learner. It was the page author from PageMotor's underlying schema, leaking through the theme.

The two ways to stop it are to remove the element from the page template, or to hide it with a CSS rule. Hasmukh's preference was clear: hide rather than remove, in case it is wanted back later for a different theme or a future change. A single CSS rule was added to the active theme's custom stylesheet, the stylesheet was recompiled, and the line is now invisible everywhere on the site.

OutcomePage titles now stand alone. The author element is still there in the markup if a future page or theme wants to surface a real byline; today it just doesn't show.
Step 5

6. A course-add playbook, so the next course is faster

One observation Hasmukh made afterwards was that adding a new course tends to be slow at the start of a session: the Vimeo token has to be tracked down, the right database tables remembered, the bug from a previous session (the one where lessons saved cleanly but had no video player because the wrong column was filled) re-learned and worked around. None of that is the interesting work; it is friction.

The fix is a written playbook, stored in Claude's memory, that loads into every new session automatically. It captures, in plain English: where the Vimeo token lives, how to search Vimeo by tag, the exact field shape for the two database tables a course needs, the field gotcha where a lesson must carry both the video URL and the Vimeo id, the row that creates the course's landing page, the fact that the language listing picks up the course on its own, the URLs to verify, and a rollback recipe if anything is wrong.

The other half of the agreement was about session shape. From the next course onwards, each one happens in its own fresh session. That keeps each session log focused, gives a clean git checkpoint to roll back to, and means the playbook only has to be re-read once per course, not per topic. A typical prompt to start a course-add session now looks like:

Build a new course on s2l.online.

Title: WhatsApp isiZulu
Slug: whatsapp-isizulu
Language: zulu
Vimeo tag: WAzulu
Description: A short course in isiZulu on getting started with WhatsApp on your Android phone.

That is enough for the playbook to take over: pull the videos, present the lesson list and total runtime for sign-off, then build the course and verify it on the live site, all in one transaction.

Going forward

7. Going forward

Three things remain. The first is short: write a polished isiXhosa course summary for /whatsapp-isixhosa/ in place of the generic one. The second is to repeat the WhatsApp course in the other South African languages once those translated recordings are uploaded to Vimeo with the matching language tag (WAzulu, WAafrikaans, and so on). The third is the upstream nudge to the EP Membership maintainers: the local cookie patch can become a one-line plugin update once they accept it back into the suite.

Out of all of today's work, the biggest unlock is invisible: logged-in learners are now recognised as logged-in across the whole site. Every future feature that depends on login state, paid courses, progress tracking, certificates, comment posting, can be built on top without a buried surprise underneath.