Skip to content

How to work on coding challenges

Our goal is to develop a fun and clear interactive learning experience.

Designing interactive coding challenges is difficult. It would be much easier to write a lengthy explanation or to create a video tutorial. But for our core curriculum, we’re sticking with what works best for most people - a fully interactive, video game-like experience.

We want campers to achieve a flow state. We want them to build momentum and blast through our curriculum with as few snags as possible. We want them to go into the projects with confidence and gain wide exposure to programming concepts.

We are currently in version 9 of the curriculum, which includes theory lessons, workshops, labs, review pages and quizzes.

The content for each challenge is stored in its markdown file. This markdown file is later converted to HTML using our tools to create interactive web pages.

You can find all of freeCodeCamp.org’s curricular content in the /curriculum/challenges directory.

The core curriculum teaches full stack development and is broken down into the following certifications:

  • Responsive Web Design Certification
  • JavaScript Certification
  • Front-End Development Libraries Certification
  • Python Certification
  • Relational Databases Certification
  • Back-End Development and APIs Certification
  • Certified Full-Stack Developer

Version 9 certifications are organized into chapters, modules, blocks and challenges. Chapters contain modules, modules contain blocks, and blocks contain individual challenge files. See the curriculum file structure for details.

Each module contains blocks. A block contains one or more challenge files and is labeled according to its content, such as lecture, workshop, lab, review or quiz.

Theory lessons are short text based lectures with interactive examples that teach the theory behind concepts including common data structures, CSS Grid and SQL.

Workshops are guided, step-based projects that introduce or reinforce concepts.

Labs are campers’ opportunity to test their problem-solving skills and build out projects reviewing the concepts learned in the theory lessons and workshops.

Review pages summarize concepts covered in the module.

Quizzes test campers’ knowledge of the module material.

Each core curriculum component has its own tooling and style guide. Refer to the guide for the content you are working on:

Language curricula are separate from the core curriculum and have their own content structure and challenge formats. Refer to How to Work on Language Curricula for specific guidance.

Before you work on the curriculum, you would need to set up some tooling to help you test your changes. You can use any option from the below:

  • You can set up freeCodeCamp locally. This is highly recommended for regular/repeat contributions. This setup allows you to work and test your changes.

  • Use GitHub Codespaces, a free online dev environment. Clicking the button below will start a ready-to-code dev environment for freeCodeCamp in your browser. It only takes a few minutes.

    Open in GitHub Codespaces

Sentences should be clear and concise with minimal jargon. If used, jargon should be immediately defined in plain English.

Keep paragraphs short (around 1-4 sentences). People are more likely to read several short paragraphs than a wall of text.

Use American English, e.g., use labeled instead of labelled.

Challenge text should use the second person (“you”) to help to give it a conversational tone. This way the text and instructions seem to speak directly to the camper working through the challenge. Try to avoid using the first person (“I”, “we”, “let’s”, and “us”).

Don’t use outbound links in challenge instructions. Include the information campers need in the challenge text or teach it in a preceding lesson.

You can add diagrams if necessary.

Don’t use emojis or emoticons in challenges. freeCodeCamp has a global community, and the cultural meaning of an emoji or emoticon may be different around the world. Also, emojis can render differently on different systems.

Proper nouns should use correct capitalization when possible. Below is a list of words as they should appear in the challenges.

  • JavaScript (capital letters in “J” and “S” and no abbreviations)
  • Node.js
  • When referring to front-end, back-end, or full-stack, use the hyphenated form.

Each workshop step or other short coding exercise should be solvable within 120 seconds by a native English speaker who has completed the preceding challenges. This includes the time needed to read the instructions, understand the seed code, write the solution and pass the tests. This rule does not apply to an entire lab or certification project.

If it takes longer than two minutes to complete the challenge, you have two options:

  • Simplify the challenge, or
  • Split the challenge into two challenges.

The 2-minute rule keeps instructions concise, seed code clear and tests straightforward.

We track how long it takes for campers to solve short challenges and use this information to identify challenges that need to be simplified or split.

Each short instructional challenge or workshop step should teach one concept. For challenges with descriptive titles, the concept should be apparent from the title.

We can reinforce previously covered concepts through repetition and variations, for example, introducing <h1> elements in one challenge, then <h3> elements a few challenges later.

Short challenges can flow together and reinforce previously covered concepts.

In addition to the rules contained in the Writing Style Guide, here are specific formatting guidelines for challenge text and examples:

  • Language keywords go in ``` backticks. For example, HTML tag names or CSS property names.
  • References to code parts (i.e. function, method, or variable names) should be wrapped in ``` backticks. See example below:
Use `parseInt` to convert the variable `realNumber` into an integer.
  • References to file names and path directories (e.g. package.json, src/components) should be wrapped in ``` backticks.
  • Multi-line code blocks must be preceded by an empty line. The next line must start with three backticks followed immediately by one of the supported languages. To complete the code block, you must start a new line that only has three backticks and another empty line. See example below:
  • Whitespace matters in Markdown, so we recommend that you make it visible in your editor.

The following is an example of code:

```{language}
[YOUR CODE HERE]
```
  • Additional information in the form of a note should be surrounded by blank lines, and formatted: **Note:** Rest of note text...
  • If multiple notes are needed, then list all of the notes in separate sentences using the format: **Notes:** First note text. Second note text.
  • Use Markdown instead of HTML tags when Markdown provides equivalent formatting.

Tests should cover the stated requirements without enforcing unrelated implementation details. Use the minimum number needed to verify those requirements.

Challenge tests can use the Node.js assert API and the Chai assert API. If needed, user-generated code can be accessed through the code variable. The __helpers object also exposes functions for inspecting code. These functions are defined in the curriculum-helpers repository.

If a method exists in Chai.js that expresses what is being tested for, its use is preferred.

Example one

assert(Array.isArray([]), 'empty arrays are arrays');

Example two

assert.isArray([]);

In the first example, what the test means isn’t immediately clear. The main thing that explains the test is the assertion message.

Meanwhile in example two, the test spells out its purpose; to determine if something is an array.

Prefer the specific assertion method.

Here are specific formatting guidelines for the challenge seed code:

  • Use two spaces to indent for HTML, CSS, and JavaScript
  • Use four spaces to indent for Python
  • JavaScript statements end with a semicolon
  • Use double quotes where applicable for HTML, CSS, and JavaScript
  • Use single quotes where applicable for Python

The curriculum has two English dictionaries for seed-code comments. The comments.json file contains comments that are translated for localized curricula. The comments-to-not-translate.json file is used for seed-code comments that must remain unchanged in every language.

Every comment in curriculum seed code must match an entry in one of these files, including its case and spacing. Do not add entries without prior discussion with the development team.

Comments should have a space between the comment marker and the comment text. In general, comments should be used sparingly. Always consider rewriting a challenge’s description or instructions if it could avoid using a seed code comment.

Workshop steps use --fcc-editable-region-- markers to show campers where to change code. Do not use seed comments as a substitute for those markers.

Example of a valid single-line JavaScript comment:

// Only change code below this line

Example of a valid CSS comment:

/* Only change code above this line */

A dictionary comment can also be part of the seed code that a camper needs to change:

// TODO: use a different type of loop
for (let i = 1; i <= count; i++) {
rows.push(padRow(i, count));
}

There are separate translated comment dictionaries for each language. The English comments.json file is their source. The translated dictionaries are located in the i18n-curriculum submodule at curriculum/dictionaries/{language}/comments.json (for example, curriculum/dictionaries/chinese/comments.json). Each dictionary is a JSON object whose keys are comment IDs and whose values are the comment text.

Some comments may contain a word/phrase that should not be translated. For example, variable names or proper library names like “React” should not be translated. See the comment below as an example. The word myGlobal should not be translated.

Declare the myGlobal variable below this line

The i18n-curriculum submodule is synchronized through the translation workflow. Do not edit its files directly.

Before you create a pull request for your changes, you need to validate that the changes you have made do not inadvertently cause problems with the challenge.

Run the following commands from the root of the freeCodeCamp repository.

  1. Install the browser that the tests drive. Do this once:

    Terminal window
    pnpm -F=@freecodecamp/curriculum install-puppeteer
  2. To test a single challenge, use its challenge id:

    Terminal window
    FCC_CHALLENGE_ID=6823ac607bfdbc46331b2559 pnpm run test-curriculum-content
  3. You can also test a block or a superblock of challenges with these commands:

    Terminal window
    FCC_BLOCK='workshop-curriculum-outline' pnpm run test-curriculum-content

    Use the block’s dashedName (the folder’s name) for the FCC_BLOCK value.

    Terminal window
    FCC_SUPERBLOCK='responsive-web-design-v9' pnpm run test-curriculum-content

After you’ve committed your changes, check here for how to open a Pull Request.

To create a new lecture block, workshop, lab, review page or quiz, you can run pnpm run create-new-project in the root directory. This opens up a command line UI that guides you through the process.

The script creates the block directory and its initial challenge file. For example, a block named test-project in the Responsive Web Design certification would be created at curriculum/challenges/english/blocks/test-project.

There are a few other helper scripts that can be used to manage the challenges in a block. Note that these commands should all be run in the block directory. For example:

Terminal window
cd curriculum/challenges/english/blocks/lecture-understanding-html-attributes

To add a new challenge at the end of a block, call the script:

Terminal window
pnpm run create-next-challenge

This will prompt you for the challenge information and create the challenge file, updating the block’s JSON structure file with the new challenge information.

To delete a challenge, call the script:

Terminal window
pnpm run delete-challenge

This will prompt you to select which challenge should be deleted, then delete the file and update the block’s JSON structure file to remove the challenge from the order.

To insert a challenge before an existing challenge, call the script:

Terminal window
pnpm run insert-challenge

This will prompt you for the challenge information, then for the challenge to insert before. For example, if your choices are:

Terminal window
a
b
c

If you choose b, your new order will be:

Terminal window
a
new challenge
b
c

If you need to manually re-order the challenges, call the script:

Terminal window
pnpm run update-challenge-order

This will take you through an interactive process to select the order of the challenges.

If you see the following error in the console while previewing a challenge:

Potential infinite loop detected on line <number>...

This means that the loop-protect plugin has found a long-running loop or recursive function. If your challenge needs to do that (e.g. it contains an event loop that is supposed to run indefinitely), then you can prevent the plugin from being used in the preview. To do so, add disableLoopProtectPreview: true to the block’s JSON structure file in curriculum/structure/blocks/.

If your tests are computationally intensive, then you may see this error when they run. If this happens then you can add disableLoopProtectTests: true to the block’s JSON structure file.

It’s not typically necessary to have both set to true, so only set them as needed.