Skip to content

Dev setup

Jonathan Sharpe edited this page Jul 8, 2023 · 30 revisions

Requirements

You need Node and NPM installed to use this starter kit. It's tested with the active and maintenance LTS versions of Node.

You can check your current versions of these tools with node --version and npm --version.

OS

The automated testing all takes place in Ubuntu 22.04, but other Linux versions should be fine and macOS (note Macs with Apple silicon require Node 16+) and Windows should both work too.

Optional

The following global tools are not required but can help to simplify development:

  • NVM - lets you manage multiple versions of Node on one machine (the version this project currently uses is in .nvmrc).
  • direnv - lets you manage environment variables (and the active version of Node) based on the .envrc of the directory you're in.

Installation

  1. Clone your repository to your local machine.

  2. cd into the repository's directory on your local machine. You can run git status to check you're in the right place, it should say something like

    On branch main
    Your branch is up to date with 'origin/main'.
    
    nothing to commit, working tree clean
    
    • If you have direnv installed, you may see

      direnv: error .envrc is blocked. Run `direnv allow` to approve its content.
      

      If you trust the repo, you can run direnv allow as suggested.

  3. Install the dependencies by running npm install; this will create a node_modules/ directory and fill it with the requirements specified in package.json and package-lock.json.

  4. [If you're using the CYF Postgres version] Set up a database and configure the app to connect to it, see Dev setup#Databases

    Note: even if you've deployed to Render or similar, I'd suggest setting up a separate database for local development (otherwise any errors or experiments in your local development can impact your production deployment and the rest of your team).

  5. Run the app using either npm run dev (developer mode, with watching/reloading of your code as you make changes) or npm run serve (production mode, to check what will actually get deployed) - see Scripts for more details.

  6. While one of those two scripts is running, visit http://localhost:3000 to see the app:

    If you see any errors, or the site doesn't look like the image above, check out Home#Common errors.

  7. Now that you're up and running, see Structure to get an idea of the layout of the kit and where to start putting your code.

Databases

If you're using the CYF Postgres fork, you'll need to supply a database for the app to use on startup.

Postgres

By default the app tries to connect to postgres://localhost:5432/cyf, or this can be overridden with either:

  • the single DATABASE_URL environment variable (which e.g. Heroku sets automatically); or
  • any or all of the separate DB_HOST, DB_NAME, DB_PASS (or DB_PASSWORD), DB_PORT and DB_USER (or DB_USERNAME) environment variables.

These variables can be set in the .env file in the repository root, see Dotenv. You can see configuration and connection data (or edit it if needed) in server/db.js and server/utils/config.js.

⚠️ Do not include credentials (usernames, passwords, etc.) in your source code. Store them only in .env, which is excluded from git tracking, for local development, and look up how to set real environment variables in your deployment environment (e.g. Heroku, Render, ...) for production.

To run Postgres locally see these CYF instructions, or if you're more confident:

  • Official installer: follow the instructions at https://www.postgresql.org/download/

  • Homebrew (macOS only): brew install postgresql then brew services start postgresql

  • Docker: assuming you've installed Docker, see https://docs.docker.com/get-docker/, either:

    • Use Docker Compose to start the database defined in docker-compose.yml: docker compose up --detach

      • The database URL will be postgres://postgres:opensesame@localhost:5432/cyf
    • Run a postgres container directly:

      docker run --detach --env POSTGRES_DB=<db> --env POSTGRES_PASSWORD=<password> --name cyf-postgres --publish 5432:5432 postgres
      
      • The database URL will be postgres://postgres:<password>@localhost:5432/<db>

    You can start and stop the container as needed using docker stop cyf-postgres/docker start cyf-postgres.

Once you have Postgres up and running, unless you used Docker, createdb cyf to create the database the app will use.

Ports

If you see EADDRINUSE when trying to run dev or serve, you may have other processes running on your machine that are using ports the starter kit expects. You can check which processes these are using the command:

lsof -i :<port>

If you see existing npm commands running, you may have terminals running in the background somewhere - find them and stop them! If you see some other program running, you may need to switch ports. You can do this as follows:

  • npm run dev:
    • Frontend (default: 3000): you need to change the line port: 3000, in client/webpack/dev.config.js
    • Backend (default: 3100): you need to change this in two places, the line target: "http://localhost:3100", in client/webpack/dev.config.js and the line "dev:server": "cross-env LOG_LEVEL=debug PORT=3100 nodemon --exitcrash --inspect --delay 500ms --watch server --exec babel-node server/server.js", in package.json.
  • npm run serve:
    • Backend (default: 3000): the easiest way to override this is when you actually run the server, so you can do e.g. PORT=3210 npm run serve. Alternatively you can change the line port: parseInt(process.env.PORT ?? "3000", 10), in server/utils/config.js.

Lockfile versions

The lockfile version is now pinned to v3 in the .npmrc, for compatibility with NPM from v8 and up.

NPM v7 introduced new (v2 and 3) formats for the package-lock.json. If you try to collaborate in a team where some people use NPM v6 and others use v7+, the lockfile can keep getting changed and cause large pull request diffs. Either:

  1. All use NPM 6;
  2. All use NPM 7+ (either all using Node 16 or upgrading NPM with npm install --global npm@<version>);
  3. Pin the lockfile-version in the .npmrc file (note this is only honoured by NPM v8.1 and above); or
  4. [Not recommended] Add the package-lock.json to .gitignore (this could cause hard-to-debug issues where different machines have slightly different versions of your dependencies).

To help in maintaining consistency, you can narrow the requirements in the package.json engines field to e.g.:

  "engines": {
    "node": "^16.13.0",
    "npm": "^8.1.0"
  }

(This would require everyone to use the same version of Node, you can use e.g. https://semver.npmjs.com/ to test out different requirements and the versions they match.)

You should also edit any other files you're using that refer to the supported Node/NPM versions (e.g. README.md, .github/ISSUE_TEMPLATE/bug-report.md, .github/workflows/push.yml, ...).

Clone this wiki locally