Skip to content

newjersey/dol-mcnj-main

Repository files navigation

My Career NJ

build

Overview

This repo is the home for the My Career NJ web app (mycareer.nj.gov), a one-stop shop for New Jerseyans seeking to explore training programs, in-demand career insights, and data-driven career advice custom-tailored to users’ experiences. Note that this repository does not yet include Career Navigator.

Architecture

  • The frontend is written in Typescript, a single page app built with React using the create-react-app setup.
  • The backend is written in Typescript, with an Express-based server API.
  • The databases include multiple PostgreSQL tables (which are imported from raw CSV files stored in backend/data directory). For more information on the tables, see the data_model guide.
  • The entire app is deployed to production Amazon Web Services (AWS) instances in a Node 18 environment. We use CircleCI for continuous integration/deployment.

References

Getting started

After cloning this repo, run through the following steps to run the app locally.

Install prerequisites

If you are using a newer Mac (Apple Silicon), you will likely need to install jq. Run brew install jq or install a pre-built binary here.

Install node dependencies

./scripts/install-all.sh

Set up Postgres DB

  1. If not already installed, install postgres

  2. Create postgres database on your local machine:

psql -c 'create database d4adlocal;' -U postgres
  1. Run database migrations from d4ad directory:
./scripts/db-migrate.sh

Note: If you get a key error when running the script, make sure that you have the correct DB password for the user postgres updated in the code. It assumes the password is an empty string, but it will be what you entered when you initially set up the postgres user after installation. You need to update it in database.json and the fall-back value in app.ts.

Run app locally

In one terminal window, start backend dev server:

./scripts/backend-start.sh

In another window, start frontend dev server. It should automatically open up localhost:3000 in your browser.

./scripts/frontend-start.sh

Development

Pushing changes

Always push via ship-it (why?)

./scripts/ship-it.sh

CI/CD

We use circleci for CI/CD and deploy both the user research environment to Google Cloud Platform (GCP) environments. Pipelines for AWS prod, test, dev incoming. Our pipeline is:

  1. npm install (frontend and backend)
  2. run all unit tests (frontend and backend)
  3. build code and run feature tests
  4. deploy to GCP User Research2 environment (reach out to developer for URL or look in D4AD User Research 2 App Engine settings)
  5. Manual approval step - go to CircleCI build and "prod-approval" step, and click "Approve" button.
  6. deploy to GCP User Research2 environment

Environment Variables

Amazon Web Services

TBD

Feature Flags

This will likely change as features are rolled out.

  • REACT_APP_FEATURE_MULTILANG - Enable/disable multi-language support in the React app.
  • REACT_APP_FEATURE_CAREER_PATHWAYS - Toggle the display of career pathways feature as well as any reference to it.
  • REACT_APP_FEATURE_CAREER_NAVIGATOR - Toggle the display of the Career Navigator landing page as well as any references to it.
  • REACT_APP_FEATURE_PINPOINT - Show or hide any instance of the Pinpoint email collection tool.
Database

Dev, QA, and production databases are hosted in AWS as SQL instances running PostgreSQL.

  • DB_DEV_PASS - Password for postgres user in dev environment
CareerOneStop

Dev and prod environments use a CareerOneStop account owned by NJ Office of Innovation.

  • CAREER_ONESTOP_USERID - account username used both in dev and prod
  • CAREER_ONESTOP_AUTH_TOKEN - account auth token used both in dev and prod
O*NET
  • ONET_BASEURL - O*NET account base URL (dev + prod)
  • ONET_USERNAME- O*NET account username (dev + prod)
  • ONET_PASSWORD- O*NET account password (dev + prod)
Contentful GraphQL Content API
  • BASE_URL - Typically https://graphql.contentful.com
  • ENVIRONMENT - master, unless you have multiple environments
  • SPACE_ID - Your project's unique space ID
Sentry
General
  • IS_CI - boolean flag for whether environment is deployed using continuous integration
  • NO_COLOR
  • ZIPCODE_BASEURL
  • ZIPCODE_API_KEY

Deployment

Generally, developers won't have to do this - we have automated deploys to dev and prod via circleci.

Build frontend, build backend, compile all into one directory:

./scripts/build.sh

Start the production server (frontend & backend):

./scripts/prod-start.sh

Testing and linting

Use these two scripts below in order to run our normal testing flows, which include:

To run all jest tests, and linting:

./scripts/test-all.sh

To run cypress feature tests:

./scripts/feature-tests.sh

Tools and libraries

  • UI Components: We use a combination of Material UI React components and modular CSS from the New Jersey Web Design System, which is a customized version of the U.S. Web Design System.
  • Internationalization (i18n): We use the i18next library to implement the logic of storing English and Spanish content and switching between the two on the client-side. All the content is stored in JSON files in frontend/src/locales.
  • Routing: We add client-side routing to this single page app using the Reach Router library, similar to the more common React Router.
  • User engagement: We track user engagement using Google Analytics, including pageviews and specific event-based interactions that we implement manually in different parts of the app, such as tracking what filters a user clicks on the training search page. Please request access from the NJ Office of Innovation in order to view our analytics dashboards.
  • Accessibility: We have automated a11y tests that run as part of our Cypress feature tests using the cypress-axe package. We also use tools such as axe DevTools and WAVE Chrome extensions to do manual checks.
  • Data APIs: We fetch data from the following Web APIs: O*NET Web API, CareerOneStop. To access API keys to set as environment variables, request access for the NJInnovation Bitwarden account, and see the "Training Explorer Secrets" file in it.
  • SDKs - We use AWS SDK for JavaScript for Node.js to collect user email address signups and retrieve secrets on the back-end.

Dependency inversion

This repo uses good-fences to enforce module boundaries. Most importantly, the backend and frontend cannot import from each other.

Additionally, fences are used in the backend subdirectories to enforce dependency inversion. The routes and database folders depend on the interfaces defined in domain (only - not on each other), and domain is not allowed to import from any of these implementation directories.

Fences are enforced via a linting-like command that will fail when any violations are flagged:

npm --prefix=backend run fences
npm --prefix=frontend run fences