Personal portfolio site, built with React, TypeScript, Vite, Tailwind CSS, and Framer Motion. Deployed to GitHub Pages at adlahiru.com.
npm install
npm run devnpm run build
npm run previewAll copy lives under src/data/ — edit those files to update site content without touching components:
- src/data/site.ts — nav links, email, phone, socials, site URL
- src/data/sections/ — one file per section (hero, about, skills, experience, projects, publications, recognition, contact)
- src/data/sectionOrder.ts — visible section order; eyebrow numbers ("01 — ABOUT") derive from it automatically
Append one object to the right items array — e.g. a certification in src/data/sections/recognition.ts:
{
date: '2026',
title: 'AWS Certified Machine Learning',
org: 'Amazon Web Services',
desc: 'What it covers.',
link: 'https://credential-url', // optional — renders "VIEW CREDENTIAL →"
image: myImage, // optional — import from ../../assets/certifications/
imageVariant: 'portrait', // optional — overrides the group default
}Card numbers and monogram tiles are derived automatically (see src/lib/derive.ts); set monogram only to override the initials. Each recognition group and the projects section support initialVisible: n — cards beyond n hide behind a "View more" button.
Awards use the original feature layout (layout: 'feature') — wide horizontal cards with image on the left and copy on the right, in a 2-column grid with alternating reveals. Volunteering uses a timeline layout (layout: 'timeline') with a center spine, alternating image/copy sides, and equal-height image frames. Certifications use a uniform landscape grid (layout: 'grid'). Set imageVariant per entry to override the group's defaultImageVariant.
Images live in src/assets/ by section: profile/, education/, projects/, awards/, certifications/, volunteering/. Entries without an image render a gradient monogram tile (src/components/primitives/PlaceholderImage.tsx).
The Publications section is built but hidden — to show it, add 'publications' to sectionOrder and render <Publications /> in src/App.tsx.
On-site signals live in index.html (title, meta, Open Graph/Twitter, Person + WebSite JSON-LD) and public/ (robots, sitemap, headshot, OG image, manifest, llms.txt, humans.txt, .well-known/security.txt). Production builds prerender the homepage into dist/index.html (Playwright) so crawlers see real content — see scripts/prerender.mjs.
After content changes worth re-indexing, bump <lastmod> in public/sitemap.xml.
Code cannot finish indexing or off-site authority. After deploying these SEO changes:
- Google Search Console — search.google.com/search-console
- Add property
adlahiru.com(DNS TXT or HTML file verification) - Submit sitemap:
https://adlahiru.com/sitemap.xml - URL Inspection on
https://adlahiru.com/→ Request indexing
- Add property
- Bing Webmaster Tools — bing.com/webmasters — add the site and submit the same sitemap
- LinkedIn — display name Lahiru Dilshan, website =
https://adlahiru.com/, profile public; keep URL matching Person schemasameAs - GitHub — profile name Lahiru Dilshan, website field =
https://adlahiru.com/, profile public; matchsameAs - Share / link the site from bios, CV, club pages, and project READMEs whenever you can
- Verify after deploy — View Source on the live homepage (title + JSON-LD), then Rich Results Test on
https://adlahiru.com/
Prerendering improves crawlability; ranking for “Lahiru Dilshan” / “Lahiru” still depends on consistent profiles, backlinks, and time after indexing.
Pushing to main triggers .github/workflows/deploy.yml, which installs Chromium, builds (with prerender), and publishes via GitHub Pages. Repo Settings → Pages source must be set to "GitHub Actions".
Custom domain: public/CNAME carries adlahiru.com into every deploy; the domain must also be set under repo Settings → Pages → Custom domain, with DNS A records pointing at GitHub Pages.