Static GitHub Pages portfolio for thermal-fluid engineering, gas turbine CFD/CHT, test instrumentation, energy management and energy systems modelling applications.
Use these defaults when adding or editing UI so pages stay visually consistent:
- Color system:
- Primary accent:
#1f4f73 - Secondary accent:
#2f6b83 - Surface dark:
#121820 - Border dark:
rgba(255,255,255,0.09)
- Primary accent:
- Radius and container:
- Global radius:
16px - Max content width:
1120px
- Global radius:
- Spacing rhythm:
--space-1: 8px--space-2: 12px--space-3: 16px--space-4: 20px--space-5: 28px--space-6: 40px--space-7: 56px
- Typography:
h1:clamp(2.05rem, 3.6vw, 3.1rem)h2:clamp(1.55rem, 2.5vw, 2.2rem)h3:clamp(1.08rem, 1.6vw, 1.22rem)- Body text:
1remwith line-height around1.58–1.62
- Thumbnail spec:
- Aspect ratio:
16:9 - Use
object-fit: cover - Keep a single frame style: dark panel + subtle border + monospace labels
- Avoid rainbow accents; use primary/secondary with one support highlight only
- Aspect ratio:
Open this folder in VS Code and edit:
index.htmlfor the homepagestyles.cssfor stylingprojects/*.htmlfor individual project case studiesexperience/*.htmlfor individual experience pagesapi/certifications.jsonfor the read-only certifications data endpointbackend/data/*.jsonfor REST API-backed editable dataadmin.htmlfor the backend record editordownloads/for role-specific CV PDFs. The homepage expects title-led CV cards for gas turbine CFD, test/instrumentation, energy coordination and PhD tracks.assets/thumb-*.svgfor project visuals and data-rich thumbnail figures
GitHub Pages serves static JSON files, so profile data is exposed through read-only endpoints:
/api/certifications.json
/api/linkedin-projects.json
/api/linkedin-experience.json
/api/courses.json
/api/skills.json
The About page fetches this JSON and renders the certifications client-side.
A real Node REST API now lives in backend/. It is separate from GitHub Pages because GitHub Pages can only host static files.
You do not need to buy a domain for this. You can deploy the backend on a platform such as Render, Railway or Fly.io and use the provider URL, then point the GitHub Pages frontend at that URL.
Backend collections:
GET /api/certifications
GET /api/projects
GET /api/experience
GET /api/courses
GET /api/skills
GET /api/content
GET /api/admin/session
POST /api/:collection
PUT /api/:collection
PUT /api/:collection/:id
PATCH /api/:collection/:id
DELETE /api/:collection/:id
PUT /api/content
Write requests require this header:
Authorization: Bearer <ADMIN_API_TOKEN>
The same write endpoints also accept a Firebase Google ID token when the backend has FIREBASE_PROJECT_ID and admin email hashes configured.
Serve the folder over HTTP before testing API-backed sections. Browser fetch() calls usually fail when opening about.html directly from file://.
cd E:\abhijith-sivaprasadan.github.io
python -m http.server 8000 --bind 127.0.0.1Open:
http://127.0.0.1:8000/
http://127.0.0.1:8000/about.html
http://127.0.0.1:8000/api/certifications.json
Stop the server with Ctrl+C in the terminal that started it.
To run the REST API locally, open a second terminal:
cd E:\abhijith-sivaprasadan.github.io\backend
$env:ADMIN_API_TOKEN="change-this-local-token"
$env:FRONTEND_ORIGIN="http://127.0.0.1:8000"
npm run devBackend URLs:
http://127.0.0.1:3000/health
http://127.0.0.1:3000/api
http://127.0.0.1:3000/api/certifications
To make the frontend read from the REST API instead of static JSON:
Copy-Item scripts/config.example.js scripts/config.jsThen set this in scripts/config.js:
globalThis.PORTFOLIO_API_BASE_URL = "http://127.0.0.1:3000";The live GitHub Pages site reads its production API URL from scripts/public-config.js.
Open the admin editor at:
http://127.0.0.1:8000/admin.html
Use Google sign-in or paste the same ADMIN_API_TOKEN value into the admin page to create, update and delete backend records. The admin editor supports hashes such as admin.html#projects so you can open a specific collection directly.
The admin editor can use Firebase Google sign-in. The backend verifies the Google ID token before allowing insert, update, delete or full-collection write operations.
- Create a Firebase project.
- In Firebase Authentication, enable Google as a sign-in provider.
- Add authorized domains:
localhost127.0.0.1abhijith-sivaprasadan.github.io
- Copy the web app config from Firebase project settings.
- Set these Render backend environment variables:
FIREBASE_PROJECT_IDADMIN_EMAIL_HASHES
- Copy the example config for local testing:
Copy-Item scripts/config.example.js scripts/config.js- Edit
scripts/config.jsand fillglobalThis.PORTFOLIO_AUTH_CONFIG. - Generate the SHA-256 hash of each admin email and add it to backend
ADMIN_EMAIL_HASHES:
node -e "crypto.subtle.digest('SHA-256', new TextEncoder().encode('[email protected]'.toLowerCase())).then(b=>console.log([...new Uint8Array(b)].map(x=>x.toString(16).padStart(2,'0')).join('')))"scripts/config.js is ignored by git, so local Firebase config is not committed by accident. Firebase web config is not a private server secret, but commit it deliberately only if you want Google admin login enabled on GitHub Pages:
git add -f scripts/config.jsCommit and push the frontend/backend repo:
git add .
git commit -m "Update portfolio"
git push origin mainGitHub Pages URL:
https://abhijith-sivaprasadan.github.io
The repo includes render.yaml, so Render can create the backend from the repository.
- Push this repo to GitHub.
- In Render, choose New > Blueprint.
- Connect
abhijith-sivaprasadan/abhijith-sivaprasadan.github.io. - Render will detect
render.yamland createabhijith-portfolio-api. - After deploy, copy the service URL, for example:
https://abhijith-portfolio-api.onrender.com
- Put that URL in
scripts/public-config.jsfor the public GitHub Pages site:
globalThis.PORTFOLIO_API_BASE_URL = "https://abhijith-portfolio-api.onrender.com";- Open
admin.html, use the backend URL and the generatedADMIN_API_TOKENfrom Render environment variables.
The current backend stores edits in JSON files. That is good for localhost and simple demos. For production editing that must survive restarts/redeploys, add persistent storage later with a Render disk, Supabase, Neon Postgres or another database.