---
id: daily-freecodecamp-curriculum
name: "freecodecamp-curriculum"
url: https://skills.yangsir.net/skill/daily-freecodecamp-curriculum
author: aradotso
domain: education
tags: ["education", "curriculum", "interactive-learning", "coding-challenges", "react"]
install_count: 1300
rating: 4.30 (27 reviews)
github: https://github.com/aradotso/trending-skills
---

# freecodecamp-curriculum

> freeCodeCamp 平台开发，包含数千个交互式编程挑战、认证和全栈课程

**Stats**: 1,300 installs · 4.3/5 (27 reviews)

## Before / After 对比

### 学习平台开发

**Before**:

从零搭建学习平台，手动设计课程结构和交互挑战，开发周期长且维护困难

**After**:

基于成熟平台扩展课程，直接使用交互式挑战框架，专注于内容创作而非平台开发

| Metric | Before | After | Change |
|---|---|---|---|
| 课程开发速度 | 30days/module | 5days/module | -83% |
| 学生参与度 | 50% | 85% | +70% |

## Readme

# freecodecamp-curriculum

# 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

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

```

### 2. Install Dependencies

```
pnpm install

```

### 3. Configure Environment

```
cp sample.env .env

```

Key `.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_KEY

```

### 4. Seed the Database

```
pnpm run seed

```

### 5. 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 :8000

```

## Curriculum 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.

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

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

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

- Find the correct directory under `curriculum/challenges/english/`

- Create a new `.md` file 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-javascript

```

## Writing Challenge Tests

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

### JavaScript Challenges

```
# --hints--

`myVariable` should be declared with `let`.

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

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

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

```
// Add keys to client/i18n/locales/english/translations.json
{
  "my-component": {
    "title": "My Title",
    "description": "My description with {{variable}}"
  }
}

// Use in component
const { t } = useTranslation();
t('my-component.title');
t('my-component.description', { variable: 'value' });

```

## Testing

### Unit Tests (Jest)

```
# Run all unit tests
pnpm test

# Run tests for a specific package
pnpm --filter api test
pnpm --filter client test

# Watch mode
pnpm --filter client test -- --watch

```

### Curriculum Tests

```
# Validate all challenges
pnpm run test:curriculum

# Validate specific superblock
pnpm run test:curriculum -- --superblock javascript-algorithms-and-data-structures

# Lint challenge markdown
pnpm run lint:curriculum

```

### E2E Tests (Playwright)

```
# Run all e2e tests
pnpm run test:e2e

# Run specific test file
pnpm run test:e2e -- e2e/learn.spec.ts

# Run with UI
pnpm run test:e2e -- --ui

```

### Writing E2E Tests

```
// e2e/my-feature.spec.ts
import { test, expect } from '@playwright/test';

test('user can complete a challenge', async ({ page }) => {
  await page.goto('/learn/javascript-algorithms-and-data-structures/basic-javascript/comment-your-javascript-code');

  // Fill in the code editor
  await page.locator('.monaco-editor').click();
  await page.keyboard.type('// inline comment\n/* block comment */');

  // Run tests
  await page.getByRole('button', { name: /run the tests/i }).click();

  // Check results
  await expect(page.getByText('Tests Passed')).toBeVisible();
});

```

## Key pnpm Scripts Reference

```
# Development
pnpm run develop              # Start all services
pnpm run develop:api          # API only
pnpm run develop:client       # Client only

# Building
pnpm run build                # Build everything
pnpm run build:api            # Build API
pnpm run build:client         # Build client (Gatsby)

# Testing
pnpm test                     # Unit tests
pnpm run test:curriculum      # Validate curriculum
pnpm run test:e2e             # Playwright e2e

# Linting
pnpm run lint                 # ESLint all packages
pnpm run lint:curriculum      # Curriculum markdown lint

# Database
pnpm run seed                 # Seed DB with curriculum data
pnpm run seed:certified-user  # Seed a test certified user

# Utilities
pnpm run create-challenge     # Interactive challenge creator
pnpm run clean                # Clean build artifacts

```

## Superblock & Block Naming Conventions

Superblocks map to certifications. Directory names use kebab-case:

```
responsive-web-design/
javascript-algorithms-and-data-structures/
front-end-development-libraries/
data-visualization/
relational-database/
back-end-development-and-apis/
quality-assurance/
scientific-computing-with-python/
data-analysis-with-python/
machine-learning-with-python/
coding-interview-prep/
the-odin-project/
project-euler/

```

Block directories within a superblock:

```
responsive-web-design/
├── basic-html-and-html5/
├── basic-css/
├── applied-visual-design/
├── css-flexbox/
└── css-grid/

```

## Common Patterns & Gotchas

### Challenge ID Generation

Every challenge needs a unique 24-character hex ID:

```
// tools/challenge-helper-scripts/helpers/id-gen.ts
import { ObjectId } from 'bson';
export const generateId = (): string => new ObjectId().toHexString();

```

### Adding Forum Links

Every challenge needs a `forumTopicId` linking to forum.freecodecamp.org:

```
forumTopicId: 301090  # Must be a real forum post ID

```

### Curriculum Meta Files

Each block needs a `_meta.json`:

```
{
  "name": "Basic JavaScript",
  "dashedName": "basic-javascript",
  "order": 0,
  "time": "5 hours",
  "template": "",
  "required": [],
  "isUpcomingChange": false,
  "isBeta": false,
  "isLocked": false,
  "isPrivate": false
}

```

### Testing with Authentication

```
// In e2e tests, use the test user fixture
import { authedUser } from './fixtures/authed-user';

test.use({ storageState: 'playwright/.auth/user.json' });

test('authenticated action', async ({ page }) => {
  // page is already logged in
  await page.goto('/settings');
  await expect(page.getByText('Account Settings')).toBeVisible();
});

```

## Troubleshooting

### MongoDB Connection Issues

```
# Check if MongoDB is running
mongosh --eval "db.adminCommand('ping')"

# Start MongoDB (macOS with Homebrew)
brew services start mongodb-community

# Use in-memory MongoDB for tests
MONGOHQ_URL=mongodb://127.0.0.1:27017/freecodecamp-test pnpm test

```

### Port Conflicts

```
# API runs on 3000, Client on 8000
lsof -i :3000
kill -9 <PID>

```

### Curriculum Validation Failures

```
# See detailed error output
pnpm run test:curriculum -- --verbose

# Common issues:
# - Missing forumTopicId
# - Duplicate challenge IDs
# - Invalid challengeType
# - Malformed YAML frontmatter

```

### Node/pnpm Version Mismatch

```
# Use the project's required versions
node --version   # Should match .nvmrc
pnpm --version   # Should match packageManager in package.json

nvm use          # Switches to correct Node version

```

### Client Build Errors

```
# Clear Gatsby cache
pnpm --filter client run clean
pnpm run develop:client

```

## Contributing Workflow

```
# 1. Create a feature branch
git checkout -b fix/challenge-typo-in-basic-js

# 2. Make changes and test
pnpm run test:curriculum
pnpm test

# 3. Lint
pnpm run lint

# 4. Commit using conventional commits
git commit -m "fix(curriculum): correct typo in basic-javascript challenge"

# 5. Push and open PR against main
git push origin fix/challenge-typo-in-basic-js

```

Commit message prefixes: `fix:`, `feat:`, `chore:`, `docs:`, `refactor:`, `test:`

## Resources

- Contribution guide: [https://contribute.freecodecamp.org](https://contribute.freecodecamp.org)

- Forum: [https://forum.freecodecamp.org](https://forum.freecodecamp.org)

- Discord: [https://discord.gg/PRyKn3Vbay](https://discord.gg/PRyKn3Vbay)

- How to report bugs: [https://forum.freecodecamp.org/t/how-to-report-a-bug/19543](https://forum.freecodecamp.org/t/how-to-report-a-bug/19543)

Weekly Installs252Repository[aradotso/trending-skills](https://github.com/aradotso/trending-skills)GitHub Stars3First Seen5 days agoInstalled ongemini-cli248github-copilot248codex248amp248cline248kimi-cli248

---
*Source: https://skills.yangsir.net/skill/daily-freecodecamp-curriculum*
*Markdown mirror: https://skills.yangsir.net/api/skill/daily-freecodecamp-curriculum/markdown*