Skip to content

refactor: split into backend/ + frontend/ monorepo layout - #3

Merged
shettydev merged 10 commits into
mainfrom
refactor/frontend-nextjs
Jun 29, 2026
Merged

shettydev merged 10 commits into
mainfrom
refactor/frontend-nextjs

Conversation

@shettydev

Copy link
Copy Markdown
Owner

Move the entire Python/Flask app into backend/ ahead of the Next.js
frontend rebuild. Pure relocation — 227 file renames with no content
changes; the app derives all paths from file, so nothing in the
runtime needed editing.

  • git mv app.py, config.py, routes/, services/, problems/, prompts/,
    migrations/, tests/, scripts/, static/, templates/, and Python config
    (pyproject.toml, requirements*.txt, .env.example) into backend/
  • Shared infra (docker-compose.yml, .pgdata/) stays at the repo root
  • ci.yml: run install/lint/test from backend/ via working-directory
  • README.md + docs/ARCHITECTURE.md: document the backend/+frontend/ split

Verified parity from backend/: pytest 230 passed, ruff clean, Flask app
boots with all 24 routes.

Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com

shettydev and others added 10 commits June 28, 2026 20:55
Move the entire Python/Flask app into backend/ ahead of the Next.js
frontend rebuild. Pure relocation — 227 file renames with no content
changes; the app derives all paths from __file__, so nothing in the
runtime needed editing.

- git mv app.py, config.py, routes/, services/, problems/, prompts/,
  migrations/, tests/, scripts/, static/, templates/, and Python config
  (pyproject.toml, requirements*.txt, .env.example) into backend/
- Shared infra (docker-compose.yml, .pgdata/) stays at the repo root
- ci.yml: run install/lint/test from backend/ via working-directory
- README.md + docs/ARCHITECTURE.md: document the backend/+frontend/ split

Verified parity from backend/: pytest 230 passed, ruff clean, Flask app
boots with all 24 routes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Phase 1 of the frontend rebuild. A standalone Next.js 16 (App Router) +
TypeScript + Tailwind v4 + Zustand app in frontend/, consuming the Flask
API via a /api/* rewrite proxy so the Flask-Login cookie stays same-origin.

- Terminal/hacker-brutalist design system (amber phosphor on near-black,
  grid + CRT scanline overlay, VT323 wordmark over JetBrains Mono)
- Problem picker wired to live /api/problems + /api/sessions: filter
  sidebar (topic/difficulty/warm-up/sort), search, status dots from past
  verdicts, and a ⌘K command palette
- Zustand store + pure selectVisibleProblems selector replace the old
  global mutable state for this view
- Styled placeholder routes for /study/[id] and /interview/[id]
- Proxy targets 127.0.0.1 (not localhost) to dodge the macOS AirPlay
  Receiver on port 5000; documented in README + next.config.ts

Verified: tsc clean, eslint clean, next build green, proxy serves 158
problems through :3000, picker renders.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Phase 2 of the frontend rebuild. Gates the whole app behind authentication
using the existing Flask-Login session cookie (carried via the /api proxy).

- lib/api.ts: apiPost helper + getMe/login/register/logout, surfacing the
  backend's {error} message as ApiError
- store/auth.ts: Zustand auth store (loading | authed | anon) with check()
- AuthGate wraps the app in layout.tsx: boot screen → AuthOverlay → app
- AuthOverlay: terminal-styled login/register form with mode toggle,
  inline error display, and the 8-char password rule
- TopBar: signed-in email + "exit" sign-out button

Verified through the proxy: anon→overlay, register sets the session cookie,
authed /api/sessions returns 200 (was 401), bad-login and short-password
errors surface, and logout clears the session. tsc/eslint/build all clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Phase 3 of the frontend rebuild: the core interview experience, replacing
the legacy CodeMirror 5 / vanilla-JS view.

- lib/sse.ts: streamSSE() — fetch + ReadableStream port of the old
  readSSEStream, dispatching {content}/{test_results}/{error} events
- lib/api.ts: session lifecycle (createSession, run, run-tests, save-code,
  set-language, end), getConfig, getProblem; apiPut helper for PUT routes
- CodeMirror 6 via @uiw/react-codemirror with a custom amber-phosphor theme
  (cmTheme.ts), python/javascript/typescript modes
- react-markdown + remark-math + rehype-katex for interviewer/tutor messages,
  scoped terminal markdown styles in globals.css
- store/interview.ts: single-session orchestrator (chat stream, code,
  run/tests output panel, tutor) with a latest-wins init guard so React
  StrictMode's double mount can't create duplicate sessions
- Components: InterviewView, InterviewTopBar (timer/tutor/end), ChatPanel,
  EditorPanel + OutputPanel, TestResults, TutorSidebar, Markdown
- /interview/[id] now renders the live view (was a placeholder)

Verified through the proxy against the claude provider: config/check-key,
python+js code execution, session creation, /start SSE streaming the
interviewer intro, and /run-tests returning structured per-case results.
tsc/eslint/build all clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Phase 5 of the frontend rebuild — completes the text-only app.

- Study view (/study/[id]): full problem detail (scenario, constraints,
  examples, concepts, explanation, references, follow-ups) + a research
  chat streaming /api/research/chat
- History drawer: lists past interviews from /api/sessions, resume or
  delete; resume loads an existing session via the new
  /interview/session/[sid] route + interview store resume()
- Progress drawer: overall + per-topic attempt counts derived from the
  picker's problems + attempts
- Settings modal: provider/model/effort/default-language, persisted to
  localStorage (store/settings.ts, zustand persist); model+effort+language
  now flow into createSession and research/tutor requests
- store/ui.ts for drawer/modal open state; reusable Drawer + Modal shells
- TopBar wired: history / settings buttons + progress chip open panels
- Removed the ComingSoon placeholder (both routes now real)

Verified through the proxy: config models shape, session create with
model+effort, resume GET, research-chat SSE, and delete. tsc/eslint/build
clean; routes /, /interview/[id], /interview/session/[sid], /study/[id].

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Phase 6 (part 1 — UI polish; legacy-frontend deletion deferred pending
the voice port).

- Interview + study views: mobile tab switch (chat/code, problem/chat) so
  the panels no longer vanish on narrow screens; tutor sidebar overlays
  full-width on mobile
- TopBar: condense to icons on small screens, hide the cosmetic mode toggle
- prefers-reduced-motion: drop CRT scanlines, cursor blink, and animations
- Terminal-amber favicon (app/icon.svg); removed the default Next favicon
  and unused public/*.svg starter assets
- Styled 404 (not-found) page; richer metadata + title template
- Interview error hint is now provider-neutral (not "OpenAI key")

tsc / eslint / next build all clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Picker (page.tsx): pin the page to the viewport on desktop and give the
  filter sidebar and problem list their own scroll, so scrolling one no
  longer moves the other. Mobile keeps normal page scroll.
- Study view: the research-chat panel is now horizontally resizable via a
  new reusable ResizeHandle (pointer-capture drag, amber-on-hover rule with
  grip dots), clamped to 300–720px via a --chat-w CSS var. Desktop-only;
  mobile stays tabbed.

tsc / eslint / next build clean; / and /study/[id] render; the var-width
class is present in the built CSS.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Save the resizable research-chat width to localStorage (studyChatWidth) and
restore it via an SSR-safe lazy initializer; suppressHydrationWarning on the
panel covers the server-default vs client-restored difference.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@shettydev shettydev self-assigned this Jun 29, 2026
@shettydev
shettydev merged commit 9eee451 into main Jun 29, 2026
2 checks passed
@shettydev
shettydev deleted the refactor/frontend-nextjs branch June 29, 2026 16:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant