frontend
blueprint
frontend/ src/ components/ PersonForm.jsx PersonList.jsx pages/ Home.jsx services/ api.js # axios config App.jsx package.json
backend start order
Great question 👍 — order matters a lot when you’re starting a FastAPI + SQLAlchemy + Postgres project. Here’s the recommended sequence from zero (like enterprises do):
🔹 Step 1: Setup project structure
Create the folder layout (
backend/app/...).Add empty
__init__.pyfiles so imports work.Add
requirements.txtwith dependencies.if u made changes in version then run
pip install -r requirements.txt --upgrade --force-reinstall

🔹 Step 2: Database layer
database.py→ setup SQLAlchemy engine,SessionLocal, andBase.models.py→ define your DB tables (ORM models).alembic init → initialize Alembic for migrations.
🔹 Step 3: Schemas
schemas.py→ create Pydantic models for request/response (PersonCreate, PersonOut).These map closely to
models.py, but keep API clean and validated.
🔹 Step 4: Business logic
crud.py→ write functions to insert/query/update data using SQLAlchemy.Keep DB queries out of routes for clean separation.
🔹 Step 5: API layer
routers/persons.py→ build API routes (POST/persons, GET/persons, etc.).app/main.py→ create FastAPI app instance, include routers, add root health-check route.
🔹 Step 6: Migrations
Run Alembic to generate migrations from
models.py.Apply migrations to create/update your PostgreSQL schema.
🔹 Step 7: Testing
Run backend with:
uvicorn app.main:app --reloadCheck API docs at
http://127.0.0.1:8000/docs.
✅ Final Sequence (file order to work on):
requirements.txtdatabase.pymodels.pyalembic/(init + first migration)schemas.pycrud.pyrouters/persons.pymain.py
Would you like me to start coding these step by step for you (beginning with database.py), so you can just copy-paste and run?
frontend and backend code
Excellent 🚀 your database is ready — now let’s build the backend + frontend in a clean way so it scales like an enterprise project.
🔑 Where enterprises start?
Most teams start from the backend first:
Define API contract (schemas, endpoints, validation).
Expose mock or real endpoints.
Then frontend consumes them.
This ensures the database + API are solid before UI connects. Some companies do “API-first design” → publish OpenAPI/Swagger docs so frontend devs can start in parallel.
So let’s start with the backend (Python + FastAPI + Postgres), then do the frontend (React).
🐍 Backend Setup (FastAPI + SQLAlchemy + Alembic)
1. Folder structure
backend/
app/
__init__.py // Purpose: Turns a directory into a Python package.
main.py // Entry point of your FastAPI app. includes routes and runs the app
database.py // Handles database connection setup (SQLAlchemy engine, session, base).
models.py // Contains SQLAlchemy ORM models (database tables).
schemas.py // Defines Pydantic models for request/response validation.
crud.py // Business logic layer. Handles DB queries separate from API routes.
routers/ // Holds modular route files (keeps API endpoints organized).
__init__.py
persons.py
alembic/ # migrations
alembic.ini
requirements.txt // Lists Python dependencies.2. requirements.txt
fastapi // Web framework to build REST APIs quickly with async support.
uvicorn[standard] // ASGI server to run FastAPI apps in production.
sqlalchemy // ORM & SQL toolkit for defining models and querying PostgreSQL.
psycopg2-binary // PostgreSQL database driver used by SQLAlchemy to connect.
alembic // Migration tool to version-control database schema changes.
pydantic // Data validation & serialization library (used in FastAPI schemas).
python-dotenv // Loads environment variables from a .env file for configs.3. database.py
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
import os
DB_USER = os.getenv("DB_USER", "daybuddy_user")
DB_PASS = os.getenv("DB_PASS", "change_me_strong_password")
DB_HOST = os.getenv("DB_HOST", "localhost")
DB_PORT = os.getenv("DB_PORT", "5432")
DB_NAME = os.getenv("DB_NAME", "daybuddy")
SQLALCHEMY_DATABASE_URL = f"postgresql://{DB_USER}:{DB_PASS}@{DB_HOST}:{DB_PORT}/{DB_NAME}"
engine = create_engine(SQLALCHEMY_DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()4. models.py
from sqlalchemy import Column, Integer, String, Text, TIMESTAMP, func
from .database import Base
class Person(Base):
__tablename__ = "persons"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, nullable=False)
email = Column(String, nullable=True)
company = Column(String, nullable=True)
mobile = Column(String, nullable=True)
details = Column(Text, nullable=True)
company_size = Column(Integer, nullable=True)
url = Column(String, nullable=True)
location = Column(String, nullable=True)
created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())5. schemas.py
from pydantic import BaseModel, EmailStr, HttpUrl
from typing import Optional
from datetime import datetime
class PersonBase(BaseModel):
name: str
email: Optional[EmailStr] = None
company: Optional[str] = None
mobile: Optional[str] = None
details: Optional[str] = None
company_size: Optional[int] = None
url: Optional[HttpUrl] = None
location: Optional[str] = None
class PersonCreate(PersonBase):
name: str
class PersonRead(PersonBase):
id: int
created_at: datetime
class Config:
orm_mode = True6. crud.py
from sqlalchemy.orm import Session
from . import models, schemas
def get_persons(db: Session, skip: int = 0, limit: int = 100):
return db.query(models.Person).offset(skip).limit(limit).all()
def create_person(db: Session, person: schemas.PersonCreate):
db_person = models.Person(**person.dict())
db.add(db_person)
db.commit()
db.refresh(db_person)
return db_person7. routers/persons.py
from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session
from .. import schemas, crud, database
from typing import List
router = APIRouter(prefix="/persons", tags=["persons"])
def get_db():
db = database.SessionLocal()
try:
yield db
finally:
db.close()
@router.get("/", response_model=List[schemas.PersonRead])
def list_persons(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
return crud.get_persons(db, skip=skip, limit=limit)
@router.post("/", response_model=schemas.PersonRead)
def create_person(person: schemas.PersonCreate, db: Session = Depends(get_db)):
return crud.create_person(db=db, person=person)8. main.py
from fastapi import FastAPI
from .routers import persons
from .database import Base, engine
# Create tables (for dev; in prod use Alembic migrations)
Base.metadata.create_all(bind=engine)
app = FastAPI(title="Person API")
app.include_router(persons.router)9. Run backend
uvicorn app.main:app --reload --port 8000Docs auto-generated at: http://localhost:8000/docs
⚛️ Frontend Setup (React + Axios + Tailwind)
1. Create project
npm create vite@latest frontend --template react
cd frontend
npm install axios
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -pIn tailwind.config.js:
content: ["./index.html", "./src/**/*.{js,jsx,ts,tsx}"]In src/index.css add:
@tailwind base;
@tailwind components;
@tailwind utilities;2. src/services/api.js
import axios from "axios";
const api = axios.create({
baseURL: "http://localhost:8000",
});
export default api;3. src/components/PersonForm.jsx
import { useState } from "react";
import api from "../services/api";
export default function PersonForm({ onAdded }) {
const [form, setForm] = useState({ name: "", email: "", company: "", mobile: "", details: "", company_size: "", url: "", location: "" });
const handleChange = (e) => {
setForm({ ...form, [e.target.name]: e.target.value });
};
const handleSubmit = async (e) => {
e.preventDefault();
if (!form.name) return alert("Name is required!");
try {
const res = await api.post("/persons/", form);
onAdded(res.data);
setForm({ name: "", email: "", company: "", mobile: "", details: "", company_size: "", url: "", location: "" });
} catch (err) {
console.error(err);
alert("Error saving person");
}
};
return (
<form onSubmit={handleSubmit} className="space-y-2">
<input className="border p-2 w-full" name="name" placeholder="Name *" value={form.name} onChange={handleChange} required />
<input className="border p-2 w-full" name="email" placeholder="Email" value={form.email} onChange={handleChange} />
<input className="border p-2 w-full" name="company" placeholder="Company" value={form.company} onChange={handleChange} />
<input className="border p-2 w-full" name="mobile" placeholder="Mobile" value={form.mobile} onChange={handleChange} />
<input className="border p-2 w-full" name="details" placeholder="Details" value={form.details} onChange={handleChange} />
<input className="border p-2 w-full" type="number" name="company_size" placeholder="Company Size" value={form.company_size} onChange={handleChange} />
<input className="border p-2 w-full" name="url" placeholder="URL" value={form.url} onChange={handleChange} />
<input className="border p-2 w-full" name="location" placeholder="Location" value={form.location} onChange={handleChange} />
<button className="bg-blue-600 text-white p-2 rounded">Save</button>
</form>
);
}4. src/components/PersonList.jsx
export default function PersonList({ persons }) {
return (
<ul className="mt-4 space-y-2">
{persons.map((p) => (
<li key={p.id} className="border rounded p-2">
<div className="font-bold">{p.name}</div>
{p.email && <div>{p.email}</div>}
{p.company && <div>{p.company}</div>}
<div className="text-sm text-gray-500">Added {new Date(p.created_at).toLocaleString()}</div>
</li>
))}
</ul>
);
}5. src/pages/Home.jsx
import { useEffect, useState } from "react";
import api from "../services/api";
import PersonForm from "../components/PersonForm";
import PersonList from "../components/PersonList";
export default function Home() {
const [persons, setPersons] = useState([]);
useEffect(() => {
api.get("/persons/").then((res) => setPersons(res.data));
}, []);
const handleAdded = (newPerson) => {
setPersons([newPerson, ...persons]);
};
return (
<div className="p-4 max-w-xl mx-auto">
<h1 className="text-2xl font-bold mb-4">Person Registry</h1>
<PersonForm onAdded={handleAdded} />
<PersonList persons={persons} />
</div>
);
}6. src/App.jsx
import Home from "./pages/Home";
function App() {
return <Home />;
}
export default App;✅ Next steps
Run backend with
uvicorn.Run frontend with
npm run dev.Try adding a person → check DB → verify list updates.
Later, add Dockerfiles for frontend & backend.
Then wrap with Helm/Kubernetes.
Do you want me to add Alembic migrations setup now (so schema changes are tracked properly, like enterprises do), or keep it simple with Base.metadata.create_all for now?
Last updated