Skip to content

Repository files navigation

CodeFTC

Codecademy-style interactive learning platform for FTC (FIRST Tech Challenge) programming in Java. Students read lesson content in a left panel and write/run real Java code in a Monaco editor on the right. Code is compiled and executed entirely in the browser using CheerpJ (a WebAssembly-based JVM), with automated test results returned in real time.

Tech Stack

LayerTechnology
FrameworkNext.js 16 (App Router, Turbopack)
LanguageTypeScript
StylingTailwind CSS 4
EditorMonaco Editor
DatabasePostgreSQL 16 + Prisma ORM
AuthNextAuth.js v5 (GitHub, Google, Discord)
Java ExecutionCheerpJ 3.0 (in-browser WASM JVM)
Package ManagerBun

Local Development

Prerequisites: Bun, a PostgreSQL instance (provided via Docker Compose).

# Install dependencies
bun install
# Start PostgreSQL
bun run db:up
# Run database migrations
bun run db:migrate
# Build CheerpJ assets (compile FTC stubs JAR + download OpenJDK 8 tools.jar)
bun run build:cheerpj
# Download the FTC Robot Controller template (needed for project downloads)
bun run setup:ftc-template
# Start the dev server (Turbopack)
bun run dev

The app is available at http://localhost:3000.

Environment Variables

Copy .env.docker.example to .env.local and fill in the values:

VariableDescription
DATABASE_URLPostgreSQL connection string
AUTH_SECRETRandom secret for NextAuth (openssl rand -base64 32)
AUTH_TRUST_HOSTSet to true in development
ADMIN_EMAILSComma-separated list of admin email addresses
GITHUB_ID / GITHUB_SECRETGitHub OAuth app credentials
GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRETGoogle OAuth credentials
DISCORD_CLIENT_ID / DISCORD_CLIENT_SECRETDiscord OAuth credentials

Scripts

ScriptDescription
bun devStart dev server
bun run buildProduction build
bun run lintESLint
bun run build:cheerpjCompile FTC stubs JAR and download tools.jar for browser execution
bun run docker:up / downStart/stop Docker Compose services
bun run db:migrateRun Prisma migrations
bun run db:studioOpen Prisma Studio
bun run db:resetWipe and restart the database
bash scripts/build-and-push.shBuild and push the Next.js Docker image to the registry

Project Structure

app/ # Next.js App Router pages and API routes
api/progress/ # Student progress (load/save code)
api/analytics/ # Event tracking and code run recording
api/download-project/ # Download code as FTC project ZIP
api/admin/ # Admin analytics and config
lessons/[module]/[lesson] # Dynamic lesson pages
components/ # React components
content/lessons/ # Lesson content (one directory per lesson)
lib/ # Utilities
cheerpj-executor.ts # In-browser Java compilation and execution
cheerpj-context.tsx # CheerpJ runtime initialization provider
lessons.ts # Lesson metadata loader
types.ts # Shared TypeScript types
ftc-stubs/ # FTC SDK stub classes compiled into ftc-stubs.jar
public/cheerpj/ # CheerpJ runtime assets (ftc-stubs.jar, tools.jar)
prisma/ # Database schema and migrations
e2e/ # Playwright end-to-end tests
.github/workflows/ # CI (lint, typecheck)

Lesson Structure

Each lesson lives in content/lessons/<module>/<lesson>/:

content/lessons/01-getting-started/01-hello-opmode/
├── content.mdx # Lesson text (MDX + gray-matter frontmatter)
├── exercise.json # Title, test count, hints
├── Starter.java # Initial code shown in the editor
├── Solution.java # Reference solution (shown on full hint reveal)
└── Test.java # Test suite run in the browser

The student's code must be in a class named StudentCode. Test.java instantiates it alongside mock FTC objects and uses TestBase assertion helpers (assertEqual, assertNear, assertContains, assertTrue) to verify behaviour, then calls TestBase.printResults() to emit JSON results.

In-Browser Java Execution

User code is compiled and run entirely in the browser using CheerpJ, a WebAssembly-based JVM. This means zero server resources are consumed per execution and students can run code unlimited times with no rate limiting.

The execution flow:

  1. User clicks Run → client-side executeInBrowser() is called
  2. StudentCode.java and Test.java are written to CheerpJ's virtual filesystem
  3. javac is invoked in-browser via cheerpjRunMain("com.sun.tools.javac.Main", ...)
  4. If compilation succeeds, Test.main() is executed
  5. Console output is intercepted and parsed as JSON test results
  6. Results are displayed in the output panel

Performance: ~5s cold compile (first run, lazy-loads 18MB tools.jar), ~1.7s warm compile, ~700ms test execution.

Deployment

Production uses a single Docker image pushed to docker.bedson.tech:

bash scripts/build-and-push.sh

Bring up production services with docker-compose.prod.yml (Next.js app + PostgreSQL). An Nginx reverse proxy (config in nginx.conf) sits in front on ports 80/443 and proxies to the Next.js container on port 3310.

CI

GitHub Actions (.github/workflows/test.yml) runs on every push and pull request:

  1. Installs dependencies with Bun
  2. Runs TypeScript type checking
  3. Runs ESLint

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages