Skip to content

Curriculum File Structure

Our core instructional content is located within the conveniently named curriculum directory. This page will break down how these files are organized.

There are a few terms we use when discussing our curriculum content.

  • certification : When referring to a certification in this instance, it is talking about the actual certificate that users claim. Which is separate from the name of the superBlock.
  • superBlock : A superblock is the top level collection of challenges. Each superblock corresponds to a certification in the curriculum (e.g. Responsive Web Design).
  • chapter : A chapter is a grouping of modules within a superblock. Not all superblocks use chapters; legacy superblocks organize blocks in a flat list instead.
  • module : A module is a grouping of blocks within a chapter.
  • block : A block is a section within a superblock. A block corresponds to a group of challenges in a given certification (e.g. Basic HTML and HTML5)
  • challenge : A challenge is a single lesson within the curriculum (e.g. Say Hello to HTML Elements)

Using those terms, here is how the file structure would be defined:

curriculum/
├─ challenges/
│ ├─ english/
│ │ ├─ blocks/
│ │ │ ├─ <block>/
│ │ │ │ ├─ <challenge>.md
│ │ ├─ certifications/
│ │ │ ├─ <certification>.yml
├─ i18n-curriculum/ (git submodule)
│ ├─ curriculum/
│ │ ├─ challenges/
│ │ │ ├─ <language>/
│ │ │ │ ├─ blocks/
│ │ │ │ │ ├─ <block>/
│ │ │ │ │ │ ├─ <challenge>.md
├─ structure/
│ ├─ curriculum.json
│ ├─ superblocks/
│ │ ├─ <superblock>.json
│ ├─ blocks/
│ │ ├─ <block>.json

The structure directory contains JSON files that define the curriculum organization and are used to determine which superBlock a block belongs to, and the order of the challenges within that block.

The main curriculum.json file contains two arrays:

  • superblocks: An ordered list of all superblocks in the curriculum
  • certifications: A list of all available certifications

Each superblock has its own JSON file that defines which blocks belong to it. Simple superblocks only contain a blocks array:

{
"blocks": ["basic-html-and-html5", "basic-css", "applied-visual-design"]
}

More complex superblocks can organize blocks into chapters and modules for better structure:

{
"chapters": [
{
"dashedName": "html",
"modules": [
{
"dashedName": "basic-html",
"blocks": [
"workshop-curriculum-outline",
"lecture-welcome-to-freecodecamp",
"lab-debug-camperbots-profile-page",
"lecture-understanding-html-attributes"
]
},
{
"dashedName": "semantic-html",
"blocks": [
"lecture-importance-of-semantic-html",
"lecture-understanding-nuanced-semantic-elements",
"workshop-blog-page"
]
}
]
},
{
"dashedName": "css",
"modules": [
{
"dashedName": "basic-css",
"blocks": [
"lecture-what-is-css",
"workshop-cafe-menu",
"lab-business-card"
]
}
]
}
]
}

Modules and chapters can have additional properties that affect how they are treated:

  • moduleType: "cert-project": A module containing a single certification project block.
  • moduleType: "review": A module containing a review block.
  • comingSoon: true: Marks a chapter or module as not yet available to campers.
  • chapterType: "exam": Marks a chapter as containing the certification exam.

Each block has its own JSON file that contains metadata and the order of challenges:

{
"dashedName": "workshop-greeting-bot",
"blockLabel": "workshop",
"blockLayout": "challenge-grid",
"helpCategory": "JavaScript",
"isUpcomingChange": false,
"usesMultifileEditor": true,
"hasEditableBoundaries": true,
"challengeOrder": [
{
"id": "66ad8294a0ad902f1b31b612",
"title": "Step 1"
}
]
}

Key fields:

  • dashedName: URL-friendly slug for the block. The display name of the block is defined in intro.json under the block’s title field.
  • blockLabel: The label shown on the block card. Common values are workshop, lab, lecture, review, quiz, exam, warm-up, learn, and practice. Legacy blocks do not have this field.
  • blockLayout: Controls how the block is displayed. Common values include challenge-grid, challenge-list, and legacy-challenge-list.
  • helpCategory: Determines which forum subforum is used when a camper requests help via the help button (e.g. JavaScript, HTML-CSS, Python).
  • isUpcomingChange: When true, hides the block from campers until it is ready.
  • usesMultifileEditor: When true, the challenge editor shows multiple files.
  • hasEditableBoundaries: When true, part of the code is highlighted to indicate where changes should be made.
  • challengeOrder: Ordered list of { id, title } objects defining the sequence of challenges in the block. Challenge files in curriculum/challenges/english/blocks/<block>/ are named after their id (e.g. 66ad8294a0ad902f1b31b612.md).

The challenges/english/certifications/ directory contains YAML files that define the certification requirements and project information for each certification.

Each certification YAML file includes the following key properties:

  • id: Unique identifier for the certification
  • title: Display name of the certification
  • certification: Internal name used to reference the certification
  • tests: Array of required projects with their IDs and titles

The file client/i18n/locales/english/intro.json contains the display titles and introductory text shown to campers for each superblock and block. It is organized by superblock, then by block:

{
"javascript-v9": {
"title": "JavaScript Certification",
"intro": ["..."],
"chapters": {
"javascript": "JavaScript",
"javascript-certification-exam": "JavaScript Certification Exam"
},
"modules": {
"javascript-variables-and-strings": "Variables and Strings"
},
"module-intros": {
"data-structures": {
"note": "Coming Spring 2026",
"intro": ["..."]
}
},
"blocks": {
"workshop-greeting-bot": {
"title": "Build a Greeting Bot",
"intro": ["..."]
}
}
}
}

At the superblock level, title is the display name of the superblock, and intro is the introductory text shown on the superblock page.

chapters and modules are only present in new-style superblocks. module-intros contains introductory text for modules marked as comingSoon in the structure file. Legacy superblocks only have title, intro, and blocks.

The curriculum content is internationalized using a git submodule located at curriculum/i18n-curriculum/. This submodule contains translated versions of curriculum content:

  • English content: Located directly in curriculum/challenges/english/
  • Translated content: Located in the submodule at curriculum/i18n-curriculum/curriculum/challenges/<language>/

The structure within each language directory mirrors the English structure exactly, with the same block folders and challenge files. However, only the Markdown challenge files (.md) are translated and stored in the i18n-curriculum submodule. Configuration files such as YAML certification files and JSON structure files remain in English only.

The i18n-curriculum submodule is updated automatically. Manual changes to translated content should not be made directly in the submodule.

There may be times when you need to rename a certificate, superblock, block, or challenge. This section will outline the steps needed to avoid build errors when doing so.

When renaming curriculum items that change URLs, you must set up redirects to ensure existing links continue to work. This requires updating the file serve.json in the client-config repo.

The file contains a "redirects" array where you need to add redirect objects. The redirect format follows this pattern:

{
"source": "/learn/old-name/:param?",
"destination": "/learn/new-name/:param?"
}

URL Parameters:

  • :superblock? - Captures superblock name (optional)
  • :block? - Captures block name (optional)
  • :challenge? - Captures challenge name (optional)

Examples:

For superblock renaming (e.g., apis-and-microservicesback-end-development-and-apis):

{
"source": "/learn/apis-and-microservices/:block?/:challenge?",
"destination": "/learn/back-end-development-and-apis/:block?/:challenge?"
}

For block renaming within a superblock:

{
"source": "/learn/responsive-web-design/old-block-name/:challenge?",
"destination": "/learn/responsive-web-design/new-block-name/:challenge?"
}

For individual challenge renaming:

{
"source": "/learn/superblock/block/old-challenge-name",
"destination": "/learn/superblock/block/new-challenge-name"
}

The redirect setup must be done in a PR that gets merged AT THE SAME TIME as the PR that actually renames the curriculum items. This ensures the redirects go live simultaneously with the URL changes, preventing any broken links.

When renaming a certification, you will likely want to rename the associated superblock along with it. Do the following to rename only the certificate:

  1. Rename the curriculum/challenges/english/certifications/<certification>.yml file to the new name.
  2. In the YAML file, change the title to the new name.
  3. Update the certifications array in curriculum/structure/curriculum.json to use the new certification name.
  4. Update the relevant Certification enum member and certification arrays in packages/shared/src/config/certification-settings.ts when the certification slug changes.
  5. Update the matching certification entry in client/config/cert-and-project-map.ts, including its title, certSlug, and project certSlug values when applicable.
  6. Update any matching certification names and slugs in client/i18n/locales/<language>/, curriculum/src/build-curriculum.ts, and other references found by searching for the old value.
  7. If you renamed the certification slug, add redirects to the serve.json file to redirect from old certification URLs to new ones:
    {
    "source": "/certification/:username/old-cert-slug",
    "destination": "/certification/:username/new-cert-slug"
    }
  8. Update the main README.md file to the new name.

Also, you will likely want to rename the certificate and the <superBlock>-projects block when you rename a superBlock since they all share a name. To rename only a superBlock you need to:

  1. Rename the superblock file in curriculum/structure/superblocks/ from <old-name>.json to <new-name>.json.
  2. Update the superblocks array in curriculum/structure/curriculum.json to use the new superblock name.
  3. Update the corresponding SuperBlocks enum member in packages/shared/src/config/curriculum.ts and the key in superBlockNames in curriculum/src/build-curriculum.ts.
  4. Update the superblock key in every client/i18n/locales/<language>/intro.json file. In English, update the title when the display name changes.
  5. Update references to the old superblock slug, including certification paths in client/config/cert-and-project-map.ts, by searching the repository for the old value.
  6. Add redirects to the serve.json file to redirect from old superblock URLs to new ones:
    {
    "source": "/learn/old-superblock-name/:block?/:challenge?",
    "destination": "/learn/new-superblock-name/:block?/:challenge?"
    }
  7. Update the main README.md file to the new name.

When renaming a curriculum block, you need to:

  1. Change the name of the block folder in the curriculum/challenges/english/blocks/<block> directory.
  2. Rename the block’s JSON file in curriculum/structure/blocks/ from <old-name>.json to <new-name>.json.
  3. Update the dashedName property in the renamed block JSON file.
  4. Update the superblock’s JSON file in curriculum/structure/superblocks/ to reference the new block name in its blocks array.
  5. Add redirects to the serve.json file to redirect from old block URLs to new ones:
    {
    "source": "/learn/superblock-name/old-block-name/:challenge?",
    "destination": "/learn/superblock-name/new-block-name/:challenge?"
    }
  6. In the client/i18n/locales/<language>/intro.json files, update the block name to the new name for all the languages. In the English intro.json file, update the title as well.
  7. Update the main README.md file to the new name.

When renaming a single challenge file, you need to:

  1. Change the challenge’s title and dashedName in its frontmatter.
  2. Update the challenge title in the relevant block JSON file in curriculum/structure/blocks/<block>.json.
  3. Add redirects to the serve.json file to redirect from old challenge URLs to new ones:
    {
    "source": "/learn/superblock-name/block-name/old-challenge-name",
    "destination": "/learn/superblock-name/block-name/new-challenge-name"
    }
  4. If the challenge is a certificate project, update the YAML file in curriculum/challenges/english/certifications/<certification>.yml to the new name.
  5. If the challenge is a certificate project, update the title and link in client/config/cert-and-project-map.ts
  6. If the challenge is a certificate project, update the main README.md file to the new name.

The dashedName property is used to generate the URL path for a superblock, block, or challenge. It must contain only lowercase letters, numbers, and hyphens. Choose a descriptive, stable slug and update every reference when it changes.