Imported from ilyhalight/toiloff (
AGENTS.md). Install upstream withnpx skills add ilyhalight/toiloff. Copyright stays with the author.
Project
Personal website frontend for Toiloff, built with Astro 7 and Bun.
Development
- Use Bun for package management and scripts.
- Required Node version:
>=22.12.0. - Install dependencies with
bun install. - Run production checks with
bun run build. - Preview production output with
bun preview.
When starting the dev server, use Astro background mode:
bun astro dev --background --host
Manage the background server with bun astro dev stop, bun astro dev status, and bun astro dev logs.
Code Style
- Prefer
for...ofloops over.forEach()for iteration.
Architecture
- Main layout:
src/layouts/Layout.astro. - Pages live in
src/pages/; current routes are/(index.astro),/about(about.astro),/blog(blog.astro),/blog/[slug](blog/[slug].astro), and/404(404.astro). - Global reset, design tokens, utility classes, and shared button styles live in
src/components/GlobalStyle.astro. - Site title metadata comes from
getEntry("settings", "settings"), backed bysrc/data/settings.jsonthroughsrc/content.config.ts. Layout.astroincludesHeader,Footer, global styles, the Poppins font, AstroClientRouter, and fade transitions for route changes.- Keep reusable section blocks in
src/components/<Group>/<Name>.astrowhen a component belongs to a feature group. - The icon directory is currently named
src/components/Icones/; use the existing spelling unless deliberately renaming the whole folder.
Design
Styling
- Pure CSS with Astro scoped
<style>blocks; no Tailwind, Bootstrap, or other CSS framework. - Global tokens are CSS custom properties in
:rootand[data-theme="light"]insideGlobalStyle.astro. - Dark-first theme: dark values are the default
:root; light values are enabled withdata-theme="light"onbody. ThemeSwitcher.astrotogglesdocument.body.dataset.theme; it is used in desktop preferences fromHeader.astroand inMobileNav.astro.- Use BEM-like class names with kebab-case and
__for elements, e.g..nav-list__item-link. - Prefer existing utility classes:
.button,.button_outline,.text-truncate, and.text-wrap. - Do not add unused
data-*attributes; every data hook should be read by CSS or JavaScript. - Preserve the current rounded-card, glass-header, soft-gradient, dark-first visual language unless explicitly redesigning.
Design Tokens
| Token | Dark | Light |
|---|---|---|
--background |
#05010d |
#fff |
--surface-bg |
#131317 |
#f5f5f5 |
--onsurface-bg |
#27272a |
#eaeaea |
--onsurface-hover-bg |
#1d1d1d |
#dddddd |
--text-color |
rgb(220, 220, 230) |
#0a0a0f |
--text-muted |
rgb(130, 130, 150) |
#616171 |
--text-hover-color |
#fff |
#302f2f |
--primary-color |
#ff6363 |
#ff6363 |
--success-color |
#4ade80 |
#4ade80 |
--logo-color |
#fff |
#0a0a0f |
--stroke-color |
#3a3a3f |
#c0c0c0 |
--header-bg |
#1a1a1aa3 |
#edededa3 |
--header-link-color |
var(--text-color) |
var(--text-color) |
--header-link-hover-color |
var(--text-hover-color) |
var(--text-muted) |
--button-bg |
#e6e6e6 |
#05010d |
--button-shadow-color |
var(--text-color) |
var(--text-color) |
--button-hover-color |
var(--text-hover-color) |
var(--text-hover-color) |
--button-text-color |
var(--background) |
var(--background) |
--button_outline-border-color |
var(--stroke-color) |
var(--stroke-color) |
--button_outline-bg |
#28292e |
#f0f0f0 |
Typography
- Poppins is configured through Astro's font provider in
astro.config.mjsand exposed as--font-poppins. - Fallback stack:
"Inter", system-ui, sans-serif. - Base size:
16px.
Layout
.appis a centered flex column withmax-width: 1280pxandmin-height: 100svh.mainis a flex column withflex: 1.- Header is fixed within a 100px header area, pill-shaped (
border-radius: 1.75rem), glassmorphic (backdrop-filter: blur(64px)), andwidth: min-contenton desktop. - Mobile breakpoints are mostly
500px, with component-specific breakpoints where needed.
Components
| Component | File | Purpose |
|---|---|---|
| GlobalStyle | src/components/GlobalStyle.astro |
Global reset, tokens, utilities, shared button styles |
| Header | src/components/Header.astro |
Fixed glass navigation, desktop preferences, and mobile nav trigger |
| Footer | src/components/Footer.astro |
Site footer |
| Logo | src/components/Logo.astro |
Inline SVG logo |
| MobileNav | src/components/MobileNav.astro |
Mobile sheet navigation and mobile preferences |
| Preferences | src/components/Preferences.astro |
Details-based preferences popover |
| PreferenceRow | src/components/PreferenceRow.astro |
Label/description row for preference controls |
| ThemeSwitcher | src/components/ThemeSwitcher.astro |
Dark/light theme toggle |
| Hero | src/components/Hero.astro |
Home hero with decorative shapes and actions |
| PageSection | src/components/PageSection/PageSection.astro |
Reusable revealed section wrapper with optional CTA link |
| SectionWrapper | src/components/Section/SectionWrapper.astro |
Generic page/section stack wrapper |
| SectionHero | src/components/Section/SectionHero.astro |
Shared section title, eyebrow, and description block |
| Project | src/components/Project/Project.astro |
Project grid wrapper |
| ProjectItem | src/components/Project/ProjectItem.astro |
Project card |
| Stats | src/components/Stats/Stats.astro |
Stats card grid |
| StatsItem | src/components/Stats/StatsItem.astro |
Stats card shell with decorative lines |
| StatsContentCard | src/components/Stats/StatsContentCard.astro |
Small stats content block |
| StatsContentDetail | src/components/Stats/StatsContentDetail.astro |
Label/value detail row for stats cards |
| StatsLines | src/components/Stats/StatsLines.astro |
Decorative SVG line background for stats cards |
| Guestbook | src/components/Guestbook/Guestbook.astro |
Guestbook message list with optional load-more placeholders |
| GuestbookContent | src/components/Guestbook/GuestbookContent.astro |
Reusable guestbook form and message-list grid |
| GuestbookForm | src/components/Guestbook/GuestbookForm.astro |
Frontend mock create-message form with moderation success state |
| GuestbookPlaceholder | src/components/Guestbook/GuestbookPlaceholder.astro |
Skeleton cards shown during guestbook load-more reveal |
| GuestMessage | src/components/Guestbook/GuestMessage.astro |
Guestbook message card, link normalization, platform icon selection |
| GuestMessageReply | src/components/Guestbook/GuestMessageReply.astro |
Reply block inside a guestbook message |
| AboutCard | src/components/About/AboutCard.astro |
About profile detail card |
| AboutSocialItem | src/components/About/AboutSocialItem.astro |
About page social link item |
| Dropdown | src/components/Dropdown/Dropdown.astro |
Custom dropdown control |
| BlogHero | src/components/Blog/BlogHero.astro |
Blog page title, search input, custom tag dropdown, and filter script |
| BlogPostList | src/components/Blog/BlogPostList.astro |
Blog post grid and empty search state |
| BlogPostCard | src/components/Blog/BlogPostCard.astro |
Blog post card with image, tag, title, description, date, and reading time |
| BlogPostHero | src/components/Blog/BlogPostHero.astro |
Blog detail hero with dark image background and post metadata |
| BlogPostLayout | src/components/Blog/BlogPostLayout.astro |
Blog detail 70/30 content and sidebar grid |
| BlogPostContent | src/components/Blog/BlogPostContent.astro |
Blog detail article sections |
| BlogPostSidebar | src/components/Blog/BlogPostSidebar.astro |
Blog detail authors and content anchor links |
| BlogPostAuthorCard | src/components/Blog/BlogPostAuthorCard.astro |
Blog detail author/member card |
| Icones | src/components/Icones/*.astro |
Inline SVG icon components |
Pages
src/pages/index.astro: home page with hero, projects, stats, and guestbook sections.src/pages/about.astro: about page with profile cards, social links, and tech stack icons.src/pages/blog.astro: blog list page with API-shaped placeholder posts, hero search, tag filtering, and post cards.src/pages/blog/[slug].astro: blog detail page generated from placeholder post records.src/pages/404.astro: custom not-found page with image asset and home link.
Data And Content
src/content.config.tsdefines thesettingscollection using Astro'sfile()loader.src/data/settings.jsonstoresdefaultTitleanddefaultDelimiter.- Blog data currently uses local API-shaped placeholders in
src/data/blog.ts; keepBlogPostandBlogPostDetailinsrc/components/Blog/types.tsaligned with the future API response. - Guestbook data currently uses local API-shaped placeholders in
src/data/guestbook.ts; keepGuestbookMessagealigned with the future API response. - Keep structured site-wide settings in
src/data/settings.jsonand update the schema insrc/content.config.tswhen adding fields.
Documentation
Full documentation: https://docs.astro.build
Consult these guides before working on related tasks: