Framework-free, single-page portfolio with TypeScript for light behavior, static HTML posts generated from markdown text files, and JSON-backed project entries. Built to be minimal and ultralight—no UI framework or runtime dependencies, just TypeScript compilation and static assets. Build targets dist/wuandr.github.io for GitHub Pages.
src/index.html– main page content (about, experience, projects, blog)src/styles.css– typography, layout, and component stylingsrc/main.ts– scroll spy, smooth nav scrolling, and JSON-backed rendering for projects/postssrc/posts/– individual blog pages plus the archive table (src/posts/posts-archive.html)src/projects/– project archive table assets (src/projects/projects-archive.html,src/projects/projects-archive.ts) plus the manual data override (projects.json)src/assets/Andrew_Wu_resume_20251126.pdf– résumé served directly fromassets/, no duplicate root copyscripts/build.js– copies HTML/CSS/assets, buildsposts.jsonfrom Markdown, fetches GitHub repos, and merges with manualprojects.jsonscripts/fetch-github-repos.js– fetches and filters GitHub repositories for project populationscripts/serve.js– lightweight static server for the built sitegithub-projects.config.js– configuration for GitHub project fetching (topics, filters, etc.).github/workflows/static.yml– Pages workflow that builds and uploadsdist/wuandr.github.io
- Node.js 18+ (uses
fs.cpand ES2020 output) - Only dev dependency is TypeScript; no runtime packages or frameworks are pulled into the build.
npm ci
npm run buildnpm run build compiles src/main.ts to dist/wuandr.github.io/main.js, copies HTML/CSS/assets and posts, and generates posts/projects.json via scripts/build.js.
npm start– rebuild then servedist/wuandr.github.ioat http://localhost:4173 (override withPORT=xxxx)npm run serve– serve the existingdistoutput without rebuilding
Use the server for local testing so JSON fetches (posts/posts.json, projects/projects.json) work without file:// CORS issues.
- Update hero/about/experience copy in
src/index.html. - Posts: start from the template in
CONTENT_GUIDE.mdand add Markdown files tosrc/posts/content/(the directory ships empty by default). The build script renders each post to HTML and populates the archive JSON automatically. - Projects: Automatically populated from GitHub (see below) or manually added via
src/projects/projects.json. - Replace the résumé by updating
src/assets/Andrew_Wu_resume_20251126.pdf(or adjust the filename insrc/index.htmlandscripts/build.jsif renamed). - Tweak styles in
src/styles.css; adjust client behavior insrc/main.tsand rebuild.
Projects are now dynamically populated from your GitHub repositories during the build process.
- The build script fetches your public repositories from GitHub
- Only repos tagged with specific topics (e.g.,
portfolio,showcase) are included - Repository metadata is automatically mapped to project fields
- Manual entries in
src/projects/projects.jsoncan override or supplement GitHub data
- Tag your repository: Add
portfolioorshowcasetopic to the GitHub repo you want to feature- Go to your repository's main page on GitHub
- Find the "About" section on the right sidebar (below the repo description)
- Click the gear icon (⚙️) next to "About"
- In the popup dialog, find the "Topics" field
- Type
portfolioorshowcaseand press Enter - Click "Save changes"
- Push to main: The next deployment will automatically include the project
- Status is automatic:
- "Active" if pushed within last 6 months
- "Archived" if marked as archived on GitHub
- "Maintenance" otherwise
Edit github-projects.config.js to customize:
includeTopics: Which GitHub topics to include (default:['portfolio', 'showcase'])excludeRepos: Specific repos to excludeincludeArchived: Whether to show archived repos (default:true)- See the config file for all available options
To add projects not on GitHub or override GitHub data:
- Add entries to
src/projects/projects.jsonusing the template inCONTENT_GUIDE.md - Manual entries override GitHub data for projects with matching slugs
- This is useful for client work, external projects, or custom descriptions
For local builds, you can optionally provide a GitHub token to avoid rate limits:
- Create a
.envfile in the project root (already in.gitignore) - Add:
GITHUB_TOKEN=your_github_personal_access_token - Run
npm run buildas usual
Note: The GitHub Actions workflow automatically uses GITHUB_TOKEN during deployment, so no additional setup is needed for production builds.
Run npm run build and publish dist/wuandr.github.io. The included GitHub Pages workflow already uploads this folder.
This design was largely inspired by https://brittanychiang.com/