Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 80 additions & 59 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,96 +92,117 @@ fastapi-react-starter/

## Quick Start

### Development
### Using Docker (Recommended)

1. Clone the repository:
```bash
git clone https://github.com/raythurman2386/fastapi-react-starter.git
cd fastapi-react-starter
```

2. Create environment files:

Create `.env` file in the root directory:
```env
# Database Configuration
DB_USER=postgres
DB_PASSWORD=postgres
DB_NAME=fastapi_db
```

3. Start the application with Docker:
```bash
docker compose up --build
```

This will:
- Start PostgreSQL database
- Reset the database (drop and recreate with fresh migrations)
- Start the FastAPI backend at http://localhost:8000
- Start the React frontend at http://localhost:5173

The Swagger docs will be available at http://localhost:8000/docs

### Manual Setup (Alternative)

1. Backend Setup:

First, create a `.env` file in the backend directory:
a. Install PostgreSQL and create a database:
```bash
# macOS with Homebrew
brew install postgresql
brew services start postgresql

# Create database
createdb fastapi_db
```

b. Create a `.env` file in the backend directory:
```env
# Database Configuration (PostgreSQL)
DB_NAME=your_db_name
DB_USER=your_db_user
DB_PASSWORD=your_password
# Database Configuration
DB_NAME=fastapi_db
DB_USER=postgres # your database user
DB_PASSWORD=postgres # your database password
DB_HOST=localhost
DB_PORT=5432

# JWT Configuration
JWT_SECRET_KEY=your-secret-key-for-production
CORS_ORIGINS=["http://localhost:5173"]
ENVIRONMENT=development
```

If you don't set database credentials, it will fall back to SQLite.

Then set up the Python environment:
c. Install Python dependencies and run migrations:
```bash
cd backend
python -m venv venv
# On Windows:
.\venv\Scripts\activate
# On Unix:
source venv/bin/activate

pip install -r requirements.txt
python manage.py reset_db # This will reset the database and apply migrations
uvicorn app.main:app --reload
```

The backend will be available at http://localhost:8000
- API documentation: http://localhost:8000/docs
- Alternative docs: http://localhost:8000/redoc

2. Frontend Setup:
```bash
cd frontend
npm install
npm run dev
```

The frontend will be available at http://localhost:5173
### Database Management

### Authentication System
The project includes several database management commands:

The template includes a complete JWT-based authentication system with the following features:

- User registration with email and username
- Email-based login
- JWT token generation and validation
- Role-based access control (user, admin, moderator)
- Password reset functionality
- Email verification support (ready to implement)

### Database Support
```bash
# Reset the database (drop, recreate, and apply migrations)
python manage.py reset_db

The template supports both SQLite and PostgreSQL:
# Generate new migrations
python manage.py makemigrations "description of changes"

1. **SQLite** (Default):
- No configuration needed
- Great for development and small projects
- Database file: `app.db` in the backend directory
# Apply pending migrations
python manage.py migrate

2. **PostgreSQL**:
- Production-ready, scalable database
- Async support with asyncpg
- Connection pooling and proper cleanup
- Configure through environment variables
# Check migration status
python manage.py db_status

To use PostgreSQL, set the database environment variables in `.env` and ensure PostgreSQL is running.
# Rollback last migration
python manage.py downgrade
```

### Frontend Components
If you encounter database errors:
1. Stop all running services
2. Reset the database using `python manage.py reset_db` or through Docker with `docker compose up --build`
3. The database will be recreated with fresh tables

The template uses shadcn/ui, a collection of beautifully designed, accessible components:
### Troubleshooting

- Fully styled with Tailwind CSS
- Dark mode support
- TypeScript integration
- Customizable themes
- Accessible by default
- Easy to extend and modify
1. Backend Status shows "error":
- Ensure PostgreSQL is running
- Check database credentials in `.env`
- Try resetting the database using `python manage.py reset_db`
- Check backend logs for specific error messages

To add new shadcn/ui components:
```bash
cd frontend
npx shadcn-ui@latest add button
# Replace 'button' with any component name
```
2. User Registration fails:
- Ensure the database is properly initialized
- Check if backend is running and accessible
- Verify CORS settings in backend `.env`
- Check browser console for specific error messages

## Contributing

Expand Down
39 changes: 24 additions & 15 deletions backend/alembic/env.py
Original file line number Diff line number Diff line change
@@ -1,49 +1,58 @@
import asyncio
from alembic import context
from logging.config import fileConfig
from sqlalchemy.ext.asyncio import AsyncEngine
from app.db import Base, engine, get_database_url, create_engine_with_retry

from app.db import Base, get_database_url, create_engine_with_retry

# Load Alembic configuration and set up logging
config = context.config
fileConfig(config.config_file_name)

# Set the target metadata from your SQLAlchemy models
target_metadata = Base.metadata


async def run_migrations_online():
"""Run migrations in 'online' mode with async support."""
def run_migrations_online():
"""
Run migrations in 'online' mode with async support.
This is a synchronous wrapper that runs async code internally.
"""
connectable = create_engine_with_retry(get_database_url())

async with connectable.connect() as connection:
await connection.run_sync(do_run_migrations)
# Define an async helper function to handle the connection and migration
async def do_run_migrations_async():
async with connectable.connect() as connection:
await connection.run_sync(do_run_migrations)

# Run the async function synchronously using asyncio.run
asyncio.run(do_run_migrations_async())


def do_run_migrations(connection):
"""
Configure and run migrations synchronously on the provided connection.
"""
context.configure(connection=connection, target_metadata=target_metadata)
with context.begin_transaction():
context.run_migrations()


asyncio.run(run_migrations_online())


def run_migrations_offline() -> None:
"""Run migrations in 'offline' mode."""

def run_migrations_offline():
"""
Run migrations in 'offline' mode.
Generates SQL scripts without connecting to the database.
"""
url = get_database_url()

context.configure(
url=url,
target_metadata=target_metadata,
literal_binds=True,
dialect_opts={"paramstyle": "named"},
)

with context.begin_transaction():
context.run_migrations()


# Determine whether to run migrations in offline or online mode
if context.is_offline_mode():
run_migrations_offline()
else:
Expand Down
15 changes: 14 additions & 1 deletion backend/manage.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import typer
import subprocess
import os
from sqlalchemy import create_engine
from app.config import get_settings
from app.db import engine, Base

app = typer.Typer()
settings = get_settings()


@app.command()
def run():
"""Run the FastAPI application."""
typer.echo("Starting FastAPI app...")
subprocess.run(["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"])
subprocess.run(["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"])


@app.command()
Expand Down Expand Up @@ -47,5 +51,14 @@ def format():
subprocess.run(["black", "."])


@app.command()
def reset_db():
"""Drop and recreate all database tables using Alembic"""
typer.echo("Resetting database using Alembic...")
subprocess.run(["alembic", "downgrade", "base"])
subprocess.run(["alembic", "upgrade", "head"])
typer.echo("Database reset successfully.")


if __name__ == "__main__":
app()
Binary file modified backend/requirements.txt
Binary file not shown.
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ services:
timeout: 5s
retries: 5
start_period: 10s
command: bash -c "sleep 5 && uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload"
command: bash -c "python manage.py run"

frontend:
build:
Expand Down