Self Learning, Curiosity
An interactive full-stack demo for presenting REST API concepts. Users can fire live HTTP requests from the browser and see real responses — built for a live presentation to show GET, POST, PUT, PATCH, and DELETE in action.
I built this because also want to learn on how to hosted it in VPS by using docker.
It's live but I stopped the backend service. Ping me if want to try it on prod.
Visit Here → https://racs.dev-r.org
| Layer | Tech |
|---|---|
| Backend | FastAPI + Python |
| Database | PostgreSQL (psycopg3 + psycopg-pool, no ORM) |
| Frontend | React Javascript + Tailwind CSS v4 |
| DB Hosting | VPS (systemd) |
| Frontend Hosting | Cloudflare Pages |
rest-api-sheet/
├── backend/
│ ├── main.py # FastAPI app, CORS, all 6 endpoints
│ ├── crud.py # All database operations
│ ├── database.py # psycopg_pool connection pool + execute_query helper
│ ├── schemas.py # Pydantic models (UserCreate, UserUpdate, UserPatch, UserResponse)
│ ├── requirements.txt
│ └── .env # DATABASE_URL
├── db/
│ └── init.sql # Creates resapi user, grants privileges, creates users table
└── frontend/
├── index.html
├── vite.config.js
├── package.json
├── .env # VITE_API_URL
└── src/
├── App.jsx # State hub — all state and handlers live here
├── index.css # Tailwind v4 import
└── components/
├── DescriptionCard.jsx # Describes the selected endpoint, colored border per method
├── StatusLegend.jsx # Static display of all 8 status codes
├── InputPanel.jsx # Endpoint selector, dynamic fields, Send/Clear buttons
├── UrlDisplay.jsx # Live URL preview
├── JsonPreview.jsx # Live request body preview
└── ResultPanel.jsx # Response table + status code badge + response time
GET Method
POST Method
PUT Method
PATCH Method
DELETE Method
Base URL: http://localhost:8000
| Method | Endpoint | Description |
|---|---|---|
| GET | /users |
Get all users |
| GET | /users/{id} |
Get a single user by ID |
| POST | /users |
Create a new user |
| PUT | /users/{id} |
Fully replace a user (all fields required) |
| PATCH | /users/{id} |
Partially update a user (all fields optional) |
| DELETE | /users/{id} |
Delete a user |
{
"name": "string",
"age": 0,
"address": "string",
"hobby": "string",
"course": "string"
}Connect to PostgreSQL as a superuser and run:
-- init.sql creates the resapi user and grants privileges
\i db/init.sqlThen create the users table:
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
age INTEGER NOT NULL,
address TEXT NOT NULL,
hobby TEXT NOT NULL,
course TEXT NOT NULL
);Grant the resapi user access to the table:
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE users TO resapi;
GRANT USAGE, SELECT ON SEQUENCE users_id_seq TO resapi;cd backend
python -m venv venv
# Windows
venv\Scripts\activate
# Mac/Linux
source venv/bin/activate
pip install -r requirements.txtCreate backend/.env:
DATABASE_URL=postgresql://resapi:resapi@localhost:5432/rest_api_demoRun the server:
uvicorn main:app --reloadBackend runs at http://localhost:8000.
cd frontend
npm installCreate frontend/.env:
VITE_API_URL=http://localhost:8000Run the dev server:
npm run devFrontend runs at http://localhost:5173.
Run with uvicorn behind a systemd service. Update CORS in main.py with your Cloudflare Pages URL:
allow_origins=["http://localhost:5173", "https://your-site.pages.dev"]Set the environment variable in the Cloudflare Pages dashboard:
VITE_API_URL=https://your-backend-url.com
For presentation of REST API such as the most common one is GET, PUT, POST, DELETE, PATCH
- Create
backendfolder cdintobackend
3. python -m venv venv
4. venv\Scripts\activate # Windows
source venv/bin/activate # Mac/Linux
5. pip install uvicorn
6. pip install fastapi
7. pip install psycopg[binary] psycopg-pool python-dotenv
8. pip freeze > requirements.txt- Create
.envinsidebackend
DATABASE_URL=postgresql://resapi:resapi@localhost:5432/rest_api_demo- Create
main.py— FastAPI app with CORS and all endpoints
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from schemas import UserCreate, UserUpdate, UserPatch
import crud
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:5173"],
allow_methods=["*"],
allow_headers=["*"]
)
@app.get("/health")
def check_health():
return ({ "message": "Hi", "status": "ok" })