forgia · dev log
Engineering log for the forgia LMS platform.
- 24 Aug 26Six Copies of a Nav, Four Kinds of Drift
A client reported one missing link. The link was missing because the Student topnav had been hand-copied into six templates, and by the time anyone looked, the six copies disagreed about four separate things — including one that hid the Catalog from exactly the visitor who had not bought anything yet.
phoenixliveviewcomponentsrefactoringdesign-systemelixir - 16 Aug 26The One Place morphdom Cannot Reach
A Video Lesson was rendering into a 680px column built for prose, which made text on screen unreadable. Fixing the frame was a CSS min() of three terms. Fixing the sidebar that had to get out of its way meant finding somewhere to keep state that a LiveView patch could not quietly undo.
liveviewvideocssjavascriptmorphdomdesign-system - 09 Aug 26Two Fields Are Not a Template Language
A bulk invite should read like something a person wrote. That takes one textarea, two merge fields, and a surprising number of decisions about what not to build — including a debounce that would have quietly eaten the last word of every message.
emailphoenixliveviewdesign-systemproduct - 09 Aug 26The Invitation That Knows Who You Are
An Invitation is bound to one exact email, so a typo at sign-up throws it away. The fix is a query param the registration screen trusts only as far as the database backs it — plus the enumeration oracle that opened underneath it, and the rate limit that caught my own verification script.
securityonboardingphoenixemaildesign-system - 05 Aug 26Dealing the Card Deck
An animated card game whose round runs entirely on the server. The obvious design was the opposite one, and two facts about this repo killed it. Plus a wrong Check that tells you which Cards are wrong and never where they belong, and three bugs no green test suite could have found.
liveviewgroupingjavascriptanalyticsdesign-system - 04 Aug 26Retake a Quiz
A completed Quiz Lesson was a dead end. Now it offers a Retake — one QuizAttempt row rewound in place, a Completion that is never revoked, and a Course-complete redirect that finally learned to ask whether anything new actually happened.
liveviewquizectoddddesign-system - 04 Aug 26Authoring a Grouping Lesson
A sixth Lesson type, and the first whose draft is allowed to be wrong. The rules gate Publish instead of Save, colours stay distinct by swapping rather than erroring, and three bugs that no green test suite could have found.
liveviewgroupingectoddddesign-system - 03 Aug 26References on a Lesson, and a Bibliography That Compiles Itself
Typed References attached to a Lesson, rendered as an endnote and compiled into a Course-wide Bibliography grouped by Chapter — plus the LiveView bug that stayed invisible to sixteen green tests and took a real browser to find.
liveviewectojsonbdesign-systemdddtesting - 23 Jul 26Localized App Interior & Emails: Finishing What the Landing Page Started
Spreading the EN/pt-BR Locale infrastructure from landing and catalog into the Studio, the student learning screens, and every transactional email — plus three real bugs the sweep turned up along the way.
gettextliveviewi18ndesign-systemddd - 23 Jul 26Find the Sentence: Manual Markers, Instructor Feedback, and a Bug the Browser Caught
Three small upgrades to Sentence Selection — Prompt images, instructor-authored completion messages, and manual || markers replacing the punctuation auto-split — plus a cross-field data-loss bug that only a real browser run surfaced.
liveviewsentence-selectionectodesign-systemddd - 20 Jul 26A Real Front Door
The root route stops being a dev-only nav page and becomes a public Landing Page — nav, hero, methodology, instructor bio, and a live course catalog — while reusing the exact catalog card and Paddle pricing already built for /catalog.
liveviewphoenixgettextpaddledesign-system - 17 Jul 26Sentence Selection, and the Refactor It Forced
A fifth Lesson type — the student selects every sentence in a passage that matches a Prompt, checked server-side with no reveal — and the LiveComponent-per-type refactor it took to add it safely.
liveviewsentence-selectionectodesign-systemdddarchitecture - 15 Jul 26The Feature Was Named After the One Thing It Must Never Do
The Card asked for a banner warning users about downtime. The design system called the section 'Maintenance mode'. Building it well meant refusing that name — because the whole point of this banner is that the site stays up.
liveviewectopostgresddddesign-systemsecurity - 13 Jul 26A Course Worth Clicking: Thumbnail, Intro Video, Highlights
A Course gets a catalog preview — a Thumbnail, an ungated Intro Video, and a What-you'll-learn list — authored from a new Landing page tab. Plus two bugs that only a real browser could find: a form that ate its own inputs, and a phantom row conjured by LiveView on every keystroke.
liveviewectodesign-systemuploadsddd - 11 Jul 26Word Match Lessons
A fourth Lesson type: the instructor marks Blanks in a passage with four delimiter pairs, the student refills them from a shuffled Word Bank salted with Distractors, and the server checks — returning nothing but a count of errors.
liveviewword-matchectodesign-systemdddsecurity - 27 Jun 26One page, three screens: the tabbed Course studio
Managing a Course used to mean bouncing between three separate screens — curriculum, students, settings — each with its own URL, its own header, its own back button. This slice folds them into a single tabbed page with a persistent header and the Publish button re-homed where you actually look for it. No new features inside the tabs: every tab is the old screen, relocated unchanged. The interesting decisions are structural — one LiveView for every tab, deep-linkable routes switched with push_patch, legacy URLs that redirect so nobody's bookmarks break, and a breadcrumb deliberately deleted.
sliceliveviewroutingdesign-systemrefactor - 25 Jun 26A Certificate is a promise you can't take back
Students now earn a publicly verifiable Certificate the moment they complete every Lesson in a Course. The feature is small; the decision underneath it isn't. A credential that can be revoked retroactively — because the Instructor added a Lesson, or the Student renamed their Profile — is worthless. So the Certificate is a permanent, immutable snapshot. Plus the name gate that defers issuance, why issuance lives in the domain and not the LiveView, and a 320px overflow the design mockup didn't warn us about.
slicecertificateliveviewdddadrdesign-system - 22 Jun 26A profile page, two navbars, and a Profile that doesn't exist yet
Users can now set their own name and avatar on a /profile page. The decision worth writing down isn't the form — it's that a Profile is created lazily, on the first Save, because self-registered magic-link users never had one. Plus the Ecto trap that silently skips the write, why the dropdown got built twice, and the value of reading the design system before inventing CSS.
sliceprofileliveviewectodesign-systemddd - 17 Jun 26Studio Usability Polish
A batch of usability fixes across the instructor studio: a styled confirmation dialog before destructive deletes, a reorder bug fix for tied positions, names-as-links for cleaner grids, auto-focus on the first field, and a dev-only home page that maps both perspectives.
polishusabilityliveviewdesign-systemstudio - 17 Jun 26Student Takes a Quiz
The student-facing side of Quiz Lessons: one question at a time, immediate per-question feedback, a resumable in-progress attempt, a stale-reset when the instructor edits mid-attempt, and a Completion recorded on the final correct answer.
liveviewquizectodesign-systemddd - 17 Jun 26Slice 7: Quiz Lessons
Instructors can now add Quiz Lessons with single-choice Questions — a three-panel editor for writing questions, typing answer options, marking the correct one, and reordering. Students taking the quiz is a separate slice.
slicequizquestionsliveviewectodesign-system