Personal site of Rajkumar — portfolio at / and blog at /blog. Astro 5 + React 18 + Tailwind v4. Deployed to GitHub Pages from main.
- Astro 5 — static-by-default, React islands where they earn their bytes.
- React 18 — only inside hydration islands (
client:loadforCursor/Navbar/Hero;client:visiblefor everything else; static forFooter). - motion/react — animations inside islands.
- Tailwind v4 via
@tailwindcss/vite— CSS-first config insrc/styles/tailwind.css. - Shiki — syntax highlighting (
github-darktheme, baked in by Astro). - Pagefind — static client-side search index for the blog.
- astro-og-canvas — per-post OG images at build time.
- @astrojs/rss + @astrojs/sitemap — feed and sitemap.
- Giscus — GitHub Discussions-backed comments (env-gated).
- GitHub Actions — daily cron + push-triggered build/deploy.
pnpm install
pnpm dev # http://localhost:4321
pnpm build # static dist/
pnpm preview # serve dist/ for Lighthouse
pnpm check # astro check (TypeScript + content collections)Node 20+ recommended.
astro.config.mjs integrations + Tailwind v4 + alias
src/
pages/
index.astro portfolio (11 sections via Base layout)
blog/index.astro blog index + Pagefind search
blog/[slug].astro per-post page
blog/tags/[tag].astro per-tag listing
og/[slug].ts per-post OG image (build-time PNG)
rss.xml.ts feed
layouts/
Base.astro Cursor + Navbar + Footer + slot
BlogPost.astro post chrome + Giscus
components/ React islands
components/blog/ PostCard, TagPill, Search, Giscus
content/blog/ Markdown posts (frontmatter validated by Zod)
content/config.ts collection schema
lib/github-stats.ts build-time fetcher for GithubStats
styles/ tailwind.css + globals.css + theme.css + fonts.css
public/
giscus-theme.css Giscus dark theme matching site palette
.github/workflows/deploy.yml push + 06:00 UTC daily cron → GH Pages
Create src/content/blog/<slug>.md:
---
title: "My new post"
description: "Short summary used in OG meta and the index card."
pubDate: 2026-04-29
tags: [tag1, tag2]
draft: false
cover: /blog-covers/my-post.png
coverAlt: "Description"
---
Body in Markdown. Code blocks render via Shiki. Images use the Astro
asset pipeline. Drafts (`draft: true`) are excluded from the index,
RSS, sitemap, and OG generation.Reading time, OG image, RSS entry, sitemap entry, Pagefind index entry, and Giscus comment thread are all derived automatically.
Pushes to main trigger .github/workflows/deploy.yml, which builds and publishes via actions/deploy-pages. The 06:00 UTC daily cron rebuilds with fresh GitHub stats.
Repo settings to configure once:
- Settings → Pages → Source: GitHub Actions
- Settings → Secrets →
GH_STATS_TOKEN(fine-grained PAT, public_repo:read) — optional but recommended (5000/hr vs 60/hr unauth). - Settings → Variables →
GISCUS_REPO,GISCUS_REPO_ID,GISCUS_CATEGORY,GISCUS_CATEGORY_ID— optional; comments stay disabled (silent fallback) until set.
The site emits robots.txt, sitemap-index.xml, RSS, structured data (Person + WebSite + BlogPosting + BreadcrumbList JSON-LD), Open Graph + Twitter cards, and a placeholder slot for a Google Search Console verification meta tag. Submission is a one-time manual step.
- Go to search.google.com/search-console → Add property → URL prefix →
https://razzkumar.github.io/. - Choose HTML tag as the verification method. Copy the
content="…"value (a 40-char token). - In the GitHub repo: Settings → Secrets and variables → Actions → Variables → New repository variable:
- Name:
GSC_VERIFICATION - Value: the token only (no
<meta>wrapper).
- Name:
- Push any commit (or run the workflow manually). GitHub Actions deploy will inline
<meta name="google-site-verification" content="…">into every page's<head>viaPUBLIC_GSC_VERIFICATION. - Back in GSC, click Verify. Once verified:
- Sitemaps → Add a new sitemap →
sitemap-index.xml→ Submit. - Settings → Email preferences → enable Coverage / Manual action alerts.
- Sitemaps → Add a new sitemap →
The GSC token is a public site-ownership proof, not a secret — it's correctly stored as a repo Variable (which gets inlined into the static bundle), not as a Secret.
- Go to bing.com/webmasters → Add site.
- Choose Import from Google Search Console for one-click verification (works once GSC is verified).
- Sitemaps → Submit a sitemap →
https://razzkumar.github.io/sitemap-index.xml(Bing imports it automatically from GSC, but a manual submit is a safe backup).
After deploy:
- search.google.com/test/rich-results → enter
https://razzkumar.github.io/→ expect Person + WebSite detected. - Same for
https://razzkumar.github.io/blog/hello-blog/→ expect BlogPosting + BreadcrumbList. - Social card preview: opengraph.xyz or LinkedIn's Post Inspector.