
Trailing.io
Coding course platform that grades HTML/CSS by comparing screenshots
- Role
- Developer in a team of 5
- When
- Sep 2023 – Jan 2024
- Status
- Generated real revenue
- Highlight
- ~26K lines of code I wrote
Overview
What it is
Trailing.io teaches web development and Python through short exercises solved in the browser. A team of five built it during the Minor Entrepreneurship, from September 2023 to January 2024: five months of full-time development. It generated revenue from paying users and placed 2nd out of 23 teams. Learners follow courses laid out as stages of exercises, get AI hints, and earn bytes, a virtual currency they spend in a shop.
I wrote about 26K lines of its code. My focus was the core: the screenshot-diff grader for HTML/CSS exercises, and a full course-building admin panel. My teammates used that panel to create three complete courses: HTML & CSS, Python and JavaScript.
The grader needs no hand-written tests. An exercise author supplies a target page and a required similarity, and the server renders both pages in headless Chrome and compares the images.
Why it’s interesting
- Both pages are rendered in headless Chrome with the viewport sized to the body, so the screenshot covers the whole page, not just the first screen.
- If the two screenshots differ in size, the grader returns a fail without comparing pixels. Otherwise pixelmatch scores them at threshold 0.1.
- Every img tag is swapped for one fixed placeholder before rendering, so remote images cannot make two identical pages differ.
- A required-words pre-check counts each word against the starter code, so a page that only looks right by accident is rejected before rendering.
- A Judge0 container runs Python, JavaScript and C submissions in a sandbox, next to the visual grader for HTML/CSS.
- Revenue
- from real paying users
- 5 months
- of full-time development
- Placed 2nd
- out of 23 teams
- ~26K
- lines of code I wrote
git blame
Architecture
How it fits together
Try it
Get graded by the pixel-diff grader
A browser re-creation of the grader's rules: change the student's CSS and a pixelmatch-style colour comparison (threshold 0.1) scores it against the target. As in the real grader, a page of a different size fails without any pixel comparison.
Screens
A closer look
Course catalogue. Course cards with a progress bar on the one in progress, free and paid courses together.
1 / 9Tap a screenshot to enlarge it.
Features
Everything it does
Learning
- Courses and roadmaps — Courses are stages of levels; a level is a code exercise or a multiple-choice question.
- Browser editor — Monaco with HTML, CSS and JS tabs, live preview, a Correct output toggle and optional Vim mode.
- Four languages — Web development graded visually, plus Python, JavaScript and C run in a sandbox.
- Practice topics — Mini exercises by topic, graded by the same screenshot comparison.
- Help along the way — Solution after two failed attempts, cheat sheets, in-app tutorial and lesson feedback.
Visual grader
- Screenshot comparison — Student and target pages rendered in headless Chrome and scored with pixelmatch.
- Required similarity — Each exercise sets its own percentage; the demo exercises use 98 or 99.
- Required words — A pre-check rejects submissions that skip the HTML or CSS the exercise asks for.
- Image placeholder — Every img source is replaced by one fixed placeholder before rendering.
- Rate limit — Submissions are rate-limited with express-rate-limit.
AI
- Get a hint — GPT-3.5 streams a hint over Socket.io; the prompt forbids giving the solution.
- Code Assistant — A chat helper on each exercise, using the same streaming path.
- Problem generator — Admins can draft exercises with an OpenAI-assisted generator.
Gamification
- Bytes — A virtual currency awarded for first-time solves, the daily reward and the daily challenge.
- Shop — Avatars bought with bytes; byte packs bought with Stripe.
- Streaks and leaderboards — Leaderboards by total bytes earned or current streak.
- Profile — Progress rings per course, an activity chart, followers and referrals.
- Certificates — A PDF is drawn onto a template with pdf-lib when a course is finished.
Accounts and admin
- Sign-in — Email and password, Google and GitHub OAuth, email verification and password reset.
- Paid courses — Stripe checkout and a webhook, with a payment history page.
- Admin CMS — Exercises, courses, blog, categories, users, bug reports and multiple-choice questions.
- Blog — Public blog with an index and detail pages.
Tech stack
What it's built with, and why
Frontend
- React 18 + TypeScript + Vite
- Single-page app with 52 page components.
- Redux Toolkit
- Holds user, roadmap and level state, the shop and the selected language.
- Monaco
- In-browser editor for exercises, with an optional Vim mode.
- Tailwind CSS
- Styling, with Headless UI, framer-motion and ApexCharts for the activity chart.
Backend
- Express + TypeScript
- REST API with JWT in an httpOnly cookie, refresh tokens and rate limiting.
- Socket.io
- Streams AI hints and like counts to the browser.
- Puppeteer + pixelmatch + cheerio
- Render both pages, rewrite img tags, and score the screenshots.
- pdf-lib + node-cron
- Course certificates and the daily reward and challenge job.
Data
- PostgreSQL + Prisma
- 29 models and 78 migrations: courses, levels, submissions, rewards, payments.
AI
- OpenAI (GPT-3.5-turbo)
- Streamed hints, the chat assistant and the admin problem generator.
Integrations
- Stripe
- Checkout for paid courses and byte packs, with a webhook.
- Mailjet
- Verification and password reset emails.
- Google and GitHub OAuth
- Alternative sign-in.
- Judge0
- Sandboxed execution of Python, JavaScript and C.
Infra and tooling
- Docker Compose
- Local Postgres, and a separate Judge0 stack.
- GitHub Actions
- Backend and frontend checks on pull requests.
- ESLint + Prettier
- Shared code style across the team of five.
