A full‑stack product inventory application built with FastAPI (Python) and React. The backend exposes CRUD APIs for products stored in PostgreSQL, and the frontend provides a clean UI to create, read, update, and delete products.
- FastAPI backend with CORS enabled for the React dev server
- PostgreSQL persistence via SQLAlchemy ORM
- CRUD endpoints: list, get by id, create, update, delete
- React frontend with filtering, sorting, inline edit/delete, and form validation
- Seed data inserted automatically on first run
FASTAPI/
main.py # FastAPI app and endpoints
database.py # SQLAlchemy engine and session factory
database_model.py # SQLAlchemy models (Product)
model.py # Pydantic schema (Products)
frontend/ # React app (create-react-app)
package.json
src/
App.js # UI consuming the API
TaglineSection.js
...
myenv/ # (optional) Python virtual environment
- Python 3.13 (project uses a local venv
myenv/in the repo) - Node.js 18+ and npm
- PostgreSQL 13+ running locally
Ensure a PostgreSQL database exists and is reachable with the configured URL. Default connection string is in database.py:
---
## Backend Setup (FastAPI)
1. Create/activate a virtual environment (optional if you use `myenv/` already present):
```bash
# Windows PowerShell
python -m venv myenv
myenv\Scripts\Activate.ps1
# Install dependencies
pip install fastapi uvicorn sqlalchemy psycopg2-binary pydantic
- Configure the database URL in
database.pyif different from default:
db_url = "postgresql://<user>:<password>@<host>:<port>/<database>"- Run the backend:
uvicorn main:app --reload --host 0.0.0.0 --port 8000- API root: http://localhost:8000/
- OpenAPI docs: http://localhost:8000/docs
- Redoc docs: http://localhost:8000/redoc
On first run, tables are created and seed products are inserted if the table is empty.
- Navigate to the frontend directory and install dependencies:
cd frontend
npm install- Start the React development server:
npm start- React dev server: http://localhost:3000
- The frontend calls the backend at
http://localhost:8000(seesrc/App.js).package.jsonalso sets aproxytohttp://localhost:8000.
If you change backend host/port, update src/App.js (axios baseURL) and package.json proxy accordingly.
- CORS: In
main.py, CORS allowshttp://localhost:3000. - Database URL: In
database.pyviadb_urlvariable. - Table name: SQLAlchemy model
Productmaps to tableMyProducts.
Optional: Use environment variables instead of hardcoding the DB URL. Example pattern:
import os
db_url = os.getenv("DATABASE_URL", "postgresql://postgres:password@localhost:5432/ProductsDB")-
Products(Pydantic request/response model)- id: integer
- name: string
- description: string
- price: float
- quantity: integer
-
Product(SQLAlchemy ORM, tableMyProducts)- id (PK, int)
- name (str)
- description (str)
- price (float)
- quantity (int)
Base URL: http://localhost:8000
-
GET
/→ Welcome message- Response:
"Welcome to NRK Productions"
- Response:
-
GET
/products→ List all products- 200: Array of products
-
GET
/products/{product_id}→ Get a product by id- 200: Product object
- 200 with string:
"Product not found"(note: not a 404)
-
POST
/products→ Create a new product- Body (JSON):
{ id, name, description, price, quantity } - 200: Returns the in-memory
productslist (note: current implementation returns a static list)
- Body (JSON):
-
PUT
/products/{product_id}→ Update a product- Body (JSON):
{ id, name, description, price, quantity } - 200:
"Product updated successfully"or"Product not found"
- Body (JSON):
-
DELETE
/products/{product_id}→ Delete a product- 200:
"Product deleted successfully"or"Product not found"
- 200:
Notes:
- The backend currently returns plain strings for not-found cases and on success for update/delete. In production, consider using proper HTTP status codes and JSON error bodies.
The React app (frontend/src/App.js):
- Fetches products from
/products/on load and on refresh - Provides a form to add or edit a product
- Supports delete, filter by text, and sorting by id/name/price/quantity
- Shows success and error messages with auto-dismiss
Axios baseURL is set to http://localhost:8000. If the backend URL changes, update it here.
In two terminals:
- Backend
# from repository root
myenv\Scripts\Activate.ps1
uvicorn main:app --reload --host 0.0.0.0 --port 8000- Frontend
cd frontend
npm install
npm startOpen http://localhost:3000 in your browser.
-
Backend cannot connect to DB
- Verify PostgreSQL is running and credentials in
database.pyare correct - Ensure
ProductsDBexists: create it viacreatedb ProductsDBor GUI client
- Verify PostgreSQL is running and credentials in
-
CORS errors in browser
- Ensure backend is running on port 8000 and CORS allows
http://localhost:3000
- Ensure backend is running on port 8000 and CORS allows
-
API 500 errors
- Check terminal logs (SQLAlchemy
echo=Trueprints SQL) - Confirm the table
MyProductsexists; it is auto-created bymain.pyon startup
- Check terminal logs (SQLAlchemy
-
Frontend shows “Failed to fetch products”
- Confirm backend is reachable at
http://localhost:8000 - If you changed ports, update
frontend/src/App.jsandfrontend/package.jsonproxy
- Confirm backend is reachable at
- Use environment variables for secrets and DB URL
- Return proper HTTP status codes and JSON error payloads
- Fix POST
/productsto return created resource or DB state, not in-memory list - Add pagination and server-side filtering
- Add tests (backend and frontend)
This project is for learning/demo purposes. Add a license if you plan to distribute.