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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
111 changes: 104 additions & 7 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
# AngelaMos | 2025
# dev.compose.yml
# =============================================================================
# AngelaMos | 2026
# .gitignore
# =============================================================================

venv
*.venv
*.env
*.cache
*.egg
# =============================================================================
# Environment files (keep .example files)
# =============================================================================
.env
.env.local
.env.development
.env.production
.env.*.local
!.env.example

# =============================================================================
# Python
# =============================================================================
__pycache__/
*.py[cod]
*$py.class
Expand All @@ -26,14 +35,102 @@ wheels/
*.egg-info/
.installed.cfg
*.egg
.venv/
venv/
*.venv

# Python tooling
.pytest_cache/
.coverage
htmlcov/
.tox/
.mypy_cache/
.dmypy.json
dmypy.json
.ruff_cache/

# =============================================================================
# Node.js / JavaScript
# =============================================================================
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
.pnpm-store/

# Build outputs
dist/
dist-ssr/
*.local
.vite/

# =============================================================================
# Go
# =============================================================================
bin/
*.exe
*.exe~
*.dll
*.dylib
*.test
coverage.out
coverage.html
tmp/
vendor/
__debug_bin*

# Go keys (sensitive)
keys/*.pem
keys/*.key

# =============================================================================
# iOS / React Native
# =============================================================================
.expo/
web-build/
expo-env.d.ts
.kotlin/
*.orig.*
*.jks
*.p8
*.p12
*.key
*.mobileprovision
.metro-health-check*
*.tsbuildinfo
/ios
/android

# =============================================================================
# IDEs and Editors
# =============================================================================
.idea/
.vscode/*
!.vscode/extensions.json
*.swp
*.swo
*~
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

# =============================================================================
# OS Files
# =============================================================================
.DS_Store
Thumbs.db
*.pem

# =============================================================================
# Docker
# =============================================================================
*.log

# =============================================================================
# Misc
# =============================================================================
*.cache
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

©AngelaMos | 2025 | CarterPerez-dev
©AngelaMos | 2026 | CarterPerez-dev

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
37 changes: 34 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,8 +1,25 @@
===========================================
Fullstack Template: FastAPI + React + Nginx
Fullstack Templates Collection
===========================================

*Production-ready Docker setup with TypeScript and SCSS*
*Production-ready stack templates with TypeScript, SCSS, and modern backends*

Available Templates
===================

**Default Stack: FastAPI + React**
Full-stack web application with Python FastAPI backend and React 19 frontend.
Uses ``compose.yml`` and ``dev.compose.yml``.

**Go-Chi Stack: Go + React**
Full-stack web application with Go Chi backend and React 19 frontend.
Uses ``compose.go.yml`` and ``dev.compose.go.yml``.
Backend located in ``alternate-backends/go-chi/``.

**iOS Mobile: Expo + React Native**
Mobile application using Expo and React Native.
Located in ``mobile/ios-expo/``.
Connects to any backend via API (no Docker required).

----

Expand Down Expand Up @@ -63,10 +80,24 @@ This will:
Next Steps
----------

**For FastAPI + React (Default)**

1. Edit ``.env`` with your configuration
2. Start development: ``just dev-up``
2. Start development: ``just dev-up`` or ``docker compose -f dev.compose.yml up``
3. After creating models: ``just migration-local "initial"`` then ``just migrate-local head``

**For Go-Chi + React**

1. Edit ``.env`` with your configuration
2. Start development: ``docker compose -f dev.compose.go.yml up``
3. Production: ``docker compose -f compose.go.yml up``

**For iOS Expo App**

1. Navigate to ``mobile/ios-expo/``
2. Follow the iOS-specific README for Expo setup
3. Configure API endpoint to connect to your backend

Run ``just`` to see all available commands.

----
Expand Down
File renamed without changes.
86 changes: 86 additions & 0 deletions backends/fastapi/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# =============================================================================
# AngelaMos | 2026
# .env.example
# =============================================================================
# Standalone FastAPI Backend
# Copy to .env for production, .env.development for dev
# Production (*00 ports) and development (*01 ports) can run simultaneously
# =============================================================================

# =============================================================================
# HOST PORTS
# =============================================================================
API_HOST_PORT=8500
POSTGRES_HOST_PORT=5500
REDIS_HOST_PORT=6500

# =============================================================================
# Application
# =============================================================================
APP_NAME=FastAPI-API
APP_VERSION=1.0.0
ENVIRONMENT=production
DEBUG=false

# =============================================================================
# Server (internal container settings)
# =============================================================================
HOST=0.0.0.0
PORT=8000
RELOAD=false

# =============================================================================
# PostgreSQL
# =============================================================================
POSTGRES_USER=postgres
POSTGRES_PASSWORD=CHANGE_ME_IN_PRODUCTION
POSTGRES_DB=app_db
POSTGRES_HOST=db
POSTGRES_CONTAINER_PORT=5432

DATABASE_URL=postgresql+asyncpg://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_CONTAINER_PORT}/${POSTGRES_DB}

DB_POOL_SIZE=20
DB_MAX_OVERFLOW=10
DB_POOL_TIMEOUT=30
DB_POOL_RECYCLE=1800

# =============================================================================
# Redis
# =============================================================================
REDIS_HOST=redis
REDIS_CONTAINER_PORT=6379
REDIS_PASSWORD=CHANGE_ME_IN_PRODUCTION

REDIS_URL=redis://${REDIS_HOST}:${REDIS_CONTAINER_PORT}

# =============================================================================
# Security / JWT
# =============================================================================
SECRET_KEY=CHANGE_ME_GENERATE_WITH_openssl_rand_base64_32

JWT_ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=15
REFRESH_TOKEN_EXPIRE_DAYS=7

# =============================================================================
# Admin Bootstrap (optional)
# =============================================================================
ADMIN_EMAIL=

# =============================================================================
# Rate Limiting
# =============================================================================
RATE_LIMIT_DEFAULT=100/minute
RATE_LIMIT_AUTH=20/minute

# =============================================================================
# Logging
# =============================================================================
LOG_LEVEL=INFO
LOG_JSON_FORMAT=true

# =============================================================================
# Cloudflare Tunnel (for cloudflared.compose.yml)
# =============================================================================
CLOUDFLARE_TUNNEL_TOKEN=YOUR_TUNNEL_TOKEN_HERE
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
45 changes: 45 additions & 0 deletions backend/app/auth/routes.py → backends/fastapi/app/auth/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@
from core.rate_limit import limiter
from core.exceptions import TokenError
from .schemas import (
MobileLoginResponse,
MobileTokenResponse,
PasswordChange,
RefreshTokenRequest,
TokenResponse,
TokenWithUserResponse,
)
Expand Down Expand Up @@ -92,6 +95,48 @@ async def refresh_token(
return result


@router.post(
"/login-mobile",
response_model = MobileLoginResponse,
responses = {**AUTH_401}
)
@limiter.limit(settings.RATE_LIMIT_AUTH)
async def login_mobile(
request: Request,
auth_service: AuthServiceDep,
ip: ClientIP,
form_data: Annotated[OAuth2PasswordRequestForm,
Depends()],
) -> MobileLoginResponse:
"""
Mobile login - returns both tokens in response body
"""
return await auth_service.login_mobile(
email=form_data.username,
password=form_data.password,
ip_address=ip,
)


@router.post(
"/refresh-mobile",
response_model = MobileTokenResponse,
responses = {**AUTH_401}
)
async def refresh_token_mobile(
auth_service: AuthServiceDep,
ip: ClientIP,
data: RefreshTokenRequest,
) -> MobileTokenResponse:
"""
Mobile refresh - accepts token in body, returns both tokens
"""
return await auth_service.refresh_tokens_mobile(
data.refresh_token,
ip_address=ip,
)


@router.post(
"/logout",
status_code = status.HTTP_204_NO_CONTENT,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,25 @@ class RefreshTokenRequest(BaseSchema):
refresh_token: str


class MobileTokenResponse(BaseSchema):
"""
Schema for mobile token refresh response (returns both tokens)
"""
access_token: str
refresh_token: str
token_type: str = "bearer"


class MobileLoginResponse(BaseSchema):
"""
Schema for mobile login response (returns both tokens + user)
"""
access_token: str
refresh_token: str
token_type: str = "bearer"
user: UserResponse


class PasswordResetRequest(BaseSchema):
"""
Schema for password reset request
Expand Down
Loading
Loading