Plan: Transitioning to Forward Deployed Engineer / AI Engineer
A phase-based roadmap for backend engineers moving into FDE and AI Engineer roles — decoding the title chaos, the applied LLM stack, and the interview loop.
Study a unit, pass a short check, and a window in your city lights up.
EducationJavaScript · CSSGitHub @zenoxdev1OnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Study app that turns your course material into a city you light up.
Taken from the repository README
Loading the full README.
Read the full README ↗Keep your lights on. A study app: your degree is a city, a semester is a district, a module is a building, a teaching unit is a floor. A light goes on when you pass the 5-question check for a unit (4 right, 80 %).
Unofficial student project, not affiliated with HSLU. Files stay on the device (IndexedDB). Progress stays in localStorage unless you turn on optional sync. Nothing is tracked.
index.html, privacy/, terms/, imprint/, connector/ public pages (landing, legal, ILIAS connector page)
app/
index.html, styles.css, manifest.webmanifest, sw.js the app shell and its service worker
app.js screens, routing, city drawing, sync, wiring (being split up step by step)
js/storage.js IndexedDB access: every write resolves only after the browser confirmed it
js/imports.js when a file counts as "added" or "imported" (failed writes never count)
js/quiz-core.js chunking with headings and pages, definition questions, quality rules, question bank, 5-question and 80 % rules
js/backup.js progress backup, full backup, checked restore, merge rules
vendor/, fonts/, icons
functions/api/ Cloudflare Pages Functions: sync, sign-in, optional AI questions
quiz.js the /api/quiz endpoint (limits, auth)
_quizlib.mjs the AI quiz pipeline: analyse, write, check, replace (pure logic, tested in Node)
db/schema.sql D1 schema for sync accounts
ilias-extension/ the browser extension that reads ILIAS (thin bridge)
tests/unit/ Node tests, no dependencies
tests/e2e/ browser tests (Playwright for Python)
docs/ setup notes
The app has no build step. app.js is loaded as an ES module (<script type="module">) and imports the files in app/js/. New files in app/js/ must also be listed in SHELL in app/sw.js, and VERSION there must be raised when the shell changes.
npx serve .
Then open http://localhost:3000/app/ (the port is printed). Opening the files directly from disk does not work: modules and file storage need http.
The app is available in English, German, Spanish and French. The language is picked from the browser on the first visit and can be changed in Settings (or on the welcome screen); the choice is kept in localStorage['booklyn:lang'].
English text in app/app.js is the source and also the dictionary key. Wrap every visible string with _t('...') (plurals: _pl(n, 'one', 'many'), placeholders: _tf('{n} files', {n: 3})), then add the German, Spanish and French versions to app/js/i18n-dict.js. tests/unit/i18n.test.mjs checks that every key exists in all languages and keeps its placeholders. Demo content and the legal pages stay in English.
node --test tests/unit/*.test.mjs # fast, no installs
pip install playwright && playwright install chromium
python3 tests/e2e/batch1.py # starts its own local server
python3 tests/e2e/batch2.py
What they cover: failed imports and retries without duplicates, import confirmation only after a successful write, complete chunking (no truncated text), cache refresh when files are added or removed, the 5-question and 80 % rule, wrong answers coming back first, full backup and restore (merge and replace), damaged and hostile backups.
/api/quiz. The server first analyses the material (subject, concepts with exact quotes, relations, objectives; it stops with a reason if the text is unreadable or too thin), then writes candidate questions, then checks each one with fixed rules (4 distinct options, no "all of the above", answer not in the question, no length giveaway, supporting quote must really occur in the material, answer words must be supported) and a second strict AI review. Failed ones are replaced once. Nothing unchecked is returned. The answer shows the explanation, the supporting quote and the source (file and page).AI_DAILY_CAP), each request makes 3 to 5 model calls. The model is AI_MODEL (default Llama 3.1 8B on Workers AI).The scan knows which ILIAS course every file comes from. The module is taken from the course: automatically when the course name contains the module code (e.g. I.BA_CONWB.H2601 and module CONWB), otherwise Booklyn asks once and remembers (iliasCourseMap). The week comes from the folder or file name; if there is none the file is marked "Check this". Ready files are collapsed in the Port: open the list to review or correct each file's module and week, or import directly.
.json): one JSON object with semesters, modules, lights, notes, deadlines, coins, city and decorations. No files..ndjson): one JSON object per line: header, progress, question sets, then every imported file (base64) with its module and unit, and an end line. Reading goes line by line, so large backups do not need one giant string.end line). Nothing on the device changes until that passes. Then you choose:
Booklyn works without any backend. For sync accounts and AI questions see docs/accounts-setup.md: a D1 database bound as DB (run db/schema.sql), optional Resend variables for email sign-in, and an optional Workers AI binding for /api/quiz. Deploy by pushing to main; Cloudflare Pages builds functions/ automatically.
Admins are declared only in Cloudflare Pages → Settings → Environment variables (Production), never in the app:
ADMIN_EMAILS: comma-separated email addresses (case-insensitive). Does not match sync-code accounts.ADMIN_UIDS: comma-separated account ids, for accounts created with a sync code.After redeploying, sign in with that account: Settings → "Admin tools" lets you switch on unlimited coins, set an exact balance or add coins. The server tells the app who is an admin through /api/me; nothing in the browser can grant it. On the public site ?dev=1 does nothing; it only works on localhost.
Connected to the GitHub repository: every push to main deploys. Manual option: npx wrangler pages deploy . --project-name booklyn after wrangler login.
[...] placeholders in the legal pages and .well-known/security.txt.MIGRATIONS in app.js for every schema change. The new how field (quiz or self-check) is additive and needs no migration.