{"id":15187158,"url":"https://github.com/buuntu/fastapi-react","last_synced_at":"2025-05-15T07:04:36.195Z","repository":{"id":37263953,"uuid":"249049296","full_name":"Buuntu/fastapi-react","owner":"Buuntu","description":"🚀   Cookiecutter Template for FastAPI + React Projects.  Using PostgreSQL, SQLAlchemy, and Docker","archived":false,"fork":false,"pushed_at":"2023-10-06T23:46:17.000Z","size":4396,"stargazers_count":2360,"open_issues_count":43,"forks_count":364,"subscribers_count":45,"default_branch":"master","last_synced_at":"2025-05-15T07:04:22.537Z","etag":null,"topics":["boilerplate","cookiecutter","docker","fastapi","full-stack","jwt","nginx","oauth2","postgres","react","react-admin","sqlalchemy","typescript"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Buuntu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2020-03-21T19:48:47.000Z","updated_at":"2025-05-13T14:09:29.000Z","dependencies_parsed_at":"2024-01-03T02:30:06.309Z","dependency_job_id":"9c8629a7-e2c2-49f9-abdf-14860498615e","html_url":"https://github.com/Buuntu/fastapi-react","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Buuntu%2Ffastapi-react","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Buuntu%2Ffastapi-react/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Buuntu%2Ffastapi-react/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Buuntu%2Ffastapi-react/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Buuntu","download_url":"https://codeload.github.com/Buuntu/fastapi-react/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254292039,"owners_count":22046426,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["boilerplate","cookiecutter","docker","fastapi","full-stack","jwt","nginx","oauth2","postgres","react","react-admin","sqlalchemy","typescript"],"created_at":"2024-09-27T18:02:31.084Z","updated_at":"2025-05-15T07:04:31.180Z","avatar_url":"https://github.com/Buuntu.png","language":"Python","readme":"# FastAPI + React · ![build](https://github.com/Buuntu/fastapi-react/workflows/build/badge.svg) [![license](https://img.shields.io/github/license/peaceiris/actions-gh-pages.svg)](LICENSE) [![Dependabot Status](https://img.shields.io/badge/Dependabot-active-brightgreen.svg)](https://dependabot.com)\n\n\u003cdiv\u003e\n\u003cimg src=\"assets/fastapi-logo.png\" alt=\"fastapi-logo\" height=\"60\" /\u003e \u003cimg\nsrc=\"assets/react-logo.png\" alt=\"react-logo\" height=\"60\" /\u003e \u0026nbsp; \u0026nbsp; \u003cimg\nsrc=\"assets/react-admin.png\" alt=\"react-admin\" height=\"60\" /\u003e \u0026nbsp; \u0026nbsp; \u003cimg\nsrc=\"assets/typescript.png\" alt=\"react-logo\" height=\"60\" /\u003e \u0026nbsp;\u0026nbsp;\u0026nbsp;\n\u003cimg src=\"assets/postgres.png\" alt=\"react-logo\" height=\"60\" /\u003e \u003cimg\nsrc=\"assets/sql-alchemy.png\" alt=\"sql-alchemy\" height=\"60\" /\u003e\n\u003c/div\u003e\n\nA cookiecutter template for bootstrapping a FastAPI and React project using a\nmodern stack.\n\n---\n\n## Features\n\n- **[FastAPI](https://fastapi.tiangolo.com/)** (Python 3.8)\n  - JWT authentication using [OAuth2 \"password\n    flow\"](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/) and\n    PyJWT\n- **[React](https://reactjs.org/)** (with Typescript)\n  - [react-router v5](https://reacttraining.com/react-router/) to handle routing\n  - [Utility functions](#Frontend-Utilities) and [higher-order\n    components](#Higher-Order-Components) for handling authentication\n- **[PostgreSQL](https://www.postgresql.org/)** for the database\n- **[SqlAlchemy](https://www.sqlalchemy.org/)** for ORM\n- **[Celery](http://www.celeryproject.org/)** for [background\n  tasks](#background-tasks) and [Redis](https://redis.io/) as a message broker\n  - Includes [Flower](https://flower.readthedocs.io/en/latest/) for task\n    monitoring\n- **[Alembic](https://alembic.sqlalchemy.org/en/latest/)** for database\n  migrations\n- **[Pytest](https://docs.pytest.org/en/latest/)** for backend tests\n  - Includes test database, transaction rollbacks after each test, and reusable\n    [Pytest fixtures](#fixtures).\n- **[Prettier](https://prettier.io/)**/**[ESLint](https://eslint.org/)** (Airbnb\n  style guide)\n- **[Docker Compose](https://docs.docker.com/compose/)** for development\n- **[Nginx](https://www.nginx.com/)** as a reverse proxy to allow\n  backend/frontend on the same port\n- **[MaterialUI](https://material-ui.com/)** using recommended\n  [CSS-in-JS](https://material-ui.com/styles/basics/) styling.\n- **[react-admin](https://github.com/marmelab/react-admin)** for the admin\n  dashboard\n  - Using the same token based authentication as FastAPI backend (JWT)\n\n## Table of Contents\n\n- [Background](#background)\n- [Quick Start](#quick-start)\n- [Develop](#develop)\n- [Admin Dashboard](#admin-dashboard)\n- [Security](#security)\n- [Testing](#testing)\n  - [Fixtures](#fixtures)\n    - [test_db](#test_db)\n    - [test_user](#test_user)\n    - [test_superuser](#test_superuser)\n    - [client](#client)\n    - [user_token_headers](#user_token_headers)\n    - [superuser_token_headers](#superuser_token_headers)\n- [Background Tasks](#background-tasks)\n  - [Flower](#flower)\n- [Frontend Utilities](#frontend-utilities)\n  - [Utility Functions](#utility-functions)\n    - [login](#login)\n    - [logout](#logout)\n    - [isAuthenticated](#isauthenticated)\n  - [Routes](#routes)\n  - [Higher Order Components](#higher-order-components)\n    - [PrivateRoute](#privateroute)\n- [Deployment](#deployment)\n- [Contributing](#contributing)\n\n## Background\n\nIt is often laborsome to start a new project. 90% of the time you have to decide\nhow to handle authentication, reverse proxies, docker containers, testing,\nserver-side validation, linting, etc. before you can even get started.\n\n**FastAPI-React** serves to streamline and give you that functionality out of\nthe box.\n\nIt is meant as a lightweight/React alternative to [FastAPI's official fullstack\nproject](https://github.com/tiangolo/full-stack-fastapi-postgresql). If you want\na more comprehensive project in Vue, I would suggest you start there. A lot of\nthe backend code is taken from that project or the [FastAPI official\ndocs](https://fastapi.tiangolo.com/).\n\n## Quick Start\n\nFirst, install cookiecutter if you don't already have it:\n\n```bash\npip3 install cookiecutter\n```\n\nSecond, install docker-compose if you don't already have it:\n\n[docker-compose installation official\ndocs](https://docs.docker.com/compose/install/).\n\nThen, in the directory you want your project to live:\n\n```bash\ncookiecutter gh:Buuntu/fastapi-react\n```\n\nYou will need to put in a few variables and it will create a project directory\n(called whatever you set for `project_slug`).\n\n\u003cdetails\u003e\u003csummary\u003eInput Variables\u003c/summary\u003e\n\n- project_name [default fastapi-react-project]\n- project_slug [default fastapi-react-project] - this is your project directory\n- port [default 8000]\n- postgres_user [default postgres]\n- postgres_password [default password]\n- postgres_database [default app]\n- superuser_email [default admin@fastapi-react-project.com]\n- superuser_password [default password]\n- secret_key [default super_secret]\n\n\u003c/details\u003e\n\n## Develop\n\nChange into your project directory and run:\n\n```bash\nchmod +x scripts/build.sh\n./scripts/build.sh\n```\n\nThis will build and run the docker containers, run the alembic migrations, and\nload the initial data (a test user).\n\nIt may take a while to build the first time it's run since it needs to fetch all\nthe docker images.\n\nOnce you've built the images once, you can simply use regular `docker-compose`\ncommands to manage your development environment, for example to start your\ncontainers:\n\n```bash\ndocker-compose up -d\n```\n\nOnce this finishes you can navigate to the port set during setup (default is\n`localhost:8000`), you should see the slightly modified create-react-app page:\n\n![default create-react-app](assets/create-react-app.png)\n\n_Note: If you see an Nginx error at first with a `502: Bad Gateway` page, you\nmay have to wait for webpack to build the development server (the nginx\ncontainer builds much more quickly)._\n\nLogin screen: ![regular login](assets/regular-login.png)\n\nThe backend docs will be at `http://localhost:8000/api/docs`. ![API\nDocs](assets/api-docs.png)\n\n## Admin Dashboard\n\nThis project uses [react-admin](https://marmelab.com/react-admin/) for a highly\nconfigurable admin dashboard.\n\nAfter starting the project, navigate to `http://localhost:8000/admin`. You\nshould see a login screen. Use the username/password you set for the superuser\non project setup.\n\n_NOTE: regular users will not be able to access the admin dashboard_\n\n![React Adming Login](assets/login-screen.png)\n\nYou should now see a list of users which you can edit, add, and delete. The\ntable is configured with the REST endpoints to the FastAPI `/users` routes in\nthe backend.\n\n![React Admin Dashboard](assets/admin-dashboard.png)\n\nThe admin dashboard is kept in the `frontend/src/admin` directory to keep it\nseparate from the regular frontend.\n\n## Security\n\nTo generate a secure key used for encrypting/decrypting the JSON Web Tokens, you\ncan run this command:\n\n```bash\nopenssl rand -hex 32\n```\n\nThe default is fine for development but you will want something more secure for\nproduction.\n\nYou can either set this on project setup as `secret_key` or manually edit the\nPython `SECRET_KEY` variable in `backend/app/core/security.py`.\n\n## Testing\n\nThis project comes with Pytest and a few Pytest fixtures for easier mocking. The\nfixtures are all located in `backend/conftest.py` within your project directory.\n\nAll tests are configured to run on a test database using [SQLAlchemy\ntransactions](https://docs.sqlalchemy.org/en/13/orm/session_transaction.html) to\nreset the testing state on each function. This is to avoid a database call\naffecting the state of a different test.\n\n### Fixtures\n\nThese fixtures are included in `backend/conftest.py` and are automatically\nimported into any test files that being with `test_`.\n\n#### test_db\n\nThe `test_db` fixture is an empty test database and an instance of a SQLAlchemy\nSession class.\n\n```python\ndef test_user(test_db):\n    assert test_db.query(models.User).all()\n```\n\n#### test_user\n\n```python\ndef test_user_exists(test_user):\n    assert test_user.email == \"admin@example.com\"\n```\n\n#### test_superuser\n\n```python\ndef test_superuser(client, test_superuser):\n    assert test_superuser.is_superuser\n```\n\n#### client\n\nTo use an unauthenticated test client, use `client`:\n\n```python\ndef test_get_users(client):\n    client.get(\"/api/v1/users\")\n    assert response.status_code == 200\n```\n\n#### user_token_headers\n\nIf you need an authenticated client using OAuth2 and JWTs:\n\n```python\ndef test_user_me(client, user_token_headers):\n    response = client.get(\n      \"/api/v1/users/me\",\n      headers=user_token_headers,\n    )\n    assert response.status_code == 200\n```\n\nSince OAuth2 expects the access token in the headers, you will need to pass in\n`user_token_headers` as the `headers` argument in any client request that\nrequires authentication.\n\n#### superuser_token_headers\n\n```python\ndef test_user_me(client, superuser_token_headers):\n    response = client.get(\n      \"/api/v1/users\",\n      headers=superuser_token_headers,\n    )\n    assert response.status_code == 200\n```\n\n## Background Tasks\n\nThis template comes with Celery and Redis Docker containers pre-configured for\nyou. For any long running processes, it's recommended that you handle these\nusing a task queue like Celery to avoid making the client wait for a request to\nfinish. Some examples of this might be sending emails, uploading large files, or\nany long running, resource intensive tasks.\n\nThere is an example task in `backend/app/tasks.py` and an example Celery test in\n`backend/app/tests/test_tasks.py`. This test runs synchronously, which is what\nCelery docs recommend.\n\nIf you are not happy with Celery or Redis, it should be easy to swap these\ncontainers out with your favorite tools. Some suggested alternatives might be\n[Huey](https://github.com/coleifer/huey) as the task queue and\n[RabbitMQ](https://www.rabbitmq.com/) for the message broker.\n\n### Flower\n\nYou can monitor tasks using Flower by going to http://localhost:5555\n\n## Frontend Utilities\n\nThere are a few helper methods to handle authentication in `frontend/src/utils`.\nThese store and access the JWT returned by FastAPI in local storage. Even though\nthis doesn't add any security, we prevent loading routes that might be protected\non the frontend, which results in a better UX experience.\n\n### Utility Functions\n\n#### login\n\n```typescript\n// in src/utils/auth.ts\n\n/**\n *  Handles authentication with backend and stores in JWT in local storage\n **/\nconst login = (email: string, password: string) =\u003e boolean;\n```\n\n#### logout\n\n```typescript\n// in src/utils/auth.ts\n\n// clears token from local storage\nconst logout = (email: string, password: string) =\u003e void;\n```\n\n#### isAuthenticated\n\n```typescript\n// Checks authenticated state from JWT tokens\nconst isAuthenticated = () =\u003e boolean;\n```\n\n### Routes\n\nSome basic routes are included (and handled in `frontend/Routes.tsx`).\n\n- `/login` - Login screen\n- `/logout` - Logout\n- `/` - Home\n- `/protected` - Example of protected route\n\n### Higher Order Components\n\n#### PrivateRoute\n\nThis handles routes that require authentication. It will automatically check\nwhether the correct token with the \"user\" permissions is present or redirect to\nthe home page.\n\n```JSX\n// in src/Routes.tsx\nimport { Switch } from 'react-router-dom';\n\n// Replace this with your component\nimport { ProtectedComponent } from 'components';\n\nconst Routes = () =\u003e (\n  \u003cSwitch\u003e\n    \u003cPrivateRoute path=\"/protected_route\" component={ProtectedComponent} /\u003e\n  \u003c/Switch\u003e\n);\n```\n\n\u003c/details\u003e\n\n## Deployment\n\nThis stack can be adjusted and used with several deployment options that are\ncompatible with Docker Compose, but it may be easiest to use Docker in Swarm\nMode with an Nginx main load balancer proxy handling automatic HTTPS\ncertificates, using the ideas from DockerSwarm.rocks.\n\nPlease refer to DockerSwarm.rocks to see how to deploy such a cluster easily.\nYou will have to change the Traefik examples to Nginx or update your\ndocker-compose file.\n\n## Contributing\n\nContributing is more than welcome. Please read the [Contributing\ndoc](CONTRIBUTING.md) to find out more.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbuuntu%2Ffastapi-react","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbuuntu%2Ffastapi-react","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbuuntu%2Ffastapi-react/lists"}