GitHub README
ammdevl | Portfolio
My personal portfolio website — a modern, responsive, and SEO-friendly showcase of my projects, skills, and journey as a developer.
Tech Stack
- Framework: Next.js 16 (Pages Router)
- Styling: Tailwind CSS 3 + SCSS
- Dark Mode: next-themes
- Fonts: Inter + JetBrains Mono (self-hosted via
next/font) - Carousel: embla-carousel-react + autoplay
- Markdown Blog + READMEs: remark + remark-gfm + github-slugger
- Smooth Scroll: Lenis (lerp-based, respects
prefers-reduced-motion) - HTML Sanitization: isomorphic-dompurify
- Visitor Ticket Barcode: jsbarcode (Code 128)
- Image Processing: sharp (resize + compress)
- Linting: ESLint 9 (flat config)
- E2E Tests: Playwright (chromium)
- Deployment: Render.com static site
Features
- Blazing fast — static export with minimal JavaScript
- Dark mode — class-based theme switching
- Responsive — mobile-first design with smooth animations
- SEO optimized — Open Graph + Twitter cards, sitemap.xml, RSS feed, JSON-LD
- Contact form — sends email via Web3Forms
- Smooth scroll — Lenis lerp-based scroll physics with reduced-motion support
- Terminal widget — live uptime counter with personality
- Hero section — viewport-filling hero with quick stats, social links, and scroll indicator
- Liquid Crystal theme — macOS-style glassmorphism with shared glass tokens and animated mesh gradients
- Project README pages — click a project card to view its GitHub README (GFM tables, task lists, badges) like the Blog
- Visitor ticket — modern event ticket with tear animation and scannable Code 128 barcode
- Tabbed skills — category tabs with icons, progress bars, and levels
- Auto-scrolling carousel — featured projects auto-scroll every 2s
- Optimized images — auto-compressed to ~80KB, resized to fit
- i18n — English/Burmese translations via React Context
Getting Started
Environment Variables
Copy .env.example to .env.local and fill in your keys:
cp .env.example .env.local
| Variable | Required | Description |
|---|---|---|
NEXT_PUBLIC_WEB3FORMS_ACCESS_KEY |
Yes | API key from web3forms.com — powers the contact form |
NEXT_PUBLIC_SITE_URL |
No | Canonical URL override (sitemap, RSS, OG tags, JSON-LD). Defaults to site.base_url in config/config.json |
NEXT_PUBLIC_ASSET_VERSION |
No | Cache-buster version (defaults to 1) |
GITHUB_TOKEN |
No | Raises GitHub API rate limits for build-time project README fetches. The site falls back to raw.githubusercontent.com when the API is rate-limited |
For Render.com deployment, add these same variables under Environment → Environment Variables in your service dashboard.
Development
npm install
npm run dev
npm run lint # ESLint
npm run test:e2e # Playwright smoke tests (auto-starts dev server)
npm run generate-feeds # Regenerate sitemap.xml + rss.xml
Open http://localhost:3000 in your browser.
Build & Deploy
npm run optimize-images # Compress images (run after adding new photos)
npm run build # Static export to out/ (Render publish directory)
npm run build:render # Alias for npm run build (used by Render)
npm start # Preview the static export
CI/CD
GitHub Actions runs on every push to main and all pull requests:
| Job | What it does |
|---|---|
| Build | Static export with npm run build:render (next build → out/) |
| Lighthouse CI | Performance, accessibility, SEO audits on all routes |
| E2E Tests | Playwright smoke tests (chromium) |
| Dependency Audit | Fails on critical vulnerabilities |
See .github/workflows/ci.yml for configuration.
Deployment
This project deploys to Render.com only (static site).
Render.com (Static Site)
Auto-deploys from main. Live: ammdevl.onrender.com
Setup (one-time):
- Create a New Static Site on Render
- Connect your GitHub repo
ammdevl/ammdevl-portfolio - Set:
- Build Command:
npm run build:render - Publish Directory:
out
- Build Command:
- Add environment variables under Environment:
NEXT_PUBLIC_WEB3FORMS_ACCESS_KEY= your Web3Forms access key
- Click Deploy
Manual deploy
git add -A
git commit -m "your message"
git push
Project Structure
ammdevl-portfolio/
├── config/ # Site config, theme tokens, menus, social links
├── content/blog/ # Blog posts (Markdown + frontmatter)
├── contexts/ # LanguageContext (i18n)
├── data/ # Content data (projects, skills, experiences...)
├── e2e/ # Playwright smoke tests
├── layouts/ # Base layout, Header, Footer
│ ├── components/ # Reusable UI components
│ └── partials/ # Layout partials
├── locales/ # en.json / my.json translations
├── pages/ # Next.js pages (Home, Projects, Resume, Blog)
├── public/ # Static assets (PDF, images, og-image)
├── scripts/ # Build/utility scripts (images, feeds, OG image)
├── styles/ # SCSS + Tailwind styles
├── utils/ # Shared helpers (project slugs, GitHub README fetch)
├── out/ # Static export output (gitignored)
└── .next/ # Next.js build cache (gitignored)
Pages
| Route | Content |
|---|---|
/ |
Hero with stats & social links, tabbed skills, featured projects, contact form |
/projects |
Project cards with tech stack and GitHub links |
/projects/[slug] |
Project detail with GitHub README (GFM tables, badges, task lists) |
/blog |
Blog listing with Markdown-powered posts |
/resume |
PDF download + preview |