Table of Contents
- Contribution Guidelines
- Contributing Code
- Running the Application
- Frequently Asked Questions
- Server-side Technical Documentation
- Troubleshooting
Hello 👋 and welcome to Chapter, a project of freeCodeCamp.
We strictly enforce our "Code of Conduct", so please take a moment to read the 196 word policy.
Join our chat to get connected with the project's development team.
Consider the following options when you are ready to contribute code.
- GitPod.io - a ready-to-code development environment that launches in the cloud.
- Traditional Dev Environment - the common method of developing on a computer you control.
All pull requests will have a GitPod link to allow for quickly opening an "ready-to-code" development environment for that specific issue / task. Follow the GitPod documentation to configure your account and "ephemeral" workspace.
This approach is more common and involves the step below to setup and configuring a development environment within a local, virtual, or remote operating system that you own or control.
Step 1 - Fork the Repository on GitHub
'Forking' is a step where you get your own copy of Chapter's repository (a.k.a repo) on GitHub.
This is essential as it allows you to work on your own copy of Chapter. It allows you to request changes to be pulled into the Chapter's repository from your fork via a pull request.
Follow these steps to fork the repository:
- Go to the Chapter repository on GitHub.
- Click the "Fork" Button in the upper right-hand corner of the interface Need help?.
- After the repository has been forked, you will be taken to your copy of the Chapter repository at
https://github.com/YOUR_USER_NAME/chapter
.
Step 2 - Prepare the Development Environment
Prerequisite: All commands
will be run within a terminal's command line / shell on your development device. Options vary by operating system.
- Linux - the pre-installed terminal, usually running a bash or sh shell, should work in its default "out of the box" configuration.
- Mac - the pre-installed Terminal in MacOS, usually running a zsh shell, should work in its default "out of the box" configuration.
- Windows - options for running a Linux terminal and shell within Windows include:
- Windows Subsystem Linux with Linux (WSL) with a Linux distribution, such as Ubuntu 20.04 for Windows or other supported Linux distributions.
Note: Windows Terminal is an optional terminal interface tool. It can only open a Linux shell if WSL and a Linux distro already exist.
- Git Bash - this terminal shell emulates Linux and is included in Git for Windows. It works, but is more likely to have permission errors or minor inconsistencies.
- PowerShell and cmd may run the Chapter app in Docker Mode, but these Windows native shells are not supported for this project.
- Windows Subsystem Linux with Linux (WSL) with a Linux distribution, such as Ubuntu 20.04 for Windows or other supported Linux distributions.
Prerequisite: Git must exist (run git --version
to check) within your development terminal / shell.
-
Decide if you will authenticate to GitHub using SSH or HTTPS.
- SSH - uses SSH key authentication instead of a username and password.
- HTTPS - uses a GitHub username and personal access token (PAT). For security, use a PAT instead of a GitHub password.
-
Change directories (
cd
) to wherever you want the Chapter project to be downloaded by Git.Note: Windows using WSL + a Linux distro maintains its own file system. Use a sub-directory within the Linux /home/username/ filesystem path. The alternative, using a directory within _C:_ or /mnt/c, will cause everything to run very slowly.
-
Clone your GitHub fork of Chapter using the SSH or HTTP method you selected above. Replace YOUR_USER_NAME with your GitHub username.
- SSH method -
git clone [email protected]:YOUR_USER_NAME/Chapter.git
- HTTPS method -
git clone https://github.com/YOUR_USER_NAME/chapter.git
This command will download the entire Git repository fork into a sub-directory named chapter inside of the current directory. Your forked repository of code will be referred to as the origin .
- SSH method -
-
Configure the Chapter repository as the upstream. Doing this allows you to regularly synchronize code changes from the upstream to your origin fork.
cd chapter git remote add upstream https://github.com/freeCodeCamp/chapter.git
-
Ensure the origin and upstream configuration is correct:
git remote -v
The output should look something like below:
origin https://github.com/YOUR_USER_NAME/chapter.git (fetch) origin https://github.com/YOUR_USER_NAME/chapter.git (push) upstream https://github.com/freeCodeCamp/chapter.git (fetch) upstream https://github.com/freeCodeCamp/chapter.git (push)
Step 3 - Decide Whether to Run the Application Now, or Later
It's possible to contribute simple changes, like to README.md, without running the application. However, for many situations you will need to get the application running to view pages, see your code in action, and test changes.
If you want to proceed immeditely with running the client, database, and server, then follow the steps in the Running the Application section, below. Then, return here and continue to the next step of this section.
Step 4 - Make Changes and Test the Code 🔥
You are almost ready to make changes to files, but before that you should always follow these steps:
-
Validate that you are on the master branch
git status
You should get an output like this:
On branch master Your branch is up-to-date with 'origin/master'. nothing to commit, working directory clean
If you are not on master or your working directory is not clean, resolve any outstanding files/commits and checkout master:
git checkout master
-
Sync the latest changes from the upstream Chapter master branch to your local fork's master branch. This is very important to keep things synchronized and avoid "merge conflicts".
Note: If you have any outstanding Pull Request that you made from the master branch of your fork, you will lose them at the end of this step. You should ensure your pull request is merged by a moderator before performing this step. To avoid this scenario, you should always work on a branch separate from master.
This step will sync the latest changes from the main repository of chapter.
Update your local copy of the freeCodeCamp upstream repository:
git fetch upstream
Hard reset your master branch with the chapter master:
git reset --hard upstream/master
Push your master branch to your origin to have a clean history on your fork on GitHub:
git push origin master --force
You can validate if your current master matches the upstream/master or not by performing a diff:
git diff upstream/master
If you don't get any output, you are good to go to the next step.
-
Create a fresh new branch
Working on a separate branch for each issue helps you keep your local work copy clean. You should never work on the master branch. This will soil your copy of Chapter and you may have to start over with a fresh clone or fork.
Check that you are on master as explained previously, and branch off from there by typing:
git checkout -b fix/update-readme
Your branch name should start with fix/, feat/, docs/, etc. Avoid using issue numbers in branches. Keep them short, meaningful and unique.
Some examples of good branch names are:
- fix/update-nav-links
- fix/sign-in
- docs/typo-in-readme
- feat/sponsors
-
Edit files and write code on your preferred code editor, such as VS Code.
Then, check and confirm the files you are updating:
git status
This should show a list of unstaged files that you have edited.
On branch feat/documentation Your branch is up to date with 'upstream/feat/documentation'. Changes not staged for commit: (use "git add/rm <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: CONTRIBUTING.md modified: README.md ...
-
Always Run Code Quality Tools
Verify all automated code quality checks will pass before submitting a pull request because PRs with failures will not be merged.
- When using Docker Mode, run
NODE_ENV=test docker-compose exec app npm run lint-and-test
ORNODE_ENV=test docker-compose exec app npm run test:watch
to start "watch" mode. - When using Manual Mode, run
npm run lint-and-test
ORnpm run test:watch
to start "watch" mode.
- When using Docker Mode, run
-
Stage the changes and make a commit
In this step, you should only mark files that you have edited or added yourself. You can perform a reset and resolve files that you did not intend to change if needed.
git add path/to/my/changed/file.ext
Or, you can add all the unstaged files to the staging area using the below handy command:
git add .
Only the files that were moved to the staging area will be added when you make a commit.
git status
Output:
On branch feat/documentation Your branch is up to date with 'upstream/feat/documentation'. Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: CONTRIBUTING.md modified: README.md
Now, you can commit your changes with a short message like so:
git commit -m "fix: my short commit message"
We highly recommend making a conventional commit message. This is a good practice that you will see on some of the popular Open Source repositories. As a developer, this encourages you to follow standard practices.
Some examples of conventional commit messages are:
- fix: update API routes
- feat: RSVP event
- fix(docs): update database schema image
Keep your commit messages short. You can always add additional information in the description of the commit message.
-
Next, you can push your changes to your fork.
git push origin branch-name-here
For example if the name of your branch is fix/signin then your command should be:
git push origin fix/signin
Step 5: Propose a Pull Request (PR)
When opening a Pull Request(PR), use the following scope table to decide what to title your PR in the following format:
fix/feat/chore/refactor/docs/perf (scope): PR Title
An example is feat(client): night mode.
Scope | Documentation |
---|---|
api | For Pull Requests making changes to the APIs, routes and its architecture |
db | For Pull Requests making changes related to database |
client | For Pull Requests making changes to client platform logic or user interface |
docs | For Pull Requests making changes to the project's documentation |
-
Once the edits have been committed & pushed, you will be prompted to create a pull request on your fork's GitHub Page. Click on Compare and Pull Request.
-
By default, all pull requests should be against the Chapter main repo, master branch.
-
Submit the pull request from your branch to Chapter's master branch.
-
In the body of your PR include a more detailed summary of the changes you made and why.
-
You will be presented with a pull request template. This is a checklist that you should have followed before opening the pull request.
-
Fill in the details as they seem fit to you. This information will be reviewed and a decision will be made whether or not your pull request is going to be accepted.
-
If the PR is meant to fix an existing bug/issue then, at the end of your PR's description, append the keyword closes and #xxxx (where xxxx is the issue number). Example: closes #1337. This tells GitHub to automatically close the existing issue, if the PR is accepted and merged.
-
You have successfully created a PR. Congratulations! 🎉
Prerequisite: Follow steps 1 and 2 of the Contributing Code section, above, before continuing to the next step in this section.
Step 1 - Install Node.js and Run npx
Prerequisite: Node.js must exist on your system.
Note: Close and re-open your terminal after the installation finishes.
Ensure the Node.js tools are installed:
- Node.js 14 or greater -
node --version
and the output should be like v14.16.0 - npm 6 or greater -
npm --version
and the output should be like 6.14.11
Run npx recursive-install
to install all of the necessary dependencies.
This step will automatically read and process the package.json file. Most notably it:
- Downloads all Node package dependencies to the node_modules sub-directory
- Creates the .env configuration file if one does not exist.
Note: this is done "magically" via the postinstall hook.
Step 2 - Run the App Using Docker Mode OR Manual Mode
There are two approaches to running the Chapter application.
Based on your experience or preference, decide between the two options:
- Docker Mode: typically easier if you just want to start the application for the first time or don't want to run a local PostgreSQL database on your host computer. It will take longer to "boot up" the container than manual-mode and can be slow to reload some types of code changes.
- Manual Mode: more of a "hands-on" method, is more lightweight in that it's faster to "boot" and faster to refresh for some code changes, requires more knowledge of running PostgreSQL and configuring localhost services to play nice with the code.
Prerequisite: Docker must exist on your system:
- Windows - Docker Desktop
Note: Close and re-open your terminal after the installation finishes.
- Mac - Docker Desktop
- Linux
Ensure the Docker tools are installed:
- Docker using
docker --version
and it should output something like Docker version 19.03.13... - Docker Compose using
docker-compose --version
and it should output something like docker-compose version 1.28.5...
Make sure IS_DOCKER=TRUE is set in .env.
Run Docker Compose docker-compose up
from the root code directory and wait for the successful output as shown in the following example.
Note: This could take minutes for each line to appear.
db_1 | ... LOG: database system is ready to accept connections
client_1 | ready - started server on http://localhost:3000
app_1 | Listening on http://localhost:5000/graphql
Once Docker is running:
- The server will automatically restart anytime you save a .ts or .js file within the server/ directory.
- You can run any command within the container by prefixing it with
docker-compose exec app
, e.g.docker-compose exec app npm install express
- If you, or someone else via a commit, updates Dockerfile or the contents of its build directory, run
docker-compose build
to get the new image. Then, rundocker-compose up
to start the container's services.
Proceed to the Prepare the Database for Development step, below.
This is a much lighter development footprint than Docker Mode, but you will need to manually manage the client-server, database, and API server.
Prerequisite: PostgreSQL must exist and be configured.
Set IS_DOCKER= to blank in .env.
Run npm run both
to start the api-server and client-server:
Proceed to the Prepare the Database for Development step, below.
Step 3 - Prepare the Database for Development
The database may be empty or need to be recreated to get schema changes.See the Initializing the Database section, below, before continuing to the next step in this section.
Step 4 - View the Running Application
Once the app has started you should be able to pull up these URLs in your web browser:- Main Client Website - http://localhost:3000
- GraphQL Playground - http://localhost:5000/graphql
What do we need help with right now?
We are in the very early stages of development on this new application. We value your insight and expertise. In order to prevent duplicate issues, please search through our existing issues to see if there is one for which you would like to provide feedback. We are currently trying to consolidate many of the issues based on topics like documentation, user interface, API endpoints, and architecture. Please join our chat to stay in the loop.
I found a typo. Should I report an issue before I can make a pull request?
For typos and other wording changes, you can directly open pull requests without first creating an issue. Issues are more for discussing larger problems associated with code or structural aspects of the application.
I am new to GitHub and Open Source, where should I start?
Read our How to Contribute to Open Source Guide.
We are excited to help you contribute to any of the topics that you would like to work on. Feel free to ask us questions on the related issue threads, and we will be glad to clarify. Make sure you search for your query before posting a new one. Be polite and patient. Our community of volunteers and moderators are always around to guide you through your queries.
When in doubt, you can reach out to current project lead(s):
Name | GitHub | Role |
---|---|---|
Fran Zeko | @Zeko369 | Admin UI, routes, models, and data migrations |
Ayotomide Oladipo | @tomiiide | Public-facing client pages / forms |
Timmy Chen | @timmyichen | API |
Patrick San Juan | @pdotsani | Google Authentication |
Jonathan Seubert | @megajon | |
Vaibhav Singh | @vaibhavsingh97 | Heroku 1-click deployment |
Jim Ciallella | @allella | Documentation |
Quincy Larson | @QuincyLarson | Executive Lead |
You are a champion :).
We use GraphQL to define the API structure of the application.
The GraphQL Playground has "Docs" and "Schema" tabs on the right side of the page. You can see them:
- If you are already Running the Application at http://localhost:5000/graphql
- If you don't have a running app at GraphQL Playground. (Note, this is a free-tier of Heroku. Hit refresh every minute or two if the page fails to load and it should eventually "wake" the server.)
An important, local .env configuration file exists in the root code directory. It's used to store environment variables and their associated values.
Any changes to .env will not and should not be committed into your origin fork or the Chapter upstream. Plus, a .gitignore rule exists to prevent it. Do not remove this rule or otherwise attempt to commit your .env to any Git repository.
Keeping your .env out of the repositories is important because the file will contain "secrets" (usernames, passwords, API keys) and other values which are specific to you and your local development environment.
The .env file is automatically created via the Running the Application section when you follow Step 1 - Install Node and Run npx.
This configuration pattern is based on the dotenv package and is also popular in other frameworks and programming languages.
The initial values of the .env will be copied from the .env.example file. However, you should not attempt to add any of your personal configuration values / secrets to the .env.example file. The purpose of .env.example is as a template to declare any variable names the application will need and any values in it are "dummy" / example values purely as a guide to help other developers with their .env file.
PostgreSQL is our database and TypeORM is used to map tables to JS objects.
Our database schema and ER Diagram are hosted online on a GitHub pages domain.
This is currently manually generated and updated on the gh-pages branch by running SchemaSpy.
- Set your specific values in .env.
- For security, it's ideal to change the username and password from the default values.
- In Docker Mode, the Docker database container will be exposed to the host computer on Host: localhost and Port: 54320. Thus, avoiding potential port conflicts in the case your computer is running PostgreSQL locally for other projects.
- In Manual Mode, the PostgreSQL port will be as you configured it, the default being Host: localhost and Port: 5432
- If you're using a remote PostgreSQL server, like ElephantSQL, then the Host and Port will be provided by the service. You'll also need to update the
DB_URL
value in .env.
- pgAdmin, Postico or Table Plus, can use your mode's Host and Port values as described above.
- psql Client
- In Docker Mode -
psql -h localhost -p 54320 -U postgres
. You don't have to rundocker-compose exec...
commands to "talk" to the PostgreSQL container. - In Manual Mode -
psql -h localhost -p 5432 -U postgres
- In Docker Mode -
Our DB commands closely mirror their Rails counterparts (there isn't anything quite similar to ActiveRecord and RailsCLI in node yet, so till then #rails 🚋 )
npm run db:generate NAME
-> rake db:generate NAME
, note that this command checks for the diff between models and db, unlike rails where you need to specify the migration by hand
npm run db:migrate
-> rake db:migrate
npm run db:seed
-> rake db:seed
npm run db:reset
-> rake db:reset
If you're starting the application for the first time, or syncronizing with the latest development changes, then you like need to:
- drop the database - to delete all the structure and data
- migrate the database - to structure by setup tables based on the schema
- seed the database - development is easier with a database full of example entities. The process of creating example entities in the database is called seeding
The npm run db:reset
command will do all three tasks: drop, migrate, and seed.
If you prefer to run some or all of the steps manually, then they are:
npm run db:drop
npm run db:migrate
npm run db:seed
npm run typeorm entity:create -- --name=ModelName
This would create ModelName.ts in server/models
To keep everything DRY, add extends BaseModel
to the class and import it from 'server/models/BaseModel' to no repeat id, createdAt, and updatedAt fields on every single model
You could also run npx typeorm
since here you're not actually loading any ts files, but because regular npx typeorm
runs inside of node it import from .ts files, so we run it with ts-node
and our custom server config (check package.json)
After you created a new model or updated an existing one, you need to generate a migration for those changes. To do so run:
npm run db:generate MIGRATION_NAME
Since this runs a compare agains the current db schema, you need to have the DB running (If you're using docker-compose, you need to have that running).
After that, check the generated SQL in db/migrations/date-MigrationName.ts
You can manually run them by doing
npm run db:migrate
and then check if it happened correctly
npm run typeorm migration:show
it should ouput something like
[X] Chapter1574341690449
...
[X] MigrationName1575633316367
Visit our chat for assistance. Or, create an issue for new bugs or topics.