This monorepo contains code for most of BlueDot Impact's custom software. Reading this README carefully can save you a lot of time.
- What's included
- Get started
- Background knowledge to contribute
- Developer setup instructions
- Guide: Adding a new app
- Reference: General package structure
This repository has the code for:
- availability: Collect time availability information from users
- meet: Record meeting attendance, and host meetings with the Zoom Web SDK
- login: A custom build of Keycloak
- login-account-proxy: An app for setting up users in Keycloak from Bubble
- miniextensions-proxy (forms.bluedot.org): Host forms on a custom domain
- posthog-proxy (analytics.k8s.bluedot.org): Reverse proxy to send analytics to PostHog
- storybook (storybook.k8s.bluedot.org): App to demo and document design system components
- website-25 (website-25.k8s.bluedot.org): New public website for 2025
- website-proxy (bluedot.org): Reverse proxy to split traffic between the new and old website during migration
- infra: Deploying the above applications on Kubernetes
The following key parts of our software are not in this repository because they are built in 3rd party services that are hard to open-source the code for:
- Other public websites (parts of bluedot.org, aisafetyfundamentals.com, biosecurityfundamentals.com etc.): Wordpress
- Course hub: Bubble
- Application forms: MiniExtensions
- Application form short links: Short.io
- Primary database: Airtable
The following key parts of our software are not in this repository because they use substantially different toolchains, and are a pain to set up in a monorepo:
- Various Airtable extensions
- Keycloak theme
- Airtable standards
We welcome contributions! To help improve BlueDot Impact's software:
For simple edits e.g. typos or editing documentation, you should be able to search for the text in this repository and make edits in the GitHub UI.
For more complex edits, check you have the core skills to contribute, then follow the developer setup instructions below.
If you run into any difficulties, raise an issue or contact us.
What if I want to use BlueDot Impact's software myself?
You're very welcome to use and adapt our software for your own purposes, subject to the repository license. In general most of our apps are packaged as Docker containers, and most of our libraries are TypeScript NPM packages.There isn't yet extensive documentation on using our software for your own purposes. We'd be happy would accept contributions that make it easier for others to use our software. This could be by improving the way apps are structured or adding documentation.
How will my contribution be handled?
Our general principle for reviewing contributions is 'does this make things better' rather than 'is this perfect'. We'll generally try to give you feedback, but given our limited resources we sometimes may not always be able to do this.When contributing, you agree that we can use your contribution how we see fit, and you relinquish any copyright, patent, moral or other intellectual property rights in your contribution.
We recommend most contributors learn how to:
- Navigate their terminal and shell
- Contribute code on GitHub
- Read and write TypeScript code
- Use the basics of NPM and Node.js
- (recommended, macOS only) Install Homebrew
- Install Git
- On macOS with Homebrew:
brew install git
- On Ubuntu Linux:
sudo apt install -y git-all
- On macOS with Homebrew:
- Install Node.js 22
- On macOS with Homebrew:
brew install node
- On Ubuntu Linux:
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - && sudo apt-get install -y nodejs
- On macOS with Homebrew:
- Install Docker client. NB: NOT Docker Desktop.
- On macOS with Homebrew:
brew install docker
- On Ubuntu Linux: instructions
- On macOS with Homebrew:
- Install and configure a container runtime.
- On macOS with Homebrew:
brew install colima && brew services start colima && docker context use colima
- On Ubuntu Linux: already installed with client
- Other platforms: Docker Engine (NB: NOT Docker Desktop)
- On macOS with Homebrew:
- Install kubectl.
- On macOS with Homebrew:
brew install kubectl
- On Ubuntu Linux: instructions
- On macOS with Homebrew:
- (recommended) Install Visual Studio Code
- On macOS with Homebrew:
brew install --cask visual-studio-code
- On macOS with Homebrew:
- Clone this repository
- To clone the main repo (you might want your fork instead):
git clone git@github.com:bluedotimpact/bluedot.git
- To clone the main repo (you might want your fork instead):
- Change directory into the cloned repository, and install dependencies with:
npm install
Then find the app or library you want to contribute to. It should follow the general package structure. Usually this means you can change directory into the relevant folder, put any necessary values in .env.local
(if present), edit code in src
, and run
npm run start
or
npm run test
Some packages have their own README with further developer setup instructions specific to that app, plus useful information about how the app works. Read this!
Over time other people will make changes to the repository. Usually to get up to date with those changes, you'll need to pull the latest changes from the master branch, then re-run
npm install
The above should be enough to edit existing applications. To create a new Next.js app (which is usually what you'll want):
- Copy an existing app folder.
frontend-example
is a good place to start because it is simple. - Rename the copied folder, and the name of the app in its
package.json
, then runnpm install
- Add the app to infra's serviceDefinitions.ts
- Copy the config for frontend-example, but put your app name in
- You can remove secrets your app doesn't need (e.g. if it doesn't need to talk to Airtable or Slack)
- If you need to add a secret, see infra's README
- Commit your changes to the master branch
CI/CD might fail the first time. If so, just re-run the failed jobs. This happens because there's a race condition between:
- the infra being set up and expecting a docker container to pull
- the docker deploy script wanting infra to deploy to
This repository is split up into packages in the folders:
libraries
: code that is reused or shared across applicationsapps
: final products that actually get deployed, usually as web services
For example, the shared UI code for common components like buttons is a library. This would be consumed by multiple apps, such as the time availability form.
Inside each package folder, the common files you'll find are:
- (always)
package.json
: defines the NPM scripts, dependencies, and sometimes other package configuration. Thepackage.json
should usually identify the entrypoint (for libraries) or have at least a start script (for apps). Common scripts include:npm run start
: Start the application locally. The port should usually be printed to the terminal, and then you can visitlocalhost:<port>
in your browser e.g.localhost:8000
.npm run test
: Run automated tests, usually defined the files ending in.test.ts
or.test.tsx
. Most packages use vitest - see the vitest CLI docs for help.npm run test:watch
: Run the automated tests in an interactive watch mode. This runs the relevant tests automatically each time you edit the code.npm run lint
: Check for lint issues. Visual Studio Code should usually highlight these for you already.npm run build
: Build the application. This usually finds any type errors, which Visual Studio Code should usually highlight for you already.npm run postinstall
: Perform any extra steps to setup the application for development. Usually things like creating configuration files for local development. You usually don't need to run this manually, as it runs when you runnpm install
.npm run deploy:cd
: Actually deploy the app, usually into the production (real-world) environment. You usually don't need to run this manually, as it is run by CD tooling when you merge your changes into the master branch.
README.md
: documentation to explain what the package does, how to use it, and how to contributesrc
: most of the code usually lives here. You usually want to edit files in this folder.pages
: pages in the web app. For examplepages/some-page.tsx
usually corresponds toapp.bluedot.org/some-page
. Theapi
folder contains API routes rather than webpages (learn more in the Next.js docs).components
: components reused within the web app. If the component is likely to be useful for multiple applications, consider moving it to theui
package.lib
: helper scripts for use around the application, that aren't componentsindex.ts
: usually the entrypoint, i.e. what runs when starting or deploying an app, or the what is imported when importing a library.public
: static files for web hosting directly, usually fonts or images
.env.*
: environment files, usually to set secrets or configuration..env.local
: for local development, e.g. when runningnpm run start
. This isn't synced to git, so you can put real secrets in here. If you have issues with your environment, try deleting this file and runningnpm install
again (maybe save the values first if they're important secrets!) - this should usually replace it with the template file..env.local.template
: intended to help people create their own.env.local
file. This is synced to git, so you should only put example or non-secret values here..env.test
: for the test environment, e.g. when runningnpm run test
.
tools
: custom tools helpful for developing the app, often referred to by NPM scripts.Dockerfile
: (apps only) code to help transform the package into a Docker container to be easily deployed.dist
,.turbo
: built or transformed outputs are put here. You can usually ignore this folder.node_modules
: any special dependencies for this specific package, that can't be put at the workspace root usually because of clashing versions. You can usually ignore this folder.
In terms of tools and external libraries, we usually use:
- Coding language: TypeScript
- Script management: NPM
- Custom dev tooling: Node.js or Bash (in the
tools
folder) - Databases: Airtable (via airtable-ts) or Postgres (via kysely and kanel)
- APIs: JSON via REST. Use path parameters and request bodies to send information. Web services should respond with an X-BlueDot-Version header in the format
yyyyMMdd.hhmmss.git_short_hash
(via environment variableVERSION_TAG
). - Authentication: JSON web tokens, with sign-in via Open ID Connect (OIDC)
- Linting tool: eslint
- Testing framework: vitest
- Web applications
- Front-end library: React.js
- Framework: Next.js, usually using the path router and avoiding SSR
- Styling: Tailwind CSS
- Components: Our own ui or @adobe/react-spectrum
className
util: clsx- Global state store: zustand
- Schema validation: zod
- Infrastructure management: Pulumi
- Reverse proxies: nginx
- CI and CD: GitHub Actions via .github
- Deployment: Docker on K8s via infra
In general, we try to keep to the above structure and tools as much as possible between packages. This reduces the mental effort required to switch between working on different packages, and eases maintenance burden. We're fans of boring technology.