{"id":44290158,"url":"https://github.com/codefordenver/partner-finder","last_synced_at":"2026-02-10T23:33:14.560Z","repository":{"id":45185216,"uuid":"368370432","full_name":"codefordenver/partner-finder","owner":"codefordenver","description":"Using an open dataset with registered colorado business to build a tool that manages outreach to potential CFD partners.","archived":false,"fork":false,"pushed_at":"2022-01-11T23:26:44.000Z","size":2785,"stargazers_count":3,"open_issues_count":24,"forks_count":14,"subscribers_count":17,"default_branch":"main","last_synced_at":"2025-06-08T22:46:16.536Z","etag":null,"topics":["civic-tech","flask","python","react","rest-api"],"latest_commit_sha":null,"homepage":"","language":"Jupyter Notebook","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/codefordenver.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-05-18T01:49:41.000Z","updated_at":"2022-10-05T01:53:52.000Z","dependencies_parsed_at":"2022-09-10T11:50:14.894Z","dependency_job_id":null,"html_url":"https://github.com/codefordenver/partner-finder","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/codefordenver/partner-finder","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codefordenver%2Fpartner-finder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codefordenver%2Fpartner-finder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codefordenver%2Fpartner-finder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codefordenver%2Fpartner-finder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/codefordenver","download_url":"https://codeload.github.com/codefordenver/partner-finder/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codefordenver%2Fpartner-finder/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29321397,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-10T20:44:44.282Z","status":"ssl_error","status_checked_at":"2026-02-10T20:44:43.393Z","response_time":65,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["civic-tech","flask","python","react","rest-api"],"created_at":"2026-02-10T23:33:14.416Z","updated_at":"2026-02-10T23:33:14.540Z","avatar_url":"https://github.com/codefordenver.png","language":"Jupyter Notebook","funding_links":[],"categories":[],"sub_categories":[],"readme":"A micro-CRM to help Code For Denver discover leads and manage its outreach to nonprofits.\n\n![](./docs/app-screen-shot.png)\n# Table of Contents\n\n[Getting Started](#getting-started)\n- [Get the Code](#get-the-code)\n- [Running the app locally](#running-the-app-locally)\n    - [Using Docker Compose](#using-docker-compose)\n    - [Running Frontend Only](#running-frontend-only)\n\n[Development](#development)\n- [Frontent](#frontend)\n    - [Accessing Api Docs](#accessing-api-docs)\n        - [With Docker Compose](#with-docker-compose)\n        - [Without Docker Compose](#without-docker-compose)\n    - [Linting and Formatting](#linting-and-formatting)\n- [Backend](#backend)\n    - [Linting and Formatting Scripts](#linting-and-formatting-scripts)\n    - [Creating Database Migration Files](#creating-database-migration-files)\n    - [Connecting to the AWS Postgres instance](#connecting-to-the-aws-postgres-instance)\n    - [Postman Collection](#postman-collection)\n- [Running a data analysis jupyter notebook](#running-a-data-analysis-jupyter-notebook)\n\n[Deployments](#deployments)\n- [Deploying The API](#deploying-the-api)\n- [Deploying The Frontend](#deploying-the-frontend)\n\n[Data Sources For Leads](#data-sources-for-leads)\n\n[Community](#community)\n\n# Getting Started\n\n\n## Get the Code\n1. Go to the project's [github page](https://github.com/codefordenver/partner-finder).\n1. Find the green \"Code\" button\n1. Click the clipboard icon to copy a link to the git repo.\n    ![](./docs/github-code-button.png)\n1. In a terminal, navigate to the directory where you want to create the project folder and clone the repo:\n    ```bash\n    git clone \u003cgit-repo-name\u003e\n    ```\n## Running the app locally\n\nThere are two methods for setting up your local machine for development. If you are planning on working on the backend, or want to use docker compose to work on the frontend, follow [Using Docker Compose](#using-docker-compose). If you want to just work on the frontend, and do not want to use docker compose, follow [Running Frontend Only](#running-frontend-only).\n\n### Using Docker Compose\n1. Install Docker and Docker-compose.\n1. Run the database, api, and frontend in docker containers using compose.\n    ```bash\n    docker-compose up --build -d\n    ```\n1. Check the containers are running\n    ```bash\n    docker ps\n    ```\n    - you should see something like\n        ![](./docs/docker-ps-output.png)\n1. Try connecting to the database with psql:\n    ```bash\n    docker exec -it partner-finder_postgres_1 psql -U cfd_partner_finder\n    select * from leads limit 5;\n    ```\n    to exit psql, type `\\q`\n1. Check that the api works with curl:\n    - try the healthcheck endpoint: `curl http://localhost:8000/healthcheck`\n    - get an access token to use other api endpoints:\n        ```bash\n        curl --location --request POST 'http://localhost:8000/login' \\\n        --header 'Content-Type: application/json' \\\n        --data-raw '{\n            \"username\": \"user@gmail.com\",\n            \"password\": \"password\"\n        }'\n        ```\n    - get a list of leads:\n        ```bash\n        curl --location --request GET 'http://localhost:8000/leads' \\\n        --header 'Authorization: Bearer \u003cinsert your token here\u003e'\n1. Check that the react app is running:\n    - in a browser, go to http://localhost:1234\n1. You should see a login page. Use the following credentials for development:\n    - username: `user@gmail.com`\n    - password: `password`\n\n\n### Running Frontend Only\n\nIf you only plan to work on the frontend and do not want to use docker compose, we also have the backend running on a development server. In this case, you will need to have @galbwe set up a user account for you to log in with. Follow these steps to get up and running:\n\n1. Email galbwe92@gmail.com requesting credentials for the development server.\n1. Once your credentials are set up, `cd` to the `frontend` directory.\n1. Install dependencies by running `yarn`\n1. Start the app with `yarn dev`\n\nYou should see a login screen where you can test your credentials.\n\n\n\n# Development\n## Frontend\n### Accessing Api Docs\n#### With Docker Compose\nThe backend generates swagger documentation. This is a webpage that lets you make interactive api calls to test out the rest api before using it in your code. To run the swagger docs locally, make sure the `api` docker service is running. Check the api logs for a bearer token that you can use to authenticate on the swagger page. If you ran docker compose with the `-d` flag, you can get the logs with `docker compose logs api`.\n\nNow look for bearer tokens that let you authenticate as a normal user and as an admin:\n```\napi_1       | [2021-08-11 01:05:47 +0000] [19] [INFO] To authenticate as user@gmail.com, include this header with the request:\napi_1       |   Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXJAZ21haWwuY29tIiwiZXhwaXJlcyI6IjIwMjEtMDgtMTJUMDE6MDU6NDcuNTM0NDgzKzAwOjAwIiwiYWRtaW4iOmZhbHNlfQ.41xKVHDz0ONRiWx-fWqifVvDBSzCN6vPmmf4ZWV0H3g\napi_1       | [2021-08-11 01:05:47 +0000] [19] [INFO] To authenticate as admin@gmail.com, include this header with the request:\napi_1       |   Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluQGdtYWlsLmNvbSIsImV4cGlyZXMiOiIyMDIxLTA4LTEyVDAxOjA1OjQ3LjU2NTExNCswMDowMCIsImFkbWluIjp0cnVlfQ.NNUMN92roOU44DKXcnstBUK_vpRfg57RYJyBMCuSdmQ\n```\n\nCopy only the value of the header, that is, the part that looks like\n\n```\nBearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXJAZ21haWwuY29tIiwiZXhwaXJlcyI6IjIwMjEtMDgtMTJUMDE6MDU6NDcuNTM0NDgzKzAwOjAwIiwiYWRtaW4iOmZhbHNlfQ.41xKVHDz0ONRiWx-fWqifVvDBSzCN6vPmmf4ZWV0H3g\n```\n\nNow in a web browser, navigate to http://localhost:8000/apidocs . You should see a page that looks like this:\n\n![](./docs/swagger-page.png)\n\nClick on the green \"Authorize\" button with the lock icon, paste the bearer token you copied into the login form, and click \"Authorize\".\n\n![](./docs/swagger-login.png)\n\nTo send a request to any of the endpoints, click on one of the colored boxes, then click \"Try it out\" in the upper right corner. This lets you edit the request parameters and body through a form. You can send the request and view the response with the \"Execute\" button.\n\n![](./docs/swagger-try-it.png)\n\n#### Without Docker Compose\nTo access the api documentation page without docker compose, go to https://cfd-partner-finder-api.xyz/apidocs/ . This will allow you to view the available api endpoints. By clicking on one of the endpoints, you should also be able to view the request parameters and the shape of the api response.\n\nIn order to use the swagger docs interactively, you will need a set of login credentials for the development server. See [Running Frontend Only](running-frontend-only).\n\nOnce you have credentials, you will need to get your bearer token. One way to do this is to run the frontend in development mode on `localhost:1234` by running `yarn dev` in the `frontend` directory. Once you have done this and successfully submitted the login form, open developer tools in your browser (command + option + J on macOS, or right click and select \"inspect\")\n\nOnce dev tools are open, go to the \"Application\" tab:\n\n![](./docs/dev-tools-application.png)\n\nIn the side panel, under \"Local Storage\", select `http://localhost:1234`. You should see a key called `partnerFinderToken` in the right pane, along with a bearer token.\n\n![](./docs/dev-tools-local-storage.png)\n\nNow in the docs page, click the green \"Authorize\" button near the top right corner. You will be prompted to enter an Authorization header. Enter `Bearer \u003cyour token\u003e` and submit the form.\n\n![](./docs/swagger-page.png)\n\n![](./docs/swagger-login.png)\n\nYou should now be able to send api requests to the backend by clicking the \"Try it out\" button and entering request parameters.\n\n![](./docs/swagger-try-it.png)\n\n### Linting and Formatting\n\nWe use `prettier` to consistly format our javascript and `eslint` as a linter. To run them, make sure you are in the frontend directory, then run\n- `yarn format` to run `prettier`, and\n- `yarn lint` to run `eslint`\n you'll need to commit your formatting changes. It's fine to put them in their own commit, or if you want to include them in a recent commit that has not been pushed to the remote yet, you can use `git commit --amend`.\n\n## Backend\n### Linting and Formatting Scripts\nWe have github actions that will check that backend code is in the correct format and abides by PEP8 standards. You will need to run a formatter and a linter on your code before committing in order for your changes to be accepted. In the `backend/scripts`, directory, there are scripts called `lint.sh` and `format.sh` for doing this. You can run them directly from the `backend` directory:\n\n```\ncd backend\nsource venv/bin/activate\nchmod +x scripts/*.sh\n./scripts/format.sh\n./scripts/lint.sh\n```\n\nAfter running `lint.sh`, you should see an output of `0` if everything is okay. Otherwise flake8 will output lines that need to be changed.\n\n\nOnce you've made formatting and linting changes, make a commit with a message like `lint and format` and add it to your PR. It is helpful to PR reviewers if you keep your formatting changes in their own commit because they can potentially make it harder to read your other code changes.\n\n### Creating Database Migration Files\nYou'll need a python virtual environment in the `backend` directory. Make sure you have python 3.7 or up installed. Ideally 3.9 since that is what is used in the rest api. You can check the version with `python --version`\n\nChange into the backend directory then do `python -m venv venv`. This should create a `venv` directory.\n\nNext you'll want to activate the virtual environment with `source venv/bin/activate`.\n\nThen install requirements with `pip install -r requirements.txt`\n\nYou should also need to set some environment variables so alembic can send queries to the locally running database. Create a `.env` file with `touch .env`, then add these lines to it:\n\n```\nexport FLASK_APP=api/app:app\nexport FLASK_ENV=development\nexport POSTGRES_PASSWORD=password\nexport POSTGRES_USER=cfd_partner_finder\nexport POSTGRES_DB=cfd_partner_finder\nexport POSTGRES_HOST=localhost\nexport POSTGRES_PORT=5432\nexport SECRET_KEY=supersafe\nexport PYTHONPATH=\"${pwd}\"\n```\n\nNow source the environment variables: `source .env`\n\nFinally, you can create a new migration by doing `alembic revision -m \"\u003cdescription of migration\u003e\"`. This should create a new file under the `versions` directory.\n\n### Connecting to the AWS Postgres instance\nWe run a postgres instance in AWS RDS. A simple method for connecting to the instance is with the psql command line tool. There is a script called `backend/database/psql.sh` that will run `psql` for you with arguments taken from environment variables. We will read these environment variables from a file called `.env-prod`. Please use this exact filename because it is already in `.gitignore`. Follow these steps to get into a psql session:\n\n1. create a file called `backend/.env-prod` if it does not already exist\n1. the contents of `backend/.env-prod` should look like this:\n    ```\n    export POSTGRES_PASSWORD=\u003cinsert password here\u003e\n    export POSGRES_DB=\u003cinsert db here\u003e\n    export POSTGRES_USER=\u003cinsert user here\u003e\n    export POSTGRES_HOST=\u003cinsert host here\u003e\n    ```\n1. contact a project maintainer (galbwe) for the values of the environment variables above\n1. source the environment variables to make them accessible in your terminal: `source backend/.env-prod`\n1. Run the database connection script: `./backend/database/psql.sh`\n1. You will be prompted for a password. It is the same as the `POSTGRES_PASSWORD` environment variable.\n1. The prompt should change to show psql. You can now run some sql commands to check that the connection worked:\n```sql\n\\dt  -- list tables\nSELECT count(*) FROM leads;\nSELECT * FROM leads LIMIT 5;\n```\n### Postman Collection\nPostman is a web client for testing out REST apis. See here to view and export [postman requests]() for this project. You will also need to install postman, import the collection, and then run the api on localhost to use postman in development.\n\n## Running a data analysis jupyter notebook\n1. Make sure python 3 is installed on your system\n1. from the project root directory, change to the data analysis directory\n    - `cd ./data_analysis`\n1. Create a virtual environment\n    ```python\n    python3 -m venv --prompt data_analysis venv\n    ```\n    - You should see a newly created folder called `venv`\n1. Activate the virtual environment\n    ```bash\n    source venv/bin/activate\n    ```\n    - Your terminal prompt should change to display `(data_analysis)` on the left while the virtual environment is active.\n1. Upgrade the virtual environment's installation of pip\n    - `pip install --upgrade pip`\n1. Install dependencies\n    - `pip install -r requirements.txt`\n1. Run a jupyter server:\n    ```\n    jupyter notebook\n    ```\n1. You should see a file system open in a web browser. If not, go to http://localhost:8888/tree\n    ![](./docs/jupyter-notebook.png)\n1. Click on `notebooks`, and then `businesses.ipynb`. You should now see a notebook\n    ![](./docs/jpyter-notebook-2.png)\n1. When you are done, stop the jupyter server with `Ctrl+C` and deactivate the virtual environment with `deactivate`.\n\n\n# Deployments\n\n## Deploying The API\n\nThis is the current manual process for building and deploying the rest api:\n\n1. Set the `AWS_PROFILE` environment variable\n2. Update the version number in `backend/scripts/build.sh`\n3. Run `build.sh` to build a docker image and push it to dockerhub\n4. Open a PR to update the version number in the github repo\n5. Use the `backend/scripts/ssh-server` script to start an ssh session in an ec2 instance\n6. update the version number in `partner-finder/start.sh`\n7. Pull the docker image from dockerhub\n8. stop and remove the running container with `sudo docker container stop \u003ccontainer name\u003e` and `sudo docker container rm \u003ccontainer name\u003e` you can get the container name by running `sudo docker ps`\n9. start a new container with the updated api with `sudo ./start.sh`\n\n\n## Deploying The Frontend\n\nThis is the current manual process for building and deploying the frontend:\n\n1. Create a `.env` file in the `frontend` directory. Make sure it has the following contents\n    ```\n    API_HOST='http://cfd-partner-finder-api.xyz:8888'\n    ```\n1. Update the version number in `frontend/scripts/build.sh`\n1. Run `./scripts/build.sh` to build a docker image and push it to dockerhub\n1. Use the `backend/scripts/ssh-server` script to start an ssh session in the ec2 instance\n1. Update the version number in `partner-finder/frontend.sh`\n1. Pull the docker image from dockerhub\n1. stop and remove the running container with `sudo docker container stop \u003ccontainer name\u003e` and `sudo docker container rm \u003ccontainer name\u003e` you can get the container name by running `sudo docker ps`\n1. start a new container with the updated frontend with `sudo ./frontend.sh`\n\n# Data Sources For Leads\n- [Socrata API](https://data.colorado.gov/Business/Business-Entities-in-Colorado/4ykn-tg5h)\n    - Dataset with registered business entities in Colorado. It can be filtered to return only nonprofits.\n- [Colorado Nonprofit Association](https://coloradononprofits.org/membership/nonprofit-member-directory)\n    - Website with nonprofit members registered with Colorado Nonprofit Association.\n- Twitter?\n- LinkedIn?\n\n# Community\n\nThis is a Code For Denver project. For more about the organization, see https://codefordenver.org/\n\nCode for Denver has a [discord server](https://discord.com/invite/aKVgZSN) and runs online [meetups](https://www.meetup.com/CodeForDenver) roughly every two weeks. This project has a channel called `#partner-finder` on the discord server. The project also has a weekly standup at 6pm MT. Typically a link to a google hangout is shared in the discord channel. If you would like to join, but do not have access to the channel, please email galbwe92@gmail.com expressing your interest to participate.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodefordenver%2Fpartner-finder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcodefordenver%2Fpartner-finder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodefordenver%2Fpartner-finder/lists"}