This backend follows a layered architecture to separate concerns and keep the codebase maintainable:
- FastAPI handles routing, request validation, and dependency injection
- SQLAlchemy ORM manages database models and relationships
- Alembic handles schema migrations
- PostgreSQL serves as the primary database
- External services (Stripe, SendGrid, AWS S3) are integrated via service modules
- The API is designed to be consumed by a single-page React frontend.
- FastAPI — high-performance Python web framework
- SQLAlchemy — ORM for database interactions
- Alembic — database migrations
- PostgreSQL — relational database
- Stripe API — secure checkout and payment processing
- SendGrid API — contact form email delivery
- AWS S3 — product image storage
- Pytest — automated testing
.
├── alembic/ # Database migrations
├── app/
│ ├── models/ # SQLAlchemy models
│ ├── schemas/ # Pydantic request/response schemas
│ ├── routes/ # API route definitions
│ ├── services/ # Stripe, SendGrid, S3 integrations
│ ├── core/ # Config, database session, security helpers
│ └── main.py # FastAPI app entry point
├── tests/ # Pytest test suite
├── seed.py # Optional database seeding
├── seed_images.py # Optional S3 image seeding
└── requirements.txt
Admin functionality is restricted to authenticated users.
- Admin users are stored in the database
- Credentials are validated server-side
- Protected routes check admin authentication before allowing access
- The frontend conditionally exposes admin-only UI based on authentication state
This prevents unauthorized users from accessing inventory management and analytics endpoints.
Stripe is used to securely process customer payments.
- The frontend sends cart data to the backend checkout endpoint
- The backend creates a Stripe Checkout Session using the Stripe Secret Key
- Stripe handles payment processing and redirects the user
- After payment, the user is redirected back to the frontend using FRONTEND_URL
STRIPE_SECRET_KEYFRONTEND_URL
Sensitive payment logic is handled exclusively on the backend for security.
The contact form submits messages to the backend, which sends emails using SendGrid.
- User submits the contact form on the frontend
- Frontend sends the message to the API
- Backend sends an email via SendGrid
- Email is delivered to the configured destination inbox
SENDGRID_API_KEYFROM_EMAILTO_EMAIL
This keeps email credentials secure and avoids exposing API keys to the client.
Product images are uploaded to and served from AWS S3.
- Images are uploaded from the backend
- Only image keys/URLs are stored in the database
- Images can be added or removed when products or variants change
This approach avoids storing binary files in the database and improves scalability.
- Request validation is handled using Pydantic schemas
- Invalid requests return structured error responses
- Database and external service errors are caught and logged
- HTTP status codes follow REST conventions
FastAPI automatically generates interactive API documentation:
- Swagger UI: http://localhost:8000/docs
- ReDoc: http://localhost:8000/redoc
These tools were used extensively during frontend integration and testing.
- Pytest is used for automated testing
- A separate test database is configured via environment variables
- Tests cover:
- Core API routes
- Database interactions
- Error handling paths
- Tests can be run locally without affecting development data.
- Environment variables must be configured in production
- Debug mode should be disabled
- Database migrations should be run before serving traffic
- Static assets (images) are served via S3, not the API server
FastAPI backend for the Eterno Soaps ecommerce application.
- Python 3.10+
- PostgreSQL
Create a .env file in the project root with the following variables:
| Variable | Required | Description | Example |
|---|---|---|---|
| SQLALCHEMY_DATABASE_URI | Yes | Postgres connection string for dev/prod | postgresql+psycopg2://user:password@localhost:5432/eterno_soaps_api_development |
| SQLALCHEMY_TEST_DATABASE_URI | Yes (tests) | Postgres connection string for tests | postgresql+psycopg2://user:password@localhost:5432/eterno_soaps_api_test |
| ADMIN_JWT_SECRET | Yes (auth) | Secret key used to sign admin access tokens | use-a-long-random-secret |
| ADMIN_ACCESS_TOKEN_EXPIRE_MINUTES | Optional (auth) | Admin token expiration time in minutes | 60 |
| STRIPE_SECRET_KEY | Yes (checkout) | Stripe secret key | |
| FRONTEND_URL | Yes (checkout) | Frontend base URL for Stripe redirects | http://localhost:5173 |
| SENDGRID_API_KEY | Yes (contact form) | SendGrid API key | SG... |
| FROM_EMAIL | Yes (contact form) | Verified sender email | [email protected] *can be identical to TO_EMAIL |
| TO_EMAIL | Yes (contact form) | Destination email for contact form | [email protected] |
| AWS_ACCESS_KEY_ID | Yes (S3 images) | AWS access key | |
| AWS_SECRET_ACCESS_KEY | Yes (S3 images) | AWS secret key | |
| AWS_REGION | Yes (S3 images) | AWS region | us-west-2 |
| AWS_BUCKET_NAME | Yes (S3 images) | S3 bucket name for product images | eterno-soaps-assets |
This application uses AWS S3 to store and serve product images. To set up your S3 bucket:
-
Create an S3 bucket in your AWS console with a unique name (e.g.,
eterno-soaps-assets) -
Create IAM user credentials:
- Create an IAM user with programmatic access
- Attach a policy with
s3:PutObject,s3:GetObject, ands3:DeleteObjectpermissions for your bucket - Save the Access Key ID and Secret Access Key to your
.envfile
-
Set the bucket region in your
.envfile to match your S3 bucket's region
- Create and activate a virtual environment:
python3 -m venv venv
source venv/bin/activate
- Install dependencies:
pip install -r requirements.txt
- Create Postgres databases:
eterno_soaps_api_development
eterno_soaps_api_test
- Run migrations:
alembic upgrade head
- If new models are created or current models are updated. Run migrations:
alembic revision --autogenerate -m "added new script for xxx"
alembic upgrade head
python seed.py
Optional image key seeding (requires S3 env vars):
python seed_images.py
uvicorn main:app --reload
The API will be available at http://localhost:8000 with docs at http://localhost:8000/docs
POST /admins/now requiresusernameandpassword(password is stored hashed, never plain text).POST /admins/loginreturns a bearer token.- Protected admin endpoints (
GET /admins/,GET /admins/{username}) requireAuthorization: Bearer <token>.
pytest
The Eterno Soaps API provides a secure, scalable backend for an ecommerce application, supporting product management, checkout, email communication, and image hosting. It is designed to integrate cleanly with a React frontend and follows best practices for API design, security, and maintainability.