Claude
Skills
Sign in
Back

freecodecamp-curriculum

Included with Lifetime
$97 forever

Comprehensive guide for contributing to and working with freeCodeCamp's open-source codebase and curriculum platform

General

What this skill does


# freeCodeCamp Curriculum & Platform Development

> Skill by [ara.so](https://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 tests
```

---

## Local Development Setup

### Prerequisites

- Node.js 20+ (use `nvm` or `fnm`)
- pnpm 9+
- MongoDB (local or Atlas)
- A GitHub account (for OAuth)

### 1. Fork & Clone

```bash
git clone https://github.com/<YOUR_USERNAME>/freeCodeCamp.git
cd freeCodeCamp
```

### 2. Install Dependencies

```bash
pnpm install
```

### 3. Configure Environment

```bash
cp sample.env .env
```

Key `.env` variables to set:

```bash
# 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_KEY
```

### 4. Seed the Database

```bash
pnpm run seed
```

### 5. Start Development Servers

```bash
# Start everything (API + Client)
pnpm run develop

# Or start individually:
pnpm run develop:api      # Fastify API on :3000
pnpm run develop:client   # Gatsby on :8000
```

---

## Curriculum Challenge Structure

Challenges are stored as YAML/Markdown files under `curriculum/challenges/`.

### Challenge File Format

```yaml
# 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.

```js
// This is an in-line comment.
/* This is a multi-line comment */
```

# --instructions--

Try creating one of each type of comment.

# --hints--

hint 1

```js
assert(code.match(/(\/\/)/).length > 0);
```

hint 2

```js
assert(code.match(/(\/\*[\s\S]+?\*\/)/).length > 0);
```

# --seed--

## --seed-contents--

```js
// Your starting code here
```

# --solutions--

```js
// 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

```bash
# 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-flexbox
```

### Manual Creation

1. Find the correct directory under `curriculum/challenges/english/`
2. Create a new `.md` file with a unique ID

```bash
# Generate a unique challenge ID
node -e "const {ObjectID} = require('mongodb'); console.log(new ObjectID().toString())"
```

3. Follow the challenge file format above

### Validate Your Challenge

```bash
# 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-javascript
```

---

## Writing Challenge Tests

Tests use a custom assertion library. Inside `# --hints--` blocks:

### JavaScript Challenges

```markdown
# --hints--

`myVariable` should be declared with `let`.

```js
assert.match(code, /let\s+myVariable/);
```

The function should return `true` when passed `42`.

```js
assert.strictEqual(myFunction(42), true);
```

The DOM should contain an element with id `main`.

```js
const el = document.getElementById('main');
assert.exists(el);
```
```

### Available Test Utilities

```js
// 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

```typescript
// 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

```typescript
// api/src/app.ts - register the plugin
import { exampleRoutes } from './routes/example';

await fastify.register(exampleRoutes, { prefix: '/api' });
```

### Database Access (Mongoose)

```typescript
// 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

```tsx
// 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

```tsx
// 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 ?? []
);
```

```tsx
// 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

```tsx
// Add

Related in General