A personal life portfolio template that pulls your content from across the internet and presents it as a unified timeline. Built with Astro.
- Fork / clone this repo
- Edit
src/config.ts— set your name, site URL, social links, and feed handles - Install dependencies —
npm install - Run locally —
npm run dev - Deploy —
npm run build(static output indist/)
Everything is driven by a single file: src/config.ts.
export const config = {
name: 'Your Name',
tagline: 'Your tagline here.',
site: 'https://yourdomain.com',
handle: 'yourusername',
socials: {
github: 'yourusername',
// instagram: 'yourusername',
// x: 'yourusername',
// youtube: '@yourusername',
// linkedin: 'yourusername',
},
feeds: {
github: true, // auto-fetch using default handle
// letterboxd: true,
// substack: true,
// soundcloud: true,
// medium: 'different_handle', // override with a custom handle
// youtube: true, // uses your handle or '@username'
// spotify: [ // specific URLs
// 'https://open.spotify.com/playlist/...',
// ],
},
};Each feed value can be:
true— auto-fetch content using your defaulthandle'string'— auto-fetch using a different handle or ID['url', ...]— show specific URLs (playlists, videos, repos, etc.)
Leave a feed commented out to hide it entirely — no errors, no empty sections.
Create a .env file for optional API keys:
UNSPLASH_ACCESS_KEY=...
- Unsplash — fills in random cover images for feed items that don't have one. Without it, static fallback images are used. Get a key at unsplash.com/developers.
Local content lives in src/content/:
| Directory | Purpose |
|---|---|
posts/ |
Markdown blog posts — served at /blog/{slug}/ — with frontmatter (title, description, date, world, optional cover, tags, draft) |
photos/ |
Photo slides (caption, date, image, optional world) — each gets a /photo/{slug}/ page |
gallery/ |
Photo galleries (title, date, location, cover, photos[], optional world, description, tags) |
videos/ |
YouTube video embeds (title, videoId, date, world, optional description, tags) — each gets a /video/{slug}/ page |
Content is organized into five "worlds": Tech, Film, Music, Writing, Travel. Each feed source maps to a world automatically (e.g., Letterboxd → Film, GitHub → Tech). Worlds are defined in config.ts (the worlds array) and the corresponding CSS color variables live in global.css.
You can create, update, and delete content directly from GitHub Issues — works great from your phone.
| Action | How |
|---|---|
| Create | Open a new issue using a template (Post, Photo, Gallery, Video) |
| Update | Edit the issue body → close and reopen the issue |
| Delete | Add the delete label to the issue |
The included .github/workflows/publish-content.yml workflow handles parsing the issue, committing the content file, and triggering a site rebuild. Only repo owners / collaborators can publish.
Push to your default branch at least once after setup so the workflow can create the required labels (post, photo, gallery, video, delete).
The included .github/workflows/deploy.yml builds and deploys on every push to master and on a daily schedule. To use it:
- Enable GitHub Pages in your repo settings (source: GitHub Actions)
- Optionally add
UNSPLASH_ACCESS_KEYunder Settings → Secrets - Update
public/CNAMEwith your custom domain, or delete the file to useusername.github.io
MIT