- Roboto Flex loaded from Google Fonts for compact UI text - Reduced decorative borders while retaining useful input and divider borders - Fixed blank journal detail pages - Password-protected journal publisher with four-hour signed sessions - New articles saved directly to posts.json - Prominent Spotify, Instagram, and Steam buttons on Contact - Desktop and mobile layouts visually verified - Production build and authorization tests passed
2.8 KiB
Alex Herlan Portfolio
A custom React and FastAPI portfolio built from Alex Herlan's résumé. The interface uses hand-written CSS—no Tailwind or component library—and all profile, career, skills, and journal content is loaded from JSON through the API.
Project structure
backend/
data/ JSON content store
main.py FastAPI routes, SMTP delivery, and production serving
requirements.txt
frontend/
public/ Alex's locally stored profile image
src/ React pages, components, and custom CSS
Alexander Herlan Resume 2024.pdf
Alexander Herlan Resume 2024.md
Run locally
Create and install the Python environment from the repository root:
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r backend\requirements.txt
Start FastAPI:
uvicorn backend.main:app --reload --port 8000
In a second terminal, start React:
cd frontend
npm install
npm run dev
Open http://localhost:5173. Vite proxies /api requests to FastAPI on port 8000.
The interface loads Roboto Flex from Google Fonts for its compact UI copy, while editorial headings keep the résumé-inspired serif treatment.
Contact-form delivery
The form uses POST /api/contact and sends email through SMTP. Copy backend/.env.example to backend/.env, fill in the SMTP values, and start the API with the environment file:
uvicorn backend.main:app --reload --port 8000 --env-file backend\.env
If SMTP is unavailable, the API returns a clear delivery error and the page keeps Alex's direct email, LinkedIn, and GitHub links visible.
Journal publisher
Open http://localhost:5173/blog/manage and sign in with the journal admin password. Publishing writes the new article directly to backend/data/posts.json; no database is involved.
Set unique production values in backend/.env:
JOURNAL_ADMIN_PASSWORD=replace-with-a-strong-password
JOURNAL_TOKEN_SECRET=replace-with-a-long-random-secret
The login endpoint returns a signed session that expires after four hours. The password remains server-side and the browser stores only the temporary token.
Content API
GET /api/profileGET /api/experienceGET /api/skillsGET /api/postsGET /api/posts/{slug}POST /api/auth/loginGET /api/auth/sessionPOST /api/posts(authenticated)GET /api/resumePOST /api/contact
Edit the files in backend/data to update portfolio content. No database is required.
Production build
cd frontend
npm run build
cd ..
uvicorn backend.main:app --host 0.0.0.0 --port 8000
When frontend/dist exists, FastAPI serves the built single-page application and supports direct links such as /experience and /blog/{slug}.