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.
Desker is the study planner that learns how you study, with a kodama that plans each day around you. Built for university students with deadlines, exams and tasks.
EducationJavaScript · TypeScriptGitHub @SinestreaPukkOnlineOwner 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
Real one
Translation pending
Taken from the repository README
Loading the full README.
Read the full README ↗The study planner that learns how you study, with a kodama that plans each day around you. For university students: deadlines, tasks and a calendar, planned around how long things really take you and when you focus best.
npm install
npx vercel dev # runs the app and /api locally (load .env.local first: set -a; . ./.env.local; set +a)
Look (tasteskill v2, editorial greeting): white ground, tonal pale-blue panels (#f3f6fc), Instrument Serif for the greeting and Instrument Sans for everything else, ink #14213d, calm pastel blue #b4caf0 for primary actions and active states, deep #35599a for links. Shadows only on floating things (menus). Colours and radii live in the @theme block of src/index.css; shared classes in src/ui.js; icons in src/icons.jsx. Check changes with node .agents/skills/design-taste-frontend/scripts/lint.mjs --app src.
Routes: /today, /tasks, /goals, /projects, /calendar (/ and /do-now go to Today). vercel.json rewrites them to index.html.
Layout:
Sections (Today opens first): Today (greeting, key numbers, "Right now" with ways to choose, coming up, your tasks, weekly review), Tasks (add, Eisenhower matrix or list, AI prioritise), Projects (something bigger than a task: an investment, exam or test; it owns tasks via projectId, shows progress, and the AI breaks it into tasks), Goals (pyramid, happiness goals, hobbies), Calendar. Every page opens with a Notion-style head (cover art, an icon on its edge, a big serif title). On the Tasks board each card has cover art and tag chips (box, due date, hours, steps, repeat). Screens live in src/screens/, shared pieces in src/components/ and src/shared.jsx. The previous UI is kept in legacy/.
Env vars (see .env.example): ANTHROPIC_API_KEY, DATABASE_URL (Neon Postgres), ADMIN_EMAILS (who may open the owner dashboard at /dsb; everyone else gets a 404). Accounts use Better Auth (api/_auth.js): set BETTER_AUTH_SECRET (openssl rand -base64 32), BETTER_AUTH_URL (the site origin), and RESEND_API_KEY + EMAIL_FROM for verification and reset mails (without a key, mails print in the server log and verification is skipped).
Database (db/schema.sql): users, goals, hobbies, projects, deadlines, tasks and ai_calls, linked by real foreign keys (a task's project, deadline and goal; deleting a project unlinks its tasks, deleting a user removes everything of theirs). A visitor only gets a users row once they have content or use the AI. users.email and users.auth_id are ready for accounts. api/_store.js maps the app's one document to these tables, unknown fields land in each row's extra jsonb. Apply or re-run with set -a; . ./.env.local; set +a; node scripts/migrate.mjs (also copies the old workspaces / usage tables, which are kept as a backup).
Tasks: done section with undo and weekly count, drag between boxes (or "Move to" in Details), steps, repeats. Calendar has month, week and day views; give a task a start time to see it as a block. Settings (gear): reminders (browser notifications, only while a tab is open) and JSON backup export/import.
npm test # unit checks for the pure logic in src/
Also: Replan my week (Calendar, the AI agent, or the banner when planned tasks slip) shows what moves and what is at risk before you apply it; a weekly goal-alignment card on Goals; energy check-ins in Today that teach the planner your best hours; a Pomodoro focus timer that logs real time on tasks; syllabus import in Deadlines.
Public API (/api/v1/tasks): Authorization: Bearer <API key> (Settings > API key). GET lists, POST {title, important, urgent, due, when, start, hours, readiness} creates, PATCH|DELETE ?id=<id> edits or removes. 300 requests/hour per key. Reload an open tab to see API changes.
Account API (for scripts and other clients; the app itself uses /api/auth/*): POST /api/signup, POST /api/login ({identifier, password}, email or username), POST /api/logout, GET /api/me, POST /api/forgot-password, POST /api/reset-password, DELETE /api/account. They are aliases for the Better Auth routes (api/auth/[...all].js), so the same checks and rate limits apply. Other methods get 405.
Rate limits (api/_rate.js, per id per hour, 4x per IP): AI 60, state 600, API 300. Over the limit: 429 with Retry-After; X-RateLimit-Limit/Remaining on every response. If the counter is down the request is refused (503).
Deadlines live in Tasks. A dated task is a deadline. "Check with AI" in a task's panel decides if it is one task (kept as is) or several (you choose to split; it then becomes a deadline card that owns the new tasks, and you can add your own tasks to it). Syllabus import is on the Tasks page. /deadlines opens Tasks.
Accounts: email + password. Passwords are salted scrypt hashes (never stored or logged in plain text) and are checked against the Have I Been Pwned breach list; 10 to 128 characters. Sessions are httpOnly cookies. Sign-up verifies the email, "Forgot password?" mails a one-hour link and signs out other devices. Every row in users, goals, tasks, ... belongs to the account id ("user".id = users.id). Data a browser saved before accounts existed is moved into the account on first sign-in. Auth rate limits, three layers: Vercel Firewall (edge), per IP per route ("rateLimit": sign-in 5/min, sign-up 5/h, reset and verification mails 3/h, social 10/min, all else 100/min), and per email across all IPs (auth_hit: 10 failed sign-ins per 15 min locks that account for the window, 3 sign-up / reset / verification mails an hour). Google and GitHub sign-in switch on when their *_CLIENT_ID / *_CLIENT_SECRET are set. Settings > Delete account mails a confirmation link (opened while signed in); it removes the login and every row of the user's data. /api/state and every AI endpoint answer 401 without a session.
Sign-in screens: split layout, a pixel-art high-rise skyline seen from an observation deck on the left (a different one per step: a night skyline with lit windows for sign-in, dawn for sign-up, a rainy night for password reset, snow for check-your-inbox, afternoon for the welcome questions) and the form on the right. The art is drawn by art/authoring/gen_city.py (npm run pixel:city) into public/pixel/city/ as separate layers (sky, clouds, three tiers of towers with haze between, the street, traffic lights, flickering windows, rain or snow, the ledge and mug steam) that src/Wallpaper.jsx moves with CSS steps; it also draws the header of the emails. Sign-up asks for name, username, email and a confirmed password (Show / Hide on each); sign-in takes email or username. The first sign-in asks two quick questions ("Who is Desker for?", "What do you want from it?"), saved as onboarding on the account. Emails (api/_mail.js) are HTML with a plain-text twin.
The kodama (Phase 5): the companion and the AI agent are one character. Its name is the user's (data.kodama.name, default "Kodama"); its voice and wellbeing rules live in src/persona.js and are also the opening of the chat prompt in api/chat.js. src/kodama.js decides how it feels, what it says, which ritual is due and how it grows (growth replaced XP, levels, quests and badges; the old XP total became starting growth once).
Rhythm data: the rhythm engine (src/rhythm.js) stores in the account document (rhythm, energyLog). db/migrations/001_rhythm.sql holds the tables for it; they are not applied automatically. Run it by hand on a branch database first.
Notifications (web push, optional): set VITE_VAPID_PUBLIC_KEY, VAPID_PUBLIC_KEY, VAPID_PRIVATE_KEY, VAPID_SUBJECT and CRON_SECRET (npx web-push generate-vapid-keys makes the pair). Then call GET /api/state?push=1 with Authorization: Bearer <CRON_SECRET> once an hour. A Vercel cron on a paid plan works; the free plan only allows daily crons, so use an external scheduler such as cron-job.org or a GitHub Action. Without the five variables the Settings toggle is hidden and the endpoint answers 503. What may be sent is src/pushPlan.js: a morning note at 08:00 and an evening one at 19:00 in the user's time zone, never in quiet hours, never after 5+ days away.
Analytics and beta health (optional, off by default): set ANALYTICS=on and VITE_ANALYTICS=on and apply db/migrations/002_events.sql to log first-party product events (the allow-list is src/analytics.js; a test checks that no property can carry free text). Events go to /api/state?events=1 and live in an events table tied to the account and deleted with it. The owner dashboard (/dsb) has a "Beta health" section: sign-ups and active people per week, D1 / D7 / W4 retention, tasks done per active user, how many finished tasks have a real duration, estimate error against Desker's plan error by weeks since sign-up, and companion rates. Most of it is computed from data the app already stores and works without the events table; the notification rate needs it and says so when it is missing.