This guide helps you get started running and interacting with a local development server and tests. If you are a Full Time SWE onboarding, first check out the links/tutorials/account-settup detailed in New Full Time SWE Onboarding Material.
Start here! This step is a prerequisite for everything that follows, even if you only want to interact with a local server without pushing changes. If you're working in Windows, check out Getting started with Windows.
- 3.Configure an SSH key with your GitHub account. We recommend not including the "UseKeychain yes" line or setting a password.
- 4.Install Docker
- On Mac
- Run Docker Desktop and go to Preferences > Resources to increase max RAM for containers to at least 4GB (ideally 6GB), otherwise sbt compiles can get killed before completing and produce strange runtime behavior.
- On Linux
- Configure Docker to run in Rootless Mode. This will create generated files as the correct user, otherwise file permission issues occur.
- 5.Clone the CiviForm repo. This will create a copy of the codebase on your machine:
- 1.Open a terminal and navigate to the directory you'd like the copy of the CiviForm codebase to live.
- 2.In that directory, run the following (and/or refer to this guide):
You may use whichever IDE you prefer, though DO NOT use the IDE's built-in sbt (Scala Build Tool) shell if it has one. Instead, run
bin/sbtto bring up an sbt shell inside the Docker container. The sbt shell allows you to compile, run tests, and run any other sbt commands you may need
The easiest way to get IntelliJ to index the project correctly is to install the Scala plugin and open the project by specifying the build.sbt file in IntelliJ's open existing project dialog. If this isn't done correctly IntelliJ probably won't load library code correctly and will complain that it can't find symbols imported from libraries.
This setup will only include the files under (.../server), therefore, if you would like to edit other files under .../civiform, you need to add additional modules manually:
- Go to File/Project Structure,
- Select modules
sourcesare selected in second and third column,
- Click on + on the right handside to add all folders under civiform except "server" to the content roots
If you still have trouble getting some symbols to show (such as
routespackages), try the following, in order:
- 1.Go to Project Structure and add
target/scala-2.13to your Sources in the
- 2.Go to the sbt shell within IntelliJ and run
- 3.Go to Preferences, then "Languages and Frameworks", then "Scala". Switch Error Highlighting from "Built-in" to "Compiler".
- 1.Install the following extensions:
bin/vscode-setupto generate a pom.xml file that allows VSCode to resolve dependencies
- 3.Open the workspace file
- 4.Metals automatically detects the project. Click
Import Buildat the prompt.
sbtat the prompt for multiple build definitions.
- If source code isn't being indexed / symbols aren't found, you may need to clean the Java workspace. Trigger the command pallet and select
Java: Clean Java Language Server Workspace
- If a new dependency is added, the
pom.xmlfile may be out of date. You'll need to either add the dependancies manually, or re-run the bin/vscode-setup script to regenerate the file.
VSCode uses the following files
- server/pom.xml (maven dependancies for symbols)
- server/.settings/*. (generated by
- civiform.code-workspace (opens the top level directory, and server)
Note: the project makes heavy use of shell scripts for development tasks. Run
bin/helpto see a list of them.
- 1.To run the application, navigate to the
civiformdirectory you created when you cloned the repo and run the following:bin/run-devTo run the application using Azure instead of AWS, run:bin/run-dev –-azure
This will start up a dev instance of the application that uses Azurite, the Azure emulator, instead of local stack, the AWS emulator. This script sets an environment variable,
STORAGE_SERVICE_NAMEtelling the application to run using the Azure emulator instead of AWS.
Tip: Once you have the local server working, you may want to set
USE_LOCAL_CIVIFORM=1by default in your environment. This will speed up reruns by not always redownloading the latest docker images (1-2GB each) which is not usually necessary.
Warning: There's a known issue where you may encounter a compile loop, the most reliable way to address that is to do
bin/sbt cleanbefore the above.
- 2.Once you see "Server started" in your terminal (it will take some time for the server to start up), you can access the app in a browser at http://localhost:9000. Be patient on the initial page load since it will take some time for all the sources to compile.
For login and file upload to work with your local server, you need to edit your
/etc/hostsfile to include the following:
# Required for test AWS S3 bucket
This provides a local IP route for the 'dev-oidc', 'azurite', and 'localstack' hostnames.
Creating questions and programs in CiviForm is a bit time consuming to do manually with the UI, so in dev mode there is a controller action that generates several for you. You can access this feature at
We know setting up a development environment can have some snags in the road. If something isn't working, check out our Troubleshooting guide or reach out on Slack.
This section will help you run CiviForm unit and browser tests in a basic way. For more information on writing and debugging these tests, check out the Testing guide.
If you'd like to run a specific test or set of tests, and/or save sbt startup time each time you run the test(s), use the following steps. This is recommended for developer velocity.
- 1.Bring up an sbt shell inside the Docker container by running:bin/sbt-test
- 2.Run any sbt commands! For example:testOnly services.question.types.QuestionDefinitionTesttestOnly services.question.types.QuestionDefinitionTest -- -z getQuestion*test
If you'd like to run a specific test or set of tests, run the following:
bin/run-ts-tests file1.test.ts file2.test.ts
To run the browser tests (includes all the Playwright tests in
civiform/browser-test/src/, there are two steps:
- 1.Bring up the local test environment using the AWS emulator. Leave this running:bin/run-browser-test-env
- 2.Once you see "Server started" in the terminal from the above step, in a separate terminal run the tests in a docker container:bin/run-browser-testsOr, to run a test in a specific file, you can pass the file path relative to the
Browser tests are heavy handed and can take a while to run. You can focus the run to only execute a single
describesuite per file by prefixing it with
To create Questions and Programs that use them, you need to log in as a "Program and CiviForm Admin" through http://localhost:9000/loginForm .
You can return to that screen to switch to a Guest user and back again to an Admin as needed.
You can change the logging levels by editing conf/logback.xml. This can help get a deeper understanding of what the server is doing for development.
To generate coverage report, run the following:
Navigate to server/code-coverage/report/html/index.html and see the detailed report of the code coverage data and also dig deep to see how much your implemented classes are covered.
To format your code, run:
By default, this will format any files that have diffs compared to
origin/main. Diffing against
origin/main, however, can have a lot of noise if you haven't synced in a while. You can run this against a different diffbase with:
bin/fmt -d <diffbase>
# Diff against your local main branch:
bin/fmt -d main
# Diff against a specific commit:
bin/fmt -d <commit ID>
# Diff against the current commit:
bin/fmt -d HEAD
# Diff against the previous commit:
bin/fmt -d HEAD^
To learn about the CiviForm tech stack and standards, head to Technology overview and Development standards.