Skip to content

Andrew-prog1/FastAPI-Portfolio

Repository files navigation

Portfolio CMS

A self-hosted, full-stack portfolio website with a built-in CMS — built with FastAPI, SQLite, and Jinja2. Manage your projects through a secure admin panel, deploy with Docker, and serve via Nginx with HTTPS.


Features

  • Public site — Homepage, projects overview, project detail pages, contact page
  • Admin CMS — Full CRUD for projects (create, edit, delete, reorder)
  • Markdown support — Write project descriptions in Markdown, rendered to HTML
  • Security — Session-based auth, CSRF protection, login rate limiting, timing-safe credential checks
  • Hero image carousel — Upload images to static/ prefixed hero_car_* and they appear automatically
  • Docker + Nginx — Production-ready stack with HTTPS via Let's Encrypt
  • Visitor statstracker.py parses Nginx access logs and outputs stats.txt

Tech Stack

Layer Technology
Backend Python 3.12, FastAPI, SQLAlchemy
Templates Jinja2
Database SQLite (persisted via Docker volume)
Frontend Tailwind CSS (CDN), vanilla JS
Server Uvicorn + Nginx
Deployment Docker Compose, Let's Encrypt (Certbot)

Getting Started

1. Clone the repository

git clone https://github.com/your-username/your-portfolio.git
cd your-portfolio

2. Configure environment variables

cp .env.example .env

Open .env and fill in your values:

SECRET_KEY=your-generated-secret-key
ADMIN_USERNAME=admin
ADMIN_PASSWORD=your-strong-password

Generate a secure SECRET_KEY:

python -c "import secrets; print(secrets.token_urlsafe(32))"

3. Run locally (without Docker)

python -m venv venv
source venv/bin/activate      # Windows: venv\Scripts\activate
pip install -r requirements.txt
uvicorn main:app --reload

Visit http://localhost:8000 — the admin panel is at /admin/login.

4. Run with Docker Compose

docker compose up --build

The app is then available on port 8000 (Nginx not included in local mode — see deployment).


Project Structure

portfolio/
├── main.py                 # FastAPI app, routes, middleware
├── auth.py                 # Login, session, credential checks
├── database.py             # SQLAlchemy engine and session
├── models.py               # Project model with validators
├── logger_config.py        # Rotating file + console logging
├── tracker.py              # Nginx log parser → stats.txt
├── seed.py                 # One-time example data seeder
├── requirements.txt
├── Dockerfile
├── docker-compose.yml
├── nginx.conf              # Nginx reverse proxy config (edit domain/IP)
├── chmod-static.sh         # Fix static dir permissions on VPS
├── vps-deploy-letsencrypt.sh  # VPS deploy + Certbot helper
├── .env.example            # Template for environment variables
├── templates/
│   ├── base.html
│   ├── index.html
│   ├── projects.html
│   ├── project_detail.html
│   ├── contact.html
│   ├── 404.html
│   └── admin/
│       ├── login.html
│       ├── dashboard.html
│       ├── editor.html
│       └── hero.html
└── static/
    ├── favicon.svg
    ├── hero_car_*.jpg      # Homepage carousel images
    └── uploads/hero/       # Admin-uploaded hero images

Deployment

Prerequisites

  • VPS with Docker and Docker Compose installed
  • A domain pointing to your server's IP
  • Port 80 and 443 open

Steps

1. Update nginx.conf — replace andrew.co.nl and YOUR_SERVER_IP with your actual domain and server IP.

2. Upload the project to your VPS:

scp -r . user@YOUR_SERVER_IP:~/portfolio

3. Set up environment:

ssh user@YOUR_SERVER_IP
cd ~/portfolio
cp .env.example .env
nano .env   # Fill in your real values

4. Obtain SSL certificate (first time):

docker compose run --rm --entrypoint "" nginx \
  certbot certonly --webroot -w /var/www/certbot \
  -d andrew.co.nl -d www.andrew.co.nl \
  --email you@example.com --agree-tos --no-eff-email

5. Deploy:

chmod +x vps-deploy-letsencrypt.sh
./vps-deploy-letsencrypt.sh

Hero Images

Add images named hero_car_1.jpg, hero_car_2.jpg, etc. to the static/ folder — they appear automatically in the homepage carousel. Prefer .webp for better performance (the app will use .webp over .jpg if both exist).


Admin Panel

The admin panel is available at /admin/login.

  • Login with your ADMIN_USERNAME / ADMIN_PASSWORD from .env
  • Dashboard — lists all projects with edit/delete controls
  • Editor — create and edit projects with Markdown descriptions, tech stack, links, and images
  • Login attempts are rate-limited to 5 per 15 minutes per IP

Environment Variables

Variable Required Description
SECRET_KEY Random key for session signing (min. 32 chars)
ADMIN_USERNAME Username for the admin panel
ADMIN_PASSWORD Password for the admin panel
LETSENCRYPT_ROOT optional Path to Let's Encrypt certs (set by deploy script)

License

MIT — feel free to use, adapt, and deploy as your own portfolio.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors