|
| 1 | +# agents.md — AI Agent Context for jackdomleo.dev |
| 2 | + |
| 3 | +Personal portfolio site for Jack Domleo, Senior Frontend Developer. |
| 4 | +Live URL: https://jackdomleo.dev | Repo: https://github.com/jackdomleo7/jackdomleo.dev |
| 5 | + |
| 6 | +--- |
| 7 | + |
| 8 | +## Stack |
| 9 | + |
| 10 | +| Layer | Technology | |
| 11 | +|---|---| |
| 12 | +| Framework | Nuxt 4 (SSR / static generation via `nuxi generate`) | |
| 13 | +| Language | TypeScript (strict mode) | |
| 14 | +| UI | Vue 3 (Composition API, `<script lang="ts" setup>`) | |
| 15 | +| Styling | SCSS (scoped per component + global partials in `app/assets/styles/`) | |
| 16 | +| Icons | `@nuxt/icon` with a custom Iconify icon set (`custom:*`) | |
| 17 | +| Content | `@nuxt/content` — Markdown files live in `content/` | |
| 18 | +| State | No Pinia store; shared constants via `app/utilities/variables.ts` | |
| 19 | +| Testing | Vitest + `@vue/test-utils` + happy-dom | |
| 20 | +| SEO | `nuxt-seo-utils`, `nuxt-schema-org`, `@nuxtjs/sitemap`, `@nuxtjs/robots` | |
| 21 | +| Package manager | **pnpm** (do not use npm or yarn) | |
| 22 | + |
| 23 | +--- |
| 24 | + |
| 25 | +## Commands |
| 26 | + |
| 27 | +```bash |
| 28 | +pnpm dev # Start dev server (opens browser automatically) |
| 29 | +pnpm generate # Build static site output |
| 30 | +pnpm preview # Preview the generated build |
| 31 | +pnpm lint # ESLint (auto-fix, max 0 warnings) |
| 32 | +pnpm test # Run Vitest (clears coverage first) |
| 33 | +pnpm test:report # Open HTML coverage report |
| 34 | +``` |
| 35 | + |
| 36 | +--- |
| 37 | + |
| 38 | +## Folder Structure |
| 39 | + |
| 40 | +``` |
| 41 | +app/ |
| 42 | + assets/ |
| 43 | + fonts/ # Self-hosted Roboto & Roboto Mono |
| 44 | + icons/ # Custom SVG icons used with @nuxt/icon |
| 45 | + styles/ # Global SCSS partials (imported via main.scss) |
| 46 | + _colors.scss # CSS custom properties for colour tokens |
| 47 | + _font-sizes.scss |
| 48 | + _responsive.scss # CSS variables (DO NOT use in media queries) |
| 49 | + scss/variables/responsive.scss # SCSS variables — USE THESE in @media queries |
| 50 | + components/ |
| 51 | + Navigation.vue |
| 52 | + ProjectList.server.vue # Server component — rendered at build time |
| 53 | + SiteFooter.vue |
| 54 | + layouts/ |
| 55 | + default.vue |
| 56 | + pages/ |
| 57 | + index.vue # Homepage: hero, about, skills, projects preview |
| 58 | + projects.vue |
| 59 | + work.vue |
| 60 | + links.vue |
| 61 | + [slug].vue # Dynamic pages driven by Nuxt Content |
| 62 | + utilities/ |
| 63 | + variables.ts # Shared runtime constants (occupation, URLs, year, experience) |
| 64 | +content/ |
| 65 | + privacy-policy.md |
| 66 | +public/ |
| 67 | + projects/ # Project screenshots |
| 68 | + work/ # Work/employer logos |
| 69 | +nuxt.config.ts |
| 70 | +content.config.ts |
| 71 | +vitest.config.ts |
| 72 | +vitest.setup.ts |
| 73 | +``` |
| 74 | + |
| 75 | +--- |
| 76 | + |
| 77 | +## Key Conventions |
| 78 | + |
| 79 | +### SCSS |
| 80 | +- **Always use SCSS variables** (`$responsive-*`) in `@media` queries, never CSS custom properties (CSS variables don't work in media queries). |
| 81 | +- All breakpoint SCSS variables are defined in `app/assets/styles/scss/variables/responsive.scss` and imported globally via `vite.css.preprocessorOptions`. |
| 82 | +- Component styles use BEM naming (`.block__element--modifier`) and are `scoped`. |
| 83 | +- Global utilities (`container`, `link`, `sr-only`) are applied as plain classes and defined in `app/assets/styles/`. |
| 84 | + |
| 85 | +### Icons |
| 86 | +- Icons are referenced as `custom:<icon-key>` via the `<Icon>` component, e.g. `<Icon name="custom:html" mode="svg" />`. |
| 87 | +- Always set `mode="svg"` on `<Icon>`. |
| 88 | + |
| 89 | +### Variables |
| 90 | +- Shared constants (occupation title, URLs, computed years of experience, current year) live in `app/utilities/variables.ts`. |
| 91 | +- Runtime env vars are exposed via `useRuntimeConfig()` — see `nuxt.config.ts` `runtimeConfig.public`. |
| 92 | + |
| 93 | +### SEO / Schema |
| 94 | +- Per-page canonical URLs are set with `useHead()`. |
| 95 | +- Schema.org structured data uses `useSchemaOrg()` from `nuxt-schema-org`. |
| 96 | +- Global identity (Person schema for Jack Domleo) is configured in `nuxt.config.ts`. |
| 97 | + |
| 98 | +### Components |
| 99 | +- `ProjectList.server.vue` is a Nuxt server component — keep data fetching server-side only. |
| 100 | +- `v-once` is used on static sub-trees (icons, navigation items) for performance. |
| 101 | + |
| 102 | +### Content |
| 103 | +- Markdown pages in `content/` are served via `[slug].vue` using `<ContentRenderer>`. |
| 104 | +- Rich text styles are in `app/assets/styles/rich-text.scss`. |
| 105 | + |
| 106 | +### Performance |
| 107 | +- `v-once` is applied to all static sub-trees (icons, nav items, footer) to prevent unnecessary re-renders. |
| 108 | +- `ProjectList.server.vue` is a Nuxt server component — data fetching is server-side only, reducing client JS. |
| 109 | +- Hero image uses `loading="eager"` and `fetchpriority="high"`; all other images use `loading="lazy" fetchpriority="low"`. |
| 110 | +- Fonts are self-hosted (no remote font requests); `font-display: swap` is set in `_fonts.scss`. |
| 111 | +- The site is statically generated (`nuxi generate`) — all pages are pre-rendered HTML. |
| 112 | +- Animations are wrapped in `@media (prefers-reduced-motion: no-preference)` guards throughout. |
| 113 | + |
| 114 | +### Accessibility |
| 115 | +- Follow WCAG 2.2 AA as a minimum standard. |
| 116 | +- Use semantic HTML elements (`<nav>`, `<header>`, `<footer>`, `<section>`, `<main>`, etc.) rather than divs where appropriate. |
| 117 | +- The `.sr-only` global utility class is used to provide screen-reader-only context (e.g. icon button labels, decorative link supplements). |
| 118 | +- Interactive elements (links, buttons) must always have an accessible label — either visible text or `aria-label` / `.sr-only` text. |
| 119 | +- Navigation uses `aria-label`, `aria-expanded`, `aria-controls`, `aria-hidden`, and `role="menu"` / `role="menuitem"` correctly. |
| 120 | +- All images must have meaningful `alt` text; decorative images use `alt=""`. |
| 121 | +- Focus management is handled for mobile nav open/close interactions. |
| 122 | +- `touch-action: manipulation` is applied globally to links and buttons to prevent 300ms tap delay on mobile. |
| 123 | + |
| 124 | +--- |
| 125 | + |
| 126 | +## Environment Variables |
| 127 | + |
| 128 | +| Variable | Purpose | |
| 129 | +|---|---| |
| 130 | +| `NUXT_BASE_URL` | Full site URL (e.g. `https://jackdomleo.dev`), required for canonical URLs, OG tags, and Schema.org | |
0 commit comments