This Portfolio Site
▶ Architecture diagram — self-contained HTML, opens in a browser — no install, no build
Situation
A static portfolio where content (projects, posts) is edited in Markdown rather than component markup. Hosting is GitHub Pages as a user site (repository NikitaBoyarkin.github.io, served from the domain root), deploy is push-triggered with no manual build. Content and presentation must separate: a new project is a new .md file, with no component edits.
Task
I needed publishing a project to be a content change and not a code change, so I owned the setup where a new Markdown file is enough and the deploy follows from a push.
Actions
Stack: Astro 7, TypeScript, Markdown content collections (src/content/{projects,posts}/), Zod schemas in src/content.config.ts.
Architecture:
- Content collections — each project/post = Markdown + frontmatter; Zod validates fields at build.
- Base path —
withBase()fromsrc/lib/path.tsappliesbaseto all internal links and images (the site now serves from the root,base: '/'). - Theme — an inline
<head>script readslocalStorage/prefers-color-schemeand setsdata-themebefore first paint (no flash); CSS custom properties are reactive. - SEO —
sitemap.xml,robots.txt,rss.xml, JSON-LD, OG/Twitter meta, canonical. - Deploy — GitHub Actions builds
dist/and publishes to Pages on push tomaster.
Validation: scripts/check_site.py checks required pages, internal links, the profile image, and assets in index.html.
Result
Content collections with Zod are a contract between content and presentation: invalid frontmatter breaks the build, not the deploy. withBase() encapsulates the GitHub Pages base path — no link hardcodes the base. The “content = .md, presentation = .astro” split means adding a project requires no code changes.
Limitations
The site is built for one hosting setup: GitHub Pages as a user site with base: '/'. Moving to a project page or another host would require changes to withBase() and the deploy workflow. Validation covers structure and links, not content.