Guide to contributing code to Specify

Thank you for the interest in contributing to Specify’s codebase! We welcome contributions of all kinds, including bug fixes, improvements, documentation, etc.

We value contributions from all members of the community, regardless of experience level. Whether you are a seasoned open source contributor or a newcomer to the world of software development, your help is greatly appreciated.

To get started with contributing to Specify 7, this guide will provide you with the information you need to understand the project, its goals, and how you can help.

We also encourage you to reach out to the Specify 7 team with any questions you may have. You can contact the team at support@specifysoftware.org.

Code Review and Integration Philosophy

Our contribution process is grounded in clear requirements, thoughtful changes, and collaborative review. Before contributing, please review our SCC Mission Statement and Core Values.

  1. We expect all new features to be preceded by strong requirements that have been reviewed and approved by our team. If you are interested in contributing to the main codebase, please share requirements with us in advance so we can provide feedback, or propose features based on requirements written by the core SCC team.

  2. Make commits as atomic and descriptive as possible. We want to understand the thought process behind code contributions. We encourage the use of Conventional Commits to make commit history easier for both people and tooling to read.

  3. Submit work as pull requests in this repository. If you are interested in contributing a pull request, contact support@specifysoftware.org with your GitHub username.

When opening a pull request, follow the PR template and include:

  • A clear description of the PR
  • Screenshots for relevant UI changes
  • Testing instructions (what you tested and how to validate it)

Getting Started

Preferred way to do Specify 7 development is though our development composition.

Documentation for getting development Docker composition working

Issue Tracking

All feature requests and bugs are tracked on GitHub. Each issue is sorted into a project. Each project represents a major Specify 7 component.
A list of all projects

If you found a bug, feel free to open a GitHub issue. Similarly, if you are interested in fixing some issue or adding new feature, feel free to do so! If you want to work on a larger feature, it would be best if you get in touch with us first so that we can make sure the process is smooth and efficient.

First Steps

It’s recomended to start with issues that are labled with good first issue as those require less knowledge of the codebase and are as not urgent. These would prepare you for taking on larger GitHub issues.

Code Documentation

Review The Architecture

Front-End

On the front-end, we are using TypeScript, React and Tailwind CSS.

Back-End

Back-end uses Python and Django. It also works closely with a MySQL/MariaDB database both though Django ORM and though SQLAlchemy.

IDE Setup

No special IDE configuration is required, but some optional plugins would improve developer experience. That document includes a short list.

For a full list, see GitHub - specifysystems/code-principles: A central place for code-style guidelines and best practices for Specify and Lifemapper organizations · GitHub

In the browser, you can install React Devtools extension to make debugging React components easier.

Code-Style

We prefer functional programming paradigm. In our opinion, perfect code* consist of small and pure functions that have clear unit tests, and can be combined together to solve a complex task.

On a static analysis side, we use strict TypeScript type checking and Prettier formatting to make code less buggy and more consistent.

Additionally, ESLint goes beyond that to provide close to a thousand of static analysis checks and quick fixes, all in a name of clear and bug-free code. Our ESLint configuration is located in @maxxxxxdlp/eslint-config-react

Support

A great deal of user-facing documentation is available in the Speciforum. Most of it is available to users from member institutions only, thus consider joining the Specify Software Consortium if you are interested in becoming a user of Specify 7.

If you are stuck and need help, consider emailing our support at support@specifysoftware.org, opening a GitHub issue or posting a question on our Discourse forum as appropriate.

Contact Option Link
General Inquiry support@specifysoftware.org
Bug Report GitHub Issue
User Question Discourse Forum

Installing Specify Locally

If you just want to get Specify 7 running, the process is simple: clone the repository, make sure Docker is available, and run docker compose up from the project root. The application will initialize itself and guide you through setup in the browser.

What You Need

Install the following on your machine:

  • Docker Desktop with the Docker Compose plugin.
  • Git for cloning the repository.
  • VS Code or another editor you are comfortable with.
  • A MariaDB/MySQL client if you want command-line access to the database.
  • Optional: a database GUI such as DBeaver CE.

If you want the command-line client on macOS, install it without a server:

brew install mysql-client
echo 'export PATH="/opt/homebrew/opt/mysql-client/bin:$PATH"' >> ~/.zshrc && source ~/.zshrc

On Ubuntu/Debian:

sudo apt-get update && sudo apt-get install -y mariadb-client

[!warning]
Do not install a local MariaDB/MySQL server. Specify 7 runs its database inside Docker.

host.docker.internal Asset Server DNS resolution

When running Specify 7 locally, the .env file configures SERVER_NAME=host.docker.internal and the asset server URL accordingly.

ASSET_SERVER_URL=http://host.docker.internal/web_asset_store.xml
# Make sure to set the `ASSET_SERVER_KEY` to a unique value
ASSET_SERVER_KEY=your_asset_server_access_key

This is necessary because:

  • Docker containers (specify7, worker) resolve host.docker.internal
    through Docker’s extra_hosts directive.
  • The browser needs to resolve host.docker.internal to upload/download attachments through nginx (port 80).

Docker Desktop normally registers host.docker.internal in macOS DNS
resolution. If this is missing (symptoms: ERR_NAME_NOT_RESOLVED in the browser console when trying to upload attachments, specifically for /fileupload or /fileget requests), you can add it manually:

sudo sh -c 'echo "127.0.0.1 host.docker.internal" >> /etc/hosts'

This causes the browser to route attachment requests through the nginx
container, which in turn proxies to the asset-server container.

Windows-Specific Instructions

You may need to set a Git config flag around how it handles auto-converting end of line characters when pulling files that originated in Linux or Mac into Windows. Git tried auto-converting the end of line characters, which then made Docker’s linux unhappy when running the containers. Run a simple git config setting to fix it:

git config --global core.autocrlf input

If you are working with the files in the linux subsystem for windows, this will not be necessary.

If you have ever had WWWPS or IIS installed or enabled:

The service WorldWideWebPublishingService by default listens on port 80. This is a problem because specify also uses port 80 to run its website. The WWWPS can not be disabled, as it is responsible for hosting websites run by the machine.
Instead, its port must be changed. The Windows application/feature Internet Information Services Manager (IIS) can be used to change the port of WWWPS. (You have to enable the feature first. Use How to enable IIS (Internet Information Services) on Windows 11 as a guide).

  • In the Start Menu search bar, type in “iis” and click on “Internet Information Services Manager”.
  • Click on/expand “Sites” in the toolbar on the left under “Connections”
  • Click on “Default Web Site”
  • In the “Actions” toolbar on the left, under “Edit Site” click “Bindings”
  • Click on the binding that has port =>80 and click edit. Reassign the port to an empty one on your system

Linux-Specific instructions

If you are on a Linux (Ubuntu/Debian) host machine, then after cloning the repository (Step 1 of Quick Start), you will need to do the following :

  1. Ensure that the cloned repository is owned by the group with gid 999 (the human-readable name is not important):
$ sudo chown -R "$USER":999 .
$ stat .
  File: .
  Size: 4096      	Blocks: 8          IO Block: 4096   directory
Device: 259,2	Inode: 27787271    Links: 8
Access: (0770/drwxrwx---)  Uid: (<your-username>/<your-uid>)   Gid: (  999/<group-name>)
Access: 2026-06-02 10:31:35.024037120 -0500
Modify: 2026-06-02 10:31:32.734037155 -0500
Change: 2026-06-02 10:31:32.734037155 -0500
 Birth: 2026-05-28 15:37:06.671604246 -0500

Look for the Gid: label. It should show 999 and some name after the slash. Make sure that this name is not known to be important to another user, but other than that it is not important what the name is.

  1. Ensure that other users within group 999 have permission to access specify:
$ sudo chmod -R ug+rw . # alternatively chmod -R 660 .
$ sudo chmod ug+x $(find -type file) # alternatively chmod 770 $(...)

If you use the numeric permission identifiers, you may have to run the second command multiple times, until you stop seeing errors. This is because directories need executable permissions (1, 2, 3).

specifyweb is a good litmus test to see if everything worked correctly:

$ stat specifyweb
  File: specifyweb
  Size: 4096      	Blocks: 8          IO Block: 4096   directory
Device: 259,2	Inode: 30802119    Links: 8
Access: (0770/drwxrwx---)  Uid: (<your-uid>/<your-username>)   Gid: (  999/<group-name>)
Access: 2026-06-02 11:11:31.337999935 -0500
Modify: 2026-06-02 10:48:36.797292944 -0500
Change: 2026-06-02 11:18:07.789993783 -0500
 Birth: 2026-06-02 10:48:36.634030943 -0500

  1. Open docker-compose.yml and check that the webpack container has the group_add line:
  webpack:
    container_name: webpack
    group_add:
      - 999

If it does not, add it. This allows the front-end to access some of the files needed.

  1. Start the application:

    docker compose up --build
    
  2. Open the app in your browser at http://localhost/specify.

  3. Follow the guided setup process to finish initializing Specify 7.

Quick Start

  1. Clone the repository.

    git clone https://github.com/specify/specify7.git
    cd specify7
    
  2. Start the application.

    docker compose up
    
  3. Open the app in your browser at http://localhost/specify.

  4. Follow the guided setup process to finish initializing Specify 7.

That is the default path. No separate demo database download is required.

Optional: Start With Existing Data

If you want to begin with data already loaded, place a seed database file in the seed-database/ directory before running docker compose up.

You can use:

The seed database is upgraded automatically to the latest Specify 7 version during setup, regardless of the version it started from.

Optional: Python Virtual Environment

The app itself runs in Docker, but a Python virtual environment is still useful for helper scripts.

python3 -m venv ve
source ve/bin/activate
pip3 install wheel
pip3 install --upgrade -r requirements.txt

On Windows PowerShell:

.\ve\Scripts\Activate.ps1

Troubleshooting

If setup does not start cleanly, reset the Docker environment and try again:

docker compose down -v --remove-orphans
docker compose up

If you are using a seed database, confirm the file is still in seed-database/ before restarting.