Freecodecamp Curriculum
Comprehensive guide for contributing to and working with freeCodeCamp's open-source codebase and curriculum platform
- Skill ID
- reason-machines/trending-skills/freecodecamp-curriculum
- Publisher
- reason-machines
- Repository
- trending-skills
- Installs
- 0
- Files
- 1
- Synced
- Sep 23, 2026
Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.
reason-machines/trending-skills/freecodecamp-curriculumInstalls these files- SKILL.md
What this skill tells the agent
freeCodeCamp Curriculum & Platform Development
Skill by ara.so — Daily 2026 Skills collection.
freeCodeCamp.org is a free, open-source learning platform with thousands of interactive coding challenges, certifications, and a full-stack curriculum. The codebase includes a React/TypeScript frontend, Node.js/Fastify backend, and a YAML/Markdown-based curriculum system.
Architecture Overview
freeCodeCamp/
├── api/ # Fastify API server (TypeScript)
├── client/ # Gatsby/React frontend (TypeScript)
├── curriculum/ # All challenges and certifications (YAML/Markdown)
│ └── challenges/
│ ├── english/
│ │ ├── responsive-web-design/
│ │ ├── javascript-algorithms-and-data-structures/
│ │ └── ...
│ └── ...
├── tools/
│ ├── challenge-helper-scripts/ # CLI tools for curriculum authoring
│ └── ui-components/ # Shared React components
├── config/ # Shared configuration
└── e2e/ # Playwright end-to-end testsLocal Development Setup
Prerequisites
- Node.js 20+ (use
nvmorfnm) - pnpm 9+
- MongoDB (local or Atlas)
- A GitHub account (for OAuth)
1. Fork & Clone
git clone https://github.com/<YOUR_USERNAME>/freeCodeCamp.git
cd freeCodeCamp2. Install Dependencies
pnpm install3. Configure Environment
cp sample.env .envKey .env variables to set:
# MongoDB
MONGOHQ_URL=mongodb://127.0.0.1:27017/freecodecamp
# GitHub OAuth (create at github.com/settings/developers)
GITHUB_ID=$GITHUB_OAUTH_CLIENT_ID
GITHUB_SECRET=$GITHUB_OAUTH_CLIENT_SECRET
# Auth
JWT_SECRET=$YOUR_JWT_SECRET
SESSION_SECRET=$YOUR_SESSION_SECRET
# Email (optional for local dev)
SENDGRID_API_KEY=$SENDGRID_API_KEY4. Seed the Database
pnpm run seed5. Start Development Servers
# Start everything (API + Client)
pnpm run develop
# Or start individually:
pnpm run develop:api # Fastify API on :3000
pnpm run develop:client # Gatsby on :8000Curriculum Challenge Structure
Challenges are stored as YAML/Markdown files under curriculum/challenges/.
Challenge File Format
# curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/comment-your-javascript-code.md
---
id: bd7123c8c441eddfaeb5bdef # unique MongoDB ObjectId-style string
title: Comment Your JavaScript Code
challengeType: 1 # 1=JS, 0=HTML, 2=JSX, 3=Vanilla JS, 5=Project, 7=Video
forumTopicId: 16783
dashedName: comment-your-javascript-code
---
# --description--
Comments are lines of code that JavaScript will intentionally ignore.
// This is an in-line comment. / This is a multi-line comment /
# --instructions--
Try creating one of each type of comment.
# --hints--
hint 1
assert(code.match(/(\/\/)/).length > 0);
hint 2
assert(code.match(/(\/\[\s\S]+?\\/)/).length > 0);
# --seed--
## --seed-contents--
// Your starting code here
# --solutions--
// inline comment / multi-line comment /
Challenge Types
| Type | Value | Description |
|---|---|---|
| HTML | 0 | HTML/CSS challenges |
| JavaScript | 1 | JS algorithm challenges |
| JSX | 2 | React component challenges |
| Vanilla JS | 3 | DOM manipulation |
| Python | 7 | Python challenges |
| Project | 5 | Certification projects |
| Video | 11 | Video-based lessons |
Creating a New Challenge
Using the Helper Script
# Create a new challenge interactively
pnpm run create-challenge
# Or use the helper directly
cd tools/challenge-helper-scripts
pnpm run create-challenge --superblock responsive-web-design --block css-flexboxManual Creation
- Find the correct directory under
curriculum/challenges/english/ - Create a new
.mdfile with a unique ID
# Generate a unique challenge ID
node -e "const {ObjectID} = require('mongodb'); console.log(new ObjectID().toString())"- Follow the challenge file format above
Validate Your Challenge
# Lint and validate all curriculum files
pnpm run test:curriculum
# Test a specific challenge
pnpm run test:curriculum -- --challenge <challenge-id>
# Test a specific block
pnpm run test:curriculum -- --block basic-javascriptWriting Challenge Tests
Tests use a custom assertion library. Inside # --hints-- blocks:
JavaScript Challenges
# --hints--
`myVariable` should be declared with `let`.
assert.match(code, /let\s+myVariable/);
The function should return `true` when passed `42`.
assert.strictEqual(myFunction(42), true);
The DOM should contain an element with id `main`.
const el = document.getElementById('main'); assert.exists(el);
Available Test Utilities
// DOM access (for HTML challenges)
document.querySelector('#my-id')
document.getElementById('test')
// Code inspection
assert.match(code, /regex/); // raw source code string
assert.include(code, 'someString');
// Value assertions (Chai-style)
assert.strictEqual(actual, expected);
assert.isTrue(value);
assert.exists(value);
assert.approximately(actual, expected, delta);
// For async challenges
// Use __helpers object
const result = await fetch('/api/test');
assert.strictEqual(result.status, 200);API Development (Fastify)
Route Structure
// api/src/routes/example.ts
import { type FastifyPluginCallbackTypebox } from '../helpers/plugin-callback-typebox';
import { Type } from '@fastify/type-provider-typebox';
export const exampleRoutes: FastifyPluginCallbackTypebox = (
fastify,
_options,
done
) => {
fastify.get(
'/example/:id',
{
schema: {
params: Type.Object({
id: Type.String()
}),
response: {
200: Type.Object({
data: Type.String()
})
}
}
},
async (req, reply) => {
const { id } = req.params;
return reply.send({ data: `Result for ${id}` });
}
);
done();
};Adding a New API Route
// api/src/app.ts - register the plugin
import { exampleRoutes } from './routes/example';
await fastify.register(exampleRoutes, { prefix: '/api' });Database Access (Mongoose)
// api/src/schemas/user.ts
import mongoose from 'mongoose';
const userSchema = new mongoose.Schema({
email: { type: String, required: true, unique: true },
completedChallenges: [
{
id: String,
completedDate: Number,
solution: String
}
]
});
export const User = mongoose.model('User', userSchema);Client (Gatsby/React) Development
Adding a New Page
// client/src/pages/my-new-page.tsx
import React from 'react';
import { Helmet } from 'react-helmet';
import { useTranslation } from 'react-i18next';
const MyNewPage = (): JSX.Element => {
const { t } = useTranslation();
return (
<>
<Helmet>
<title>{t('page-title.my-new-page')} | freeCodeCamp.org</title>
</Helmet>
<main>
<h1>{t('headings.my-new-page')}</h1>
</main>
</>
);
};
export default MyNewPage;Using the Redux Store
// client/src/redux/selectors.ts pattern
import { createSelector } from 'reselect';
import { RootState } from './types';
export const userSelector = (state: RootState) => state.app.user;
export const completedChallengesSelector = createSelector(
userSelector,
user => user?.completedChallenges ?? []
);// In a component
import { useAppSelector } from '../redux/hooks';
import { completedChallengesSelector } from '../redux/selectors';
const MyComponent = () => {
const completedChallenges = useAppSelector(completedChallengesSelector);
return <div>{completedChallenges.length} challenges completed</div>;
};i18n Translations
More from reason-machines
Use this skill in a project
Open any RiverX project, search the Skills panel for reason-machines/trending-skills/freecodecamp-curriculum, and install it in one click.
