{"owner":"arthelokyo","repo":"astrowind","hasSkills":true,"totalSkillsCount":5,"totalTokensCount":3262,"categories":["root-instruction","anthropic-skill","claude-rule"],"hasMcp":false,"mcpConfig":null,"found":["AGENTS.md",".agents/skills/add-page.md",".agents/skills/add-component.md",".agents/skills/add-blog-post.md","CLAUDE.md"],"skills":{"AGENTS.md":"# AstroWind Agent Instructions\n\n## Project Overview\n\nAstroWind is a free, open-source website template built with **Astro v7** and **Tailwind CSS v4**. It generates a fully static site optimized for performance, SEO, and accessibility.\n\n**Stack:** Astro v7 | Tailwind CSS v4 | TypeScript 5.9 | MDX | Sharp\n\n## Skills\n\nBefore implementing a project-specific task (disabling the blog, Open Graph images, base paths, CMS, deployments, header customisation…), check `.agents/skills/` for an existing skill and follow it.\n\n## Quick Reference\n\n| Command           | Purpose                             |\n| ----------------- | ----------------------------------- |\n| `npm run dev`     | Start dev server at localhost:4321  |\n| `npm run build`   | Production build to `./dist/`       |\n| `npm run preview` | Preview production build locally    |\n| `npm run check`   | Run astro check + ESLint + Prettier |\n| `npm run fix`     | Auto-fix ESLint + Prettier issues   |\n\n**Node.js requirement:** >= 22.22.3\n\n## Architecture\n\n### Directory Structure\n\n```\nsrc/\n  assets/styles/tailwind.css   # Tailwind v4 config (themes, utilities, plugins)\n  components/\n    common/        # Shared: Image, Metadata, Analytics, ToggleTheme\n    ui/            # Primitives: Button, Form, Headline, Timeline, WidgetWrapper\n    widgets/       # Page sections: Hero, Features, Bento, Pricing, Comparison, FAQs, Team, Gallery…\n    blog/          # Blog: SinglePost, List, Pagination, Tags\n    CustomStyles.astro  # CSS variables for colors and fonts\n  content.config.ts    # Content Collections schema (Astro 5+ location)\n  data/post/           # Blog posts (.md, .mdx)\n  layouts/             # Layout.astro, PageLayout.astro, MarkdownLayout.astro\n  pages/               # File-based routing\n  utils/               # blog.ts, images.ts, permalinks.ts, frontmatter.ts\n  config.yaml          # Site configuration (loaded as virtual module)\n  navigation.ts        # Navigation structure\n  types.d.ts           # TypeScript type definitions\nvendor/integration/    # Custom Astro integration for config loading\n```\n\n### Path Aliases\n\nUse `~/` to import from `src/`:\n\n```typescript\nimport Image from '~/components/common/Image.astro';\nimport { SITE } from 'astrowind:config';\n```\n\n### Configuration System\n\nSite config lives in `src/config.yaml` and is loaded as a Vite virtual module `astrowind:config` by the custom integration in `vendor/integration/`. Exports: `SITE`, `I18N`, `METADATA`, `APP_BLOG`, `UI`, `ANALYTICS`.\n\n## Tailwind CSS v4\n\nConfiguration is CSS-first in `src/assets/styles/tailwind.css`:\n\n- **Theme tokens:** `@theme { --color-primary: var(--aw-color-primary); ... }`\n- **Custom utilities:** `@utility bg-page { ... }`\n- **Dark mode:** Class-based via `@variant dark (&:where(.dark, .dark *))`\n- **Plugins:** `@plugin \"@tailwindcss/typography\"`\n- **Custom variant:** `@custom-variant intersect (&:not([no-intersect]))`\n\nCSS variables for colors/fonts are defined in `src/components/CustomStyles.astro` with light/dark theme variants.\n\nThe Vite plugin `@tailwindcss/vite` is configured in `astro.config.ts` (not as an Astro integration).\n\n### Class Merging\n\nComponents use `twMerge` from `tailwind-merge` v3 for conditional class composition.\n\n## Content Collections\n\nDefined in `src/content.config.ts` using Astro's Content Layer API with `glob()` loader. Posts are in `src/data/post/` as `.md` or `.mdx` files.\n\nPost frontmatter: `title` (required), `publishDate`, `updateDate`, `draft`, `excerpt`, `image`, `category`, `tags`, `author`, `metadata`.\n\n## Component Patterns\n\n- Props extend interfaces from `~/types`\n- Use `class:list` for conditional classes\n- Use `twMerge()` when accepting className overrides\n- Use named slots for layout composition\n- Widget components accept standardized props (see `~/types`)\n\n## Image Handling\n\n`src/components/common/Image.astro` supports:\n\n- Local images via `astro:assets` (optimized by Sharp)\n- Remote images via Unpic CDN\n- Allowed domains (for providers Unpic can't detect, processed by Sharp): `cdn.pixabay.com`\n\nHero images use `loading=\"eager\"` and `fetchpriority=\"high\"`.\n\n## Fonts\n\nFonts are handled by Astro's native **Fonts API**, configured in `astro.config.ts` under the `fonts` key (provider, family, `cssVariable`) and injected via the `<Font />` component in `src/layouts/Layout.astro`. Astro self-hosts, subsets, preloads, and generates metric-adjusted fallbacks. To change the typeface, edit the `fonts` entry and point `--aw-font-*` in `CustomStyles.astro` at the new `cssVariable`.\n\n## Third-party Scripts (Partytown)\n\n`@astrojs/partytown` is wired as an **opt-in** in `astro.config.ts`, gated behind `const hasExternalScripts = false`. Set it to `true` to offload third-party scripts (e.g. Google Analytics via `analytics.vendors.googleAnalytics.partytown`) to a web worker. It is disabled by default so the base template ships no external scripts.\n\n## Content Security Policy\n\nAstro's native CSP is intentionally **not** enabled in this version: it is incompatible with `<ClientRouter />` view transitions (shipped on by default) and would break the arbitrary third-party scripts a template user typically adds. CSP is deferred to AstroWind v2, where the component model (and optional SSR) make it clean and opt-in.\n\n## Verification Checklist\n\nAfter changes, always verify:\n\n1. `npm run build` succeeds\n2. `npm run check` passes (astro check + ESLint + Prettier)\n3. Visual check in browser: homepage, blog, dark mode, mobile menu\n4. Structured data describes the site it is on: the `WebSite` / `Organization` block in `src/pages/index.astro` is built only from `config.yaml`; anything you add there must be true for your site\n",".agents/skills/add-page.md":"# Add a Page\n\n## Steps\n\n1. Create a new `.astro` file in `src/pages/`\n2. Use `PageLayout` for standard pages or `Layout` for custom layouts\n3. Compose the page using widget components from `src/components/widgets/`\n\n## Template\n\n```astro\n---\nimport Layout from '~/layouts/PageLayout.astro';\nimport Hero from '~/components/widgets/Hero.astro';\nimport Features from '~/components/widgets/Features.astro';\n\nconst metadata = {\n  title: 'Page Title',\n  description: 'Page description for SEO',\n};\n---\n\n<Layout metadata={metadata}>\n  <Hero\n    tagline=\"Optional tagline\"\n    title=\"Page Heading\"\n    subtitle=\"Supporting text\"\n    image={{\n      src: '~/assets/images/hero.png',\n      alt: 'Hero image description',\n    }}\n  />\n\n  <Features\n    title=\"Section Title\"\n    items={[\n      { title: 'Feature 1', description: 'Description', icon: 'tabler:star' },\n      { title: 'Feature 2', description: 'Description', icon: 'tabler:rocket' },\n    ]}\n  />\n</Layout>\n```\n\n## Available Widget Components\n\nHero, Features, Content, Steps, Testimonials, FAQs, Stats, Pricing, Brands, CallToAction, Contact, Team\n\n## Notes\n\n- Pages in `src/pages/` are automatically routed by filename\n- Use `PageLayout` (includes Header + Footer) or `Layout` (bare)\n- All widgets accept an `id` prop for anchor links\n- Icons use the `tabler:icon-name` format from `@iconify-json/tabler`\n",".agents/skills/add-component.md":"# Add a Widget Component\n\nBefore writing a new widget, check `use-widgets.md`: the catalogue covers most marketing sections, and a prop or a variant on an existing widget is usually enough.\n\n## Steps\n\n1. Create `src/components/widgets/MyWidget.astro`.\n2. Add a `MyWidget` interface to `src/types.d.ts` that extends `Omit<Headline, 'classes'>, Widget` (or only `Widget` if the section has no headline).\n3. Use the widget on a real page of the demo so it is visible and tested.\n4. Run `npm run build && npm run check` and look at the section in light and dark mode, on desktop and at 375 px.\n\n## Template\n\n```astro\n---\nimport { Icon } from 'astro-icon/components';\nimport Headline from '~/components/ui/Headline.astro';\nimport WidgetWrapper from '~/components/ui/WidgetWrapper.astro';\nimport { getColumnsClass } from '~/utils/utils';\nimport type { MyWidget as Props } from '~/types';\n\nconst {\n  title = await Astro.slots.render('title'),\n  subtitle = await Astro.slots.render('subtitle'),\n  tagline = await Astro.slots.render('tagline'),\n  items = [],\n  columns = 3,\n\n  id,\n  isDark = false,\n  classes = {},\n  bg = await Astro.slots.render('bg'),\n} = Astro.props;\n\nconst columnsClass = getColumnsClass(columns, 'sm:grid-cols-2');\n---\n\n<WidgetWrapper id={id} isDark={isDark} containerClass={`max-w-6xl mx-auto ${classes?.container ?? ''}`} bg={bg}>\n  <Headline title={title} subtitle={subtitle} tagline={tagline} classes={classes?.headline as Record<string, string>} />\n\n  <ul class:list={['grid gap-6 list-none', columnsClass]}>\n    {\n      items.map(({ title: itemTitle, description, icon }) => (\n        <li class=\"intersect-once intersect-quarter motion-safe:md:opacity-0 motion-safe:md:intersect:animate-fade\">\n          {icon && <Icon name={icon} class=\"h-8 w-8 text-primary\" />}\n          {itemTitle && <h3 class=\"text-lg font-bold text-heading\">{itemTitle}</h3>}\n          {description && <p class=\"mt-2 text-muted\" set:html={description} />}\n        </li>\n      ))\n    }\n  </ul>\n</WidgetWrapper>\n```\n\n## Conventions\n\n- `WidgetWrapper` gives spacing, container width, `id`, `isDark` and the `bg` slot; `Headline` renders `tagline`/`title`/`subtitle` and forwards `classes.headline`.\n- Colours through the tokens (`text-heading`, `text-muted`, `text-primary`, `bg-page`, `border-gray-200 dark:border-slate-700`), never hardcoded hex values, so `CustomStyles.astro` keeps working.\n- Images through `~/components/common/Image.astro` with `widths`/`sizes`, and `alt` text. Icons from the Tabler set; verify the name exists in `@iconify-json/tabler/icons.json`.\n- Items with a link render an `<a>` (`const Card = href ? 'a' : 'div'`) rather than a nested button.\n- Animations use the `intersect-*` classes and are wrapped in `motion-safe:`.\n- Interaction, when unavoidable, is a small web component (`<aw-my-widget>` with a `<script>` in the same file, ≤ 40 lines) with a static fallback: `FAQs` uses `<details>`, `Gallery` a `<dialog>`, `Countdown`/`Video`/`StickyCTA` a custom element. Register it with `if (!customElements.get(...))` so view transitions do not redefine it.\n- Add a row to the catalogue in `use-widgets.md`.\n",".agents/skills/add-blog-post.md":"# Add a Blog Post\n\n## Steps\n\n1. Create a new `.md` or `.mdx` file in `src/data/post/`\n2. Add required frontmatter:\n\n```yaml\n---\npublishDate: 2026-01-15T00:00:00Z\ntitle: 'Your Post Title'\nexcerpt: 'One or two sentences, at most 155 characters: it is the meta description and the card text.'\nimage: '~/assets/images/your-image.png'\nimageAlt: 'What the cover image shows'\ncategory: 'tutorials'\ntags:\n  - astro\n  - tailwind\nauthor: 'Author Name'\n---\n```\n\n3. Write content in Markdown (or MDX for component embedding)\n4. Run `npm run build` to verify the post renders correctly\n\n## Frontmatter Fields\n\n| Field         | Required | Description                                                                                                                           |\n| ------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------- |\n| `title`       | Yes      | Post title                                                                                                                            |\n| `publishDate` | No       | ISO 8601 date                                                                                                                         |\n| `updateDate`  | No       | ISO 8601 date; shown as \"Updated\" next to the publish date and sent as `article:modified_time` / `dateModified`                       |\n| `draft`       | No       | Set `true` to hide from listing                                                                                                       |\n| `excerpt`     | No       | Summary for listing pages and the meta description (keep it ≤ 155 characters; longer text is cut at a word boundary for the meta tag) |\n| `image`       | No       | Path to hero image (use `~/` prefix for local)                                                                                        |\n| `imageAlt`    | No       | Alt text of the hero image; leave empty for decorative stock photos                                                                   |\n| `category`    | No       | Single category string                                                                                                                |\n| `tags`        | No       | Array of tag strings                                                                                                                  |\n| `author`      | No       | Author name                                                                                                                           |\n| `metadata`    | No       | Override SEO metadata                                                                                                                 |\n\n## URL Pattern\n\nThe slug is derived from the filename and the URL follows `apps.blog.post.permalink` in `src/config.yaml` (`/%slug%` by default, so `/your-post`; `/blog/%slug%`, `%year%/%month%`, `%category%` are also available).\n\n## What every post gets automatically\n\n- `<title>` with the site template, meta description from `excerpt`, canonical URL, Open Graph and Twitter tags with the cover image, `article:published_time` / `article:modified_time` / `article:section` / `article:tag`.\n- `BlogPosting` and `BreadcrumbList` JSON-LD, a breadcrumb trail, reading time, related posts.\n- A place in the blog list, the category and tag pages, the RSS feed and the sitemap. To keep a post out of search results (a demo or an internal note), add `metadata: { robots: { index: false } }`; the sitemap still lists every page and search engines honour the robots meta tag.\n\n## Notes\n\n- Reading time is calculated automatically via remark plugin\n- Images referenced with `~/` are optimized at build time\n- Use `.mdx` extension to embed Astro components in posts\n","CLAUDE.md":"# Claude Code Configuration\n\nSee [AGENTS.md](./AGENTS.md) for all project documentation and AI agent instructions.\n"},"files":{"AGENTS.md":"# AstroWind Agent Instructions\n\n## Project Overview\n\nAstroWind is a free, open-source website template built with **Astro v7** and **Tailwind CSS v4**. It generates a fully static site optimized for performance, SEO, and accessibility.\n\n**Stack:** Astro v7 | Tailwind CSS v4 | TypeScript 5.9 | MDX | Sharp\n\n## Skills\n\nBefore implementing a project-specific task (disabling the blog, Open Graph images, base paths, CMS, deployments, header customisation…), check `.agents/skills/` for an existing skill and follow it.\n\n## Quick Reference\n\n| Command           | Purpose                             |\n| ----------------- | ----------------------------------- |\n| `npm run dev`     | Start dev server at localhost:4321  |\n| `npm run build`   | Production build to `./dist/`       |\n| `npm run preview` | Preview production build locally    |\n| `npm run check`   | Run astro check + ESLint + Prettier |\n| `npm run fix`     | Auto-fix ESLint + Prettier issues   |\n\n**Node.js requirement:** >= 22.22.3\n\n## Architecture\n\n### Directory Structure\n\n```\nsrc/\n  assets/styles/tailwind.css   # Tailwind v4 config (themes, utilities, plugins)\n  components/\n    common/        # Shared: Image, Metadata, Analytics, ToggleTheme\n    ui/            # Primitives: Button, Form, Headline, Timeline, WidgetWrapper\n    widgets/       # Page sections: Hero, Features, Bento, Pricing, Comparison, FAQs, Team, Gallery…\n    blog/          # Blog: SinglePost, List, Pagination, Tags\n    CustomStyles.astro  # CSS variables for colors and fonts\n  content.config.ts    # Content Collections schema (Astro 5+ location)\n  data/post/           # Blog posts (.md, .mdx)\n  layouts/             # Layout.astro, PageLayout.astro, MarkdownLayout.astro\n  pages/               # File-based routing\n  utils/               # blog.ts, images.ts, permalinks.ts, frontmatter.ts\n  config.yaml          # Site configuration (loaded as virtual module)\n  navigation.ts        # Navigation structure\n  types.d.ts           # TypeScript type definitions\nvendor/integration/    # Custom Astro integration for config loading\n```\n\n### Path Aliases\n\nUse `~/` to import from `src/`:\n\n```typescript\nimport Image from '~/components/common/Image.astro';\nimport { SITE } from 'astrowind:config';\n```\n\n### Configuration System\n\nSite config lives in `src/config.yaml` and is loaded as a Vite virtual module `astrowind:config` by the custom integration in `vendor/integration/`. Exports: `SITE`, `I18N`, `METADATA`, `APP_BLOG`, `UI`, `ANALYTICS`.\n\n## Tailwind CSS v4\n\nConfiguration is CSS-first in `src/assets/styles/tailwind.css`:\n\n- **Theme tokens:** `@theme { --color-primary: var(--aw-color-primary); ... }`\n- **Custom utilities:** `@utility bg-page { ... }`\n- **Dark mode:** Class-based via `@variant dark (&:where(.dark, .dark *))`\n- **Plugins:** `@plugin \"@tailwindcss/typography\"`\n- **Custom variant:** `@custom-variant intersect (&:not([no-intersect]))`\n\nCSS variables for colors/fonts are defined in `src/components/CustomStyles.astro` with light/dark theme variants.\n\nThe Vite plugin `@tailwindcss/vite` is configured in `astro.config.ts` (not as an Astro integration).\n\n### Class Merging\n\nComponents use `twMerge` from `tailwind-merge` v3 for conditional class composition.\n\n## Content Collections\n\nDefined in `src/content.config.ts` using Astro's Content Layer API with `glob()` loader. Posts are in `src/data/post/` as `.md` or `.mdx` files.\n\nPost frontmatter: `title` (required), `publishDate`, `updateDate`, `draft`, `excerpt`, `image`, `category`, `tags`, `author`, `metadata`.\n\n## Component Patterns\n\n- Props extend interfaces from `~/types`\n- Use `class:list` for conditional classes\n- Use `twMerge()` when accepting className overrides\n- Use named slots for layout composition\n- Widget components accept standardized props (see `~/types`)\n\n## Image Handling\n\n`src/components/common/Image.astro` supports:\n\n- Local images via `astro:assets` (optimized by Sharp)\n- Remote images via Unpic CDN\n- Allowed domains (for providers Unpic can't detect, processed by Sharp): `cdn.pixabay.com`\n\nHero images use `loading=\"eager\"` and `fetchpriority=\"high\"`.\n\n## Fonts\n\nFonts are handled by Astro's native **Fonts API**, configured in `astro.config.ts` under the `fonts` key (provider, family, `cssVariable`) and injected via the `<Font />` component in `src/layouts/Layout.astro`. Astro self-hosts, subsets, preloads, and generates metric-adjusted fallbacks. To change the typeface, edit the `fonts` entry and point `--aw-font-*` in `CustomStyles.astro` at the new `cssVariable`.\n\n## Third-party Scripts (Partytown)\n\n`@astrojs/partytown` is wired as an **opt-in** in `astro.config.ts`, gated behind `const hasExternalScripts = false`. Set it to `true` to offload third-party scripts (e.g. Google Analytics via `analytics.vendors.googleAnalytics.partytown`) to a web worker. It is disabled by default so the base template ships no external scripts.\n\n## Content Security Policy\n\nAstro's native CSP is intentionally **not** enabled in this version: it is incompatible with `<ClientRouter />` view transitions (shipped on by default) and would break the arbitrary third-party scripts a template user typically adds. CSP is deferred to AstroWind v2, where the component model (and optional SSR) make it clean and opt-in.\n\n## Verification Checklist\n\nAfter changes, always verify:\n\n1. `npm run build` succeeds\n2. `npm run check` passes (astro check + ESLint + Prettier)\n3. Visual check in browser: homepage, blog, dark mode, mobile menu\n4. Structured data describes the site it is on: the `WebSite` / `Organization` block in `src/pages/index.astro` is built only from `config.yaml`; anything you add there must be true for your site\n",".agents/skills/add-page.md":"# Add a Page\n\n## Steps\n\n1. Create a new `.astro` file in `src/pages/`\n2. Use `PageLayout` for standard pages or `Layout` for custom layouts\n3. Compose the page using widget components from `src/components/widgets/`\n\n## Template\n\n```astro\n---\nimport Layout from '~/layouts/PageLayout.astro';\nimport Hero from '~/components/widgets/Hero.astro';\nimport Features from '~/components/widgets/Features.astro';\n\nconst metadata = {\n  title: 'Page Title',\n  description: 'Page description for SEO',\n};\n---\n\n<Layout metadata={metadata}>\n  <Hero\n    tagline=\"Optional tagline\"\n    title=\"Page Heading\"\n    subtitle=\"Supporting text\"\n    image={{\n      src: '~/assets/images/hero.png',\n      alt: 'Hero image description',\n    }}\n  />\n\n  <Features\n    title=\"Section Title\"\n    items={[\n      { title: 'Feature 1', description: 'Description', icon: 'tabler:star' },\n      { title: 'Feature 2', description: 'Description', icon: 'tabler:rocket' },\n    ]}\n  />\n</Layout>\n```\n\n## Available Widget Components\n\nHero, Features, Content, Steps, Testimonials, FAQs, Stats, Pricing, Brands, CallToAction, Contact, Team\n\n## Notes\n\n- Pages in `src/pages/` are automatically routed by filename\n- Use `PageLayout` (includes Header + Footer) or `Layout` (bare)\n- All widgets accept an `id` prop for anchor links\n- Icons use the `tabler:icon-name` format from `@iconify-json/tabler`\n",".agents/skills/add-component.md":"# Add a Widget Component\n\nBefore writing a new widget, check `use-widgets.md`: the catalogue covers most marketing sections, and a prop or a variant on an existing widget is usually enough.\n\n## Steps\n\n1. Create `src/components/widgets/MyWidget.astro`.\n2. Add a `MyWidget` interface to `src/types.d.ts` that extends `Omit<Headline, 'classes'>, Widget` (or only `Widget` if the section has no headline).\n3. Use the widget on a real page of the demo so it is visible and tested.\n4. Run `npm run build && npm run check` and look at the section in light and dark mode, on desktop and at 375 px.\n\n## Template\n\n```astro\n---\nimport { Icon } from 'astro-icon/components';\nimport Headline from '~/components/ui/Headline.astro';\nimport WidgetWrapper from '~/components/ui/WidgetWrapper.astro';\nimport { getColumnsClass } from '~/utils/utils';\nimport type { MyWidget as Props } from '~/types';\n\nconst {\n  title = await Astro.slots.render('title'),\n  subtitle = await Astro.slots.render('subtitle'),\n  tagline = await Astro.slots.render('tagline'),\n  items = [],\n  columns = 3,\n\n  id,\n  isDark = false,\n  classes = {},\n  bg = await Astro.slots.render('bg'),\n} = Astro.props;\n\nconst columnsClass = getColumnsClass(columns, 'sm:grid-cols-2');\n---\n\n<WidgetWrapper id={id} isDark={isDark} containerClass={`max-w-6xl mx-auto ${classes?.container ?? ''}`} bg={bg}>\n  <Headline title={title} subtitle={subtitle} tagline={tagline} classes={classes?.headline as Record<string, string>} />\n\n  <ul class:list={['grid gap-6 list-none', columnsClass]}>\n    {\n      items.map(({ title: itemTitle, description, icon }) => (\n        <li class=\"intersect-once intersect-quarter motion-safe:md:opacity-0 motion-safe:md:intersect:animate-fade\">\n          {icon && <Icon name={icon} class=\"h-8 w-8 text-primary\" />}\n          {itemTitle && <h3 class=\"text-lg font-bold text-heading\">{itemTitle}</h3>}\n          {description && <p class=\"mt-2 text-muted\" set:html={description} />}\n        </li>\n      ))\n    }\n  </ul>\n</WidgetWrapper>\n```\n\n## Conventions\n\n- `WidgetWrapper` gives spacing, container width, `id`, `isDark` and the `bg` slot; `Headline` renders `tagline`/`title`/`subtitle` and forwards `classes.headline`.\n- Colours through the tokens (`text-heading`, `text-muted`, `text-primary`, `bg-page`, `border-gray-200 dark:border-slate-700`), never hardcoded hex values, so `CustomStyles.astro` keeps working.\n- Images through `~/components/common/Image.astro` with `widths`/`sizes`, and `alt` text. Icons from the Tabler set; verify the name exists in `@iconify-json/tabler/icons.json`.\n- Items with a link render an `<a>` (`const Card = href ? 'a' : 'div'`) rather than a nested button.\n- Animations use the `intersect-*` classes and are wrapped in `motion-safe:`.\n- Interaction, when unavoidable, is a small web component (`<aw-my-widget>` with a `<script>` in the same file, ≤ 40 lines) with a static fallback: `FAQs` uses `<details>`, `Gallery` a `<dialog>`, `Countdown`/`Video`/`StickyCTA` a custom element. Register it with `if (!customElements.get(...))` so view transitions do not redefine it.\n- Add a row to the catalogue in `use-widgets.md`.\n",".agents/skills/add-blog-post.md":"# Add a Blog Post\n\n## Steps\n\n1. Create a new `.md` or `.mdx` file in `src/data/post/`\n2. Add required frontmatter:\n\n```yaml\n---\npublishDate: 2026-01-15T00:00:00Z\ntitle: 'Your Post Title'\nexcerpt: 'One or two sentences, at most 155 characters: it is the meta description and the card text.'\nimage: '~/assets/images/your-image.png'\nimageAlt: 'What the cover image shows'\ncategory: 'tutorials'\ntags:\n  - astro\n  - tailwind\nauthor: 'Author Name'\n---\n```\n\n3. Write content in Markdown (or MDX for component embedding)\n4. Run `npm run build` to verify the post renders correctly\n\n## Frontmatter Fields\n\n| Field         | Required | Description                                                                                                                           |\n| ------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------- |\n| `title`       | Yes      | Post title                                                                                                                            |\n| `publishDate` | No       | ISO 8601 date                                                                                                                         |\n| `updateDate`  | No       | ISO 8601 date; shown as \"Updated\" next to the publish date and sent as `article:modified_time` / `dateModified`                       |\n| `draft`       | No       | Set `true` to hide from listing                                                                                                       |\n| `excerpt`     | No       | Summary for listing pages and the meta description (keep it ≤ 155 characters; longer text is cut at a word boundary for the meta tag) |\n| `image`       | No       | Path to hero image (use `~/` prefix for local)                                                                                        |\n| `imageAlt`    | No       | Alt text of the hero image; leave empty for decorative stock photos                                                                   |\n| `category`    | No       | Single category string                                                                                                                |\n| `tags`        | No       | Array of tag strings                                                                                                                  |\n| `author`      | No       | Author name                                                                                                                           |\n| `metadata`    | No       | Override SEO metadata                                                                                                                 |\n\n## URL Pattern\n\nThe slug is derived from the filename and the URL follows `apps.blog.post.permalink` in `src/config.yaml` (`/%slug%` by default, so `/your-post`; `/blog/%slug%`, `%year%/%month%`, `%category%` are also available).\n\n## What every post gets automatically\n\n- `<title>` with the site template, meta description from `excerpt`, canonical URL, Open Graph and Twitter tags with the cover image, `article:published_time` / `article:modified_time` / `article:section` / `article:tag`.\n- `BlogPosting` and `BreadcrumbList` JSON-LD, a breadcrumb trail, reading time, related posts.\n- A place in the blog list, the category and tag pages, the RSS feed and the sitemap. To keep a post out of search results (a demo or an internal note), add `metadata: { robots: { index: false } }`; the sitemap still lists every page and search engines honour the robots meta tag.\n\n## Notes\n\n- Reading time is calculated automatically via remark plugin\n- Images referenced with `~/` are optimized at build time\n- Use `.mdx` extension to embed Astro components in posts\n","CLAUDE.md":"# Claude Code Configuration\n\nSee [AGENTS.md](./AGENTS.md) for all project documentation and AI agent instructions.\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/arthelokyo/astrowind/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# AstroWind Agent Instructions\n\n## Project Overview\n\nAstroWind is a free, open-source website template built with **Astro v7** and **Tailwind CSS v4**. It generates a fully static site optimized for performance, SEO, and accessibility.\n\n**Stack:** Astro v7 | Tailwind CSS v4 | TypeScript 5.9 | MDX | Sharp\n\n## Skills\n\nBefore implementing a project-specific task (disabling the blog, Open Graph images, base paths, CMS, deployments, header customisation…), check `.agents/skills/` for an existing skill and follow it.\n\n## Quick Reference\n\n| Command           | Purpose                             |\n| ----------------- | ----------------------------------- |\n| `npm run dev`     | Start dev server at localhost:4321  |\n| `npm run build`   | Production build to `./dist/`       |\n| `npm run preview` | Preview production build locally    |\n| `npm run check`   | Run astro check + ESLint + Prettier |\n| `npm run fix`     | Auto-fix ESLint + Prettier issues   |\n\n**Node.js requirement:** >= 22.22.3\n\n## Architecture\n\n### Directory Structure\n\n```\nsrc/\n  assets/styles/tailwind.css   # Tailwind v4 config (themes, utilities, plugins)\n  components/\n    common/        # Shared: Image, Metadata, Analytics, ToggleTheme\n    ui/            # Primitives: Button, Form, Headline, Timeline, WidgetWrapper\n    widgets/       # Page sections: Hero, Features, Bento, Pricing, Comparison, FAQs, Team, Gallery…\n    blog/          # Blog: SinglePost, List, Pagination, Tags\n    CustomStyles.astro  # CSS variables for colors and fonts\n  content.config.ts    # Content Collections schema (Astro 5+ location)\n  data/post/           # Blog posts (.md, .mdx)\n  layouts/             # Layout.astro, PageLayout.astro, MarkdownLayout.astro\n  pages/               # File-based routing\n  utils/               # blog.ts, images.ts, permalinks.ts, frontmatter.ts\n  config.yaml          # Site configuration (loaded as virtual module)\n  navigation.ts        # Navigation structure\n  types.d.ts           # TypeScript type definitions\nvendor/integration/    # Custom Astro integration for config loading\n```\n\n### Path Aliases\n\nUse `~/` to import from `src/`:\n\n```typescript\nimport Image from '~/components/common/Image.astro';\nimport { SITE } from 'astrowind:config';\n```\n\n### Configuration System\n\nSite config lives in `src/config.yaml` and is loaded as a Vite virtual module `astrowind:config` by the custom integration in `vendor/integration/`. Exports: `SITE`, `I18N`, `METADATA`, `APP_BLOG`, `UI`, `ANALYTICS`.\n\n## Tailwind CSS v4\n\nConfiguration is CSS-first in `src/assets/styles/tailwind.css`:\n\n- **Theme tokens:** `@theme { --color-primary: var(--aw-color-primary); ... }`\n- **Custom utilities:** `@utility bg-page { ... }`\n- **Dark mode:** Class-based via `@variant dark (&:where(.dark, .dark *))`\n- **Plugins:** `@plugin \"@tailwindcss/typography\"`\n- **Custom variant:** `@custom-variant intersect (&:not([no-intersect]))`\n\nCSS variables for colors/fonts are defined in `src/components/CustomStyles.astro` with light/dark theme variants.\n\nThe Vite plugin `@tailwindcss/vite` is configured in `astro.config.ts` (not as an Astro integration).\n\n### Class Merging\n\nComponents use `twMerge` from `tailwind-merge` v3 for conditional class composition.\n\n## Content Collections\n\nDefined in `src/content.config.ts` using Astro's Content Layer API with `glob()` loader. Posts are in `src/data/post/` as `.md` or `.mdx` files.\n\nPost frontmatter: `title` (required), `publishDate`, `updateDate`, `draft`, `excerpt`, `image`, `category`, `tags`, `author`, `metadata`.\n\n## Component Patterns\n\n- Props extend interfaces from `~/types`\n- Use `class:list` for conditional classes\n- Use `twMerge()` when accepting className overrides\n- Use named slots for layout composition\n- Widget components accept standardized props (see `~/types`)\n\n## Image Handling\n\n`src/components/common/Image.astro` supports:\n\n- Local images via `astro:assets` (optimized by Sharp)\n- Remote images via Unpic CDN\n- Allowed domains (for providers Unpic can't detect, processed by Sharp): `cdn.pixabay.com`\n\nHero images use `loading=\"eager\"` and `fetchpriority=\"high\"`.\n\n## Fonts\n\nFonts are handled by Astro's native **Fonts API**, configured in `astro.config.ts` under the `fonts` key (provider, family, `cssVariable`) and injected via the `<Font />` component in `src/layouts/Layout.astro`. Astro self-hosts, subsets, preloads, and generates metric-adjusted fallbacks. To change the typeface, edit the `fonts` entry and point `--aw-font-*` in `CustomStyles.astro` at the new `cssVariable`.\n\n## Third-party Scripts (Partytown)\n\n`@astrojs/partytown` is wired as an **opt-in** in `astro.config.ts`, gated behind `const hasExternalScripts = false`. Set it to `true` to offload third-party scripts (e.g. Google Analytics via `analytics.vendors.googleAnalytics.partytown`) to a web worker. It is disabled by default so the base template ships no external scripts.\n\n## Content Security Policy\n\nAstro's native CSP is intentionally **not** enabled in this version: it is incompatible with `<ClientRouter />` view transitions (shipped on by default) and would break the arbitrary third-party scripts a template user typically adds. CSP is deferred to AstroWind v2, where the component model (and optional SSR) make it clean and opt-in.\n\n## Verification Checklist\n\nAfter changes, always verify:\n\n1. `npm run build` succeeds\n2. `npm run check` passes (astro check + ESLint + Prettier)\n3. Visual check in browser: homepage, blog, dark mode, mobile menu\n4. Structured data describes the site it is on: the `WebSite` / `Organization` block in `src/pages/index.astro` is built only from `config.yaml`; anything you add there must be true for your site\n","isInternal":false,"tokens":1384,"sizeBytes":5675},{"name":"add-blog-post.md","path":".agents/skills/add-blog-post.md","rawUrl":"https://raw.githubusercontent.com/arthelokyo/astrowind/HEAD/.agents/skills/add-blog-post.md","title":"Skills Skill","category":"anthropic-skill","format":"markdown","content":"# Add a Blog Post\n\n## Steps\n\n1. Create a new `.md` or `.mdx` file in `src/data/post/`\n2. Add required frontmatter:\n\n```yaml\n---\npublishDate: 2026-01-15T00:00:00Z\ntitle: 'Your Post Title'\nexcerpt: 'One or two sentences, at most 155 characters: it is the meta description and the card text.'\nimage: '~/assets/images/your-image.png'\nimageAlt: 'What the cover image shows'\ncategory: 'tutorials'\ntags:\n  - astro\n  - tailwind\nauthor: 'Author Name'\n---\n```\n\n3. Write content in Markdown (or MDX for component embedding)\n4. Run `npm run build` to verify the post renders correctly\n\n## Frontmatter Fields\n\n| Field         | Required | Description                                                                                                                           |\n| ------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------- |\n| `title`       | Yes      | Post title                                                                                                                            |\n| `publishDate` | No       | ISO 8601 date                                                                                                                         |\n| `updateDate`  | No       | ISO 8601 date; shown as \"Updated\" next to the publish date and sent as `article:modified_time` / `dateModified`                       |\n| `draft`       | No       | Set `true` to hide from listing                                                                                                       |\n| `excerpt`     | No       | Summary for listing pages and the meta description (keep it ≤ 155 characters; longer text is cut at a word boundary for the meta tag) |\n| `image`       | No       | Path to hero image (use `~/` prefix for local)                                                                                        |\n| `imageAlt`    | No       | Alt text of the hero image; leave empty for decorative stock photos                                                                   |\n| `category`    | No       | Single category string                                                                                                                |\n| `tags`        | No       | Array of tag strings                                                                                                                  |\n| `author`      | No       | Author name                                                                                                                           |\n| `metadata`    | No       | Override SEO metadata                                                                                                                 |\n\n## URL Pattern\n\nThe slug is derived from the filename and the URL follows `apps.blog.post.permalink` in `src/config.yaml` (`/%slug%` by default, so `/your-post`; `/blog/%slug%`, `%year%/%month%`, `%category%` are also available).\n\n## What every post gets automatically\n\n- `<title>` with the site template, meta description from `excerpt`, canonical URL, Open Graph and Twitter tags with the cover image, `article:published_time` / `article:modified_time` / `article:section` / `article:tag`.\n- `BlogPosting` and `BreadcrumbList` JSON-LD, a breadcrumb trail, reading time, related posts.\n- A place in the blog list, the category and tag pages, the RSS feed and the sitemap. To keep a post out of search results (a demo or an internal note), add `metadata: { robots: { index: false } }`; the sitemap still lists every page and search engines honour the robots meta tag.\n\n## Notes\n\n- Reading time is calculated automatically via remark plugin\n- Images referenced with `~/` are optimized at build time\n- Use `.mdx` extension to embed Astro components in posts\n","isInternal":false,"tokens":684,"sizeBytes":3801},{"name":"add-component.md","path":".agents/skills/add-component.md","rawUrl":"https://raw.githubusercontent.com/arthelokyo/astrowind/HEAD/.agents/skills/add-component.md","title":"Skills Skill","category":"anthropic-skill","format":"markdown","content":"# Add a Widget Component\n\nBefore writing a new widget, check `use-widgets.md`: the catalogue covers most marketing sections, and a prop or a variant on an existing widget is usually enough.\n\n## Steps\n\n1. Create `src/components/widgets/MyWidget.astro`.\n2. Add a `MyWidget` interface to `src/types.d.ts` that extends `Omit<Headline, 'classes'>, Widget` (or only `Widget` if the section has no headline).\n3. Use the widget on a real page of the demo so it is visible and tested.\n4. Run `npm run build && npm run check` and look at the section in light and dark mode, on desktop and at 375 px.\n\n## Template\n\n```astro\n---\nimport { Icon } from 'astro-icon/components';\nimport Headline from '~/components/ui/Headline.astro';\nimport WidgetWrapper from '~/components/ui/WidgetWrapper.astro';\nimport { getColumnsClass } from '~/utils/utils';\nimport type { MyWidget as Props } from '~/types';\n\nconst {\n  title = await Astro.slots.render('title'),\n  subtitle = await Astro.slots.render('subtitle'),\n  tagline = await Astro.slots.render('tagline'),\n  items = [],\n  columns = 3,\n\n  id,\n  isDark = false,\n  classes = {},\n  bg = await Astro.slots.render('bg'),\n} = Astro.props;\n\nconst columnsClass = getColumnsClass(columns, 'sm:grid-cols-2');\n---\n\n<WidgetWrapper id={id} isDark={isDark} containerClass={`max-w-6xl mx-auto ${classes?.container ?? ''}`} bg={bg}>\n  <Headline title={title} subtitle={subtitle} tagline={tagline} classes={classes?.headline as Record<string, string>} />\n\n  <ul class:list={['grid gap-6 list-none', columnsClass]}>\n    {\n      items.map(({ title: itemTitle, description, icon }) => (\n        <li class=\"intersect-once intersect-quarter motion-safe:md:opacity-0 motion-safe:md:intersect:animate-fade\">\n          {icon && <Icon name={icon} class=\"h-8 w-8 text-primary\" />}\n          {itemTitle && <h3 class=\"text-lg font-bold text-heading\">{itemTitle}</h3>}\n          {description && <p class=\"mt-2 text-muted\" set:html={description} />}\n        </li>\n      ))\n    }\n  </ul>\n</WidgetWrapper>\n```\n\n## Conventions\n\n- `WidgetWrapper` gives spacing, container width, `id`, `isDark` and the `bg` slot; `Headline` renders `tagline`/`title`/`subtitle` and forwards `classes.headline`.\n- Colours through the tokens (`text-heading`, `text-muted`, `text-primary`, `bg-page`, `border-gray-200 dark:border-slate-700`), never hardcoded hex values, so `CustomStyles.astro` keeps working.\n- Images through `~/components/common/Image.astro` with `widths`/`sizes`, and `alt` text. Icons from the Tabler set; verify the name exists in `@iconify-json/tabler/icons.json`.\n- Items with a link render an `<a>` (`const Card = href ? 'a' : 'div'`) rather than a nested button.\n- Animations use the `intersect-*` classes and are wrapped in `motion-safe:`.\n- Interaction, when unavoidable, is a small web component (`<aw-my-widget>` with a `<script>` in the same file, ≤ 40 lines) with a static fallback: `FAQs` uses `<details>`, `Gallery` a `<dialog>`, `Countdown`/`Video`/`StickyCTA` a custom element. Register it with `if (!customElements.get(...))` so view transitions do not redefine it.\n- Add a row to the catalogue in `use-widgets.md`.\n","isInternal":false,"tokens":825,"sizeBytes":3129},{"name":"add-page.md","path":".agents/skills/add-page.md","rawUrl":"https://raw.githubusercontent.com/arthelokyo/astrowind/HEAD/.agents/skills/add-page.md","title":"Skills Skill","category":"anthropic-skill","format":"markdown","content":"# Add a Page\n\n## Steps\n\n1. Create a new `.astro` file in `src/pages/`\n2. Use `PageLayout` for standard pages or `Layout` for custom layouts\n3. Compose the page using widget components from `src/components/widgets/`\n\n## Template\n\n```astro\n---\nimport Layout from '~/layouts/PageLayout.astro';\nimport Hero from '~/components/widgets/Hero.astro';\nimport Features from '~/components/widgets/Features.astro';\n\nconst metadata = {\n  title: 'Page Title',\n  description: 'Page description for SEO',\n};\n---\n\n<Layout metadata={metadata}>\n  <Hero\n    tagline=\"Optional tagline\"\n    title=\"Page Heading\"\n    subtitle=\"Supporting text\"\n    image={{\n      src: '~/assets/images/hero.png',\n      alt: 'Hero image description',\n    }}\n  />\n\n  <Features\n    title=\"Section Title\"\n    items={[\n      { title: 'Feature 1', description: 'Description', icon: 'tabler:star' },\n      { title: 'Feature 2', description: 'Description', icon: 'tabler:rocket' },\n    ]}\n  />\n</Layout>\n```\n\n## Available Widget Components\n\nHero, Features, Content, Steps, Testimonials, FAQs, Stats, Pricing, Brands, CallToAction, Contact, Team\n\n## Notes\n\n- Pages in `src/pages/` are automatically routed by filename\n- Use `PageLayout` (includes Header + Footer) or `Layout` (bare)\n- All widgets accept an `id` prop for anchor links\n- Icons use the `tabler:icon-name` format from `@iconify-json/tabler`\n","isInternal":false,"tokens":344,"sizeBytes":1355},{"name":"CLAUDE.md","path":"CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/arthelokyo/astrowind/HEAD/CLAUDE.md","title":"Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"# Claude Code Configuration\n\nSee [AGENTS.md](./AGENTS.md) for all project documentation and AI agent instructions.\n","isInternal":false,"tokens":25,"sizeBytes":115}],"systemPromptSnippet":"<yakaai_skills repo=\"arthelokyo/astrowind\">\n<!-- File: AGENTS.md (Tokens: ~1384 | Category: root-instruction) -->\n# AstroWind Agent Instructions\n\n## Project Overview\n\nAstroWind is a free, open-source website template built with **Astro v7** and **Tailwind CSS v4**. It generates a fully static site optimized for performance, SEO, and accessibility.\n\n**Stack:** Astro v7 | Tailwind CSS v4 | TypeScript 5.9 | MDX | Sharp\n\n## Skills\n\nBefore implementing a project-specific task (disabling the blog, Open Graph images, base paths, CMS, deployments, header customisation…), check `.agents/skills/` for an existing skill and follow it.\n\n## Quick Reference\n\n| Command           | Purpose                             |\n| ----------------- | ----------------------------------- |\n| `npm run dev`     | Start dev server at localhost:4321  |\n| `npm run build`   | Production build to `./dist/`       |\n| `npm run preview` | Preview production build locally    |\n| `npm run check`   | Run astro check + ESLint + Prettier |\n| `npm run fix`     | Auto-fix ESLint + Prettier issues   |\n\n**Node.js requirement:** >= 22.22.3\n\n## Architecture\n\n### Directory Structure\n\n```\nsrc/\n  assets/styles/tailwind.css   # Tailwind v4 config (themes, utilities, plugins)\n  components/\n    common/        # Shared: Image, Metadata, Analytics, ToggleTheme\n    ui/            # Primitives: Button, Form, Headline, Timeline, WidgetWrapper\n    widgets/       # Page sections: Hero, Features, Bento, Pricing, Comparison, FAQs, Team, Gallery…\n    blog/          # Blog: SinglePost, List, Pagination, Tags\n    CustomStyles.astro  # CSS variables for colors and fonts\n  content.config.ts    # Content Collections schema (Astro 5+ location)\n  data/post/           # Blog posts (.md, .mdx)\n  layouts/             # Layout.astro, PageLayout.astro, MarkdownLayout.astro\n  pages/               # File-based routing\n  utils/               # blog.ts, images.ts, permalinks.ts, frontmatter.ts\n  config.yaml          # Site configuration (loaded as virtual module)\n  navigation.ts        # Navigation structure\n  types.d.ts           # TypeScript type definitions\nvendor/integration/    # Custom Astro integration for config loading\n```\n\n### Path Aliases\n\nUse `~/` to import from `src/`:\n\n```typescript\nimport Image from '~/components/common/Image.astro';\nimport { SITE } from 'astrowind:config';\n```\n\n### Configuration System\n\nSite config lives in `src/config.yaml` and is loaded as a Vite virtual module `astrowind:config` by the custom integration in `vendor/integration/`. Exports: `SITE`, `I18N`, `METADATA`, `APP_BLOG`, `UI`, `ANALYTICS`.\n\n## Tailwind CSS v4\n\nConfiguration is CSS-first in `src/assets/styles/tailwind.css`:\n\n- **Theme tokens:** `@theme { --color-primary: var(--aw-color-primary); ... }`\n- **Custom utilities:** `@utility bg-page { ... }`\n- **Dark mode:** Class-based via `@variant dark (&:where(.dark, .dark *))`\n- **Plugins:** `@plugin \"@tailwindcss/typography\"`\n- **Custom variant:** `@custom-variant intersect (&:not([no-intersect]))`\n\nCSS variables for colors/fonts are defined in `src/components/CustomStyles.astro` with light/dark theme variants.\n\nThe Vite plugin `@tailwindcss/vite` is configured in `astro.config.ts` (not as an Astro integration).\n\n### Class Merging\n\nComponents use `twMerge` from `tailwind-merge` v3 for conditional class composition.\n\n## Content Collections\n\nDefined in `src/content.config.ts` using Astro's Content Layer API with `glob()` loader. Posts are in `src/data/post/` as `.md` or `.mdx` files.\n\nPost frontmatter: `title` (required), `publishDate`, `updateDate`, `draft`, `excerpt`, `image`, `category`, `tags`, `author`, `metadata`.\n\n## Component Patterns\n\n- Props extend interfaces from `~/types`\n- Use `class:list` for conditional classes\n- Use `twMerge()` when accepting className overrides\n- Use named slots for layout composition\n- Widget components accept standardized props (see `~/types`)\n\n## Image Handling\n\n`src/components/common/Image.astro` supports:\n\n- Local images via `astro:assets` (optimized by Sharp)\n- Remote images via Unpic CDN\n- Allowed domains (for providers Unpic can't detect, processed by Sharp): `cdn.pixabay.com`\n\nHero images use `loading=\"eager\"` and `fetchpriority=\"high\"`.\n\n## Fonts\n\nFonts are handled by Astro's native **Fonts API**, configured in `astro.config.ts` under the `fonts` key (provider, family, `cssVariable`) and injected via the `<Font />` component in `src/layouts/Layout.astro`. Astro self-hosts, subsets, preloads, and generates metric-adjusted fallbacks. To change the typeface, edit the `fonts` entry and point `--aw-font-*` in `CustomStyles.astro` at the new `cssVariable`.\n\n## Third-party Scripts (Partytown)\n\n`@astrojs/partytown` is wired as an **opt-in** in `astro.config.ts`, gated behind `const hasExternalScripts = false`. Set it to `true` to offload third-party scripts (e.g. Google Analytics via `analytics.vendors.googleAnalytics.partytown`) to a web worker. It is disabled by default so the base template ships no external scripts.\n\n## Content Security Policy\n\nAstro's native CSP is intentionally **not** enabled in this version: it is incompatible with `<ClientRouter />` view transitions (shipped on by default) and would break the arbitrary third-party scripts a template user typically adds. CSP is deferred to AstroWind v2, where the component model (and optional SSR) make it clean and opt-in.\n\n## Verification Checklist\n\nAfter changes, always verify:\n\n1. `npm run build` succeeds\n2. `npm run check` passes (astro check + ESLint + Prettier)\n3. Visual check in browser: homepage, blog, dark mode, mobile menu\n4. Structured data describes the site it is on: the `WebSite` / `Organization` block in `src/pages/index.astro` is built only from `config.yaml`; anything you add there must be true for your site\n\n<!-- File: .agents/skills/add-blog-post.md (Tokens: ~684 | Category: anthropic-skill) -->\n# Add a Blog Post\n\n## Steps\n\n1. Create a new `.md` or `.mdx` file in `src/data/post/`\n2. Add required frontmatter:\n\n```yaml\n---\npublishDate: 2026-01-15T00:00:00Z\ntitle: 'Your Post Title'\nexcerpt: 'One or two sentences, at most 155 characters: it is the meta description and the card text.'\nimage: '~/assets/images/your-image.png'\nimageAlt: 'What the cover image shows'\ncategory: 'tutorials'\ntags:\n  - astro\n  - tailwind\nauthor: 'Author Name'\n---\n```\n\n3. Write content in Markdown (or MDX for component embedding)\n4. Run `npm run build` to verify the post renders correctly\n\n## Frontmatter Fields\n\n| Field         | Required | Description                                                                                                                           |\n| ------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------- |\n| `title`       | Yes      | Post title                                                                                                                            |\n| `publishDate` | No       | ISO 8601 date                                                                                                                         |\n| `updateDate`  | No       | ISO 8601 date; shown as \"Updated\" next to the publish date and sent as `article:modified_time` / `dateModified`                       |\n| `draft`       | No       | Set `true` to hide from listing                                                                                                       |\n| `excerpt`     | No       | Summary for listing pages and the meta description (keep it ≤ 155 characters; longer text is cut at a word boundary for the meta tag) |\n| `image`       | No       | Path to hero image (use `~/` prefix for local)                                                                                        |\n| `imageAlt`    | No       | Alt text of the hero image; leave empty for decorative stock photos                                                                   |\n| `category`    | No       | Single category string                                                                                                                |\n| `tags`        | No       | Array of tag strings                                                                                                                  |\n| `author`      | No       | Author name                                                                                                                           |\n| `metadata`    | No       | Override SEO metadata                                                                                                                 |\n\n## URL Pattern\n\nThe slug is derived from the filename and the URL follows `apps.blog.post.permalink` in `src/config.yaml` (`/%slug%` by default, so `/your-post`; `/blog/%slug%`, `%year%/%month%`, `%category%` are also available).\n\n## What every post gets automatically\n\n- `<title>` with the site template, meta description from `excerpt`, canonical URL, Open Graph and Twitter tags with the cover image, `article:published_time` / `article:modified_time` / `article:section` / `article:tag`.\n- `BlogPosting` and `BreadcrumbList` JSON-LD, a breadcrumb trail, reading time, related posts.\n- A place in the blog list, the category and tag pages, the RSS feed and the sitemap. To keep a post out of search results (a demo or an internal note), add `metadata: { robots: { index: false } }`; the sitemap still lists every page and search engines honour the robots meta tag.\n\n## Notes\n\n- Reading time is calculated automatically via remark plugin\n- Images referenced with `~/` are optimized at build time\n- Use `.mdx` extension to embed Astro components in posts\n\n<!-- File: .agents/skills/add-component.md (Tokens: ~825 | Category: anthropic-skill) -->\n# Add a Widget Component\n\nBefore writing a new widget, check `use-widgets.md`: the catalogue covers most marketing sections, and a prop or a variant on an existing widget is usually enough.\n\n## Steps\n\n1. Create `src/components/widgets/MyWidget.astro`.\n2. Add a `MyWidget` interface to `src/types.d.ts` that extends `Omit<Headline, 'classes'>, Widget` (or only `Widget` if the section has no headline).\n3. Use the widget on a real page of the demo so it is visible and tested.\n4. Run `npm run build && npm run check` and look at the section in light and dark mode, on desktop and at 375 px.\n\n## Template\n\n```astro\n---\nimport { Icon } from 'astro-icon/components';\nimport Headline from '~/components/ui/Headline.astro';\nimport WidgetWrapper from '~/components/ui/WidgetWrapper.astro';\nimport { getColumnsClass } from '~/utils/utils';\nimport type { MyWidget as Props } from '~/types';\n\nconst {\n  title = await Astro.slots.render('title'),\n  subtitle = await Astro.slots.render('subtitle'),\n  tagline = await Astro.slots.render('tagline'),\n  items = [],\n  columns = 3,\n\n  id,\n  isDark = false,\n  classes = {},\n  bg = await Astro.slots.render('bg'),\n} = Astro.props;\n\nconst columnsClass = getColumnsClass(columns, 'sm:grid-cols-2');\n---\n\n<WidgetWrapper id={id} isDark={isDark} containerClass={`max-w-6xl mx-auto ${classes?.container ?? ''}`} bg={bg}>\n  <Headline title={title} subtitle={subtitle} tagline={tagline} classes={classes?.headline as Record<string, string>} />\n\n  <ul class:list={['grid gap-6 list-none', columnsClass]}>\n    {\n      items.map(({ title: itemTitle, description, icon }) => (\n        <li class=\"intersect-once intersect-quarter motion-safe:md:opacity-0 motion-safe:md:intersect:animate-fade\">\n          {icon && <Icon name={icon} class=\"h-8 w-8 text-primary\" />}\n          {itemTitle && <h3 class=\"text-lg font-bold text-heading\">{itemTitle}</h3>}\n          {description && <p class=\"mt-2 text-muted\" set:html={description} />}\n        </li>\n      ))\n    }\n  </ul>\n</WidgetWrapper>\n```\n\n## Conventions\n\n- `WidgetWrapper` gives spacing, container width, `id`, `isDark` and the `bg` slot; `Headline` renders `tagline`/`title`/`subtitle` and forwards `classes.headline`.\n- Colours through the tokens (`text-heading`, `text-muted`, `text-primary`, `bg-page`, `border-gray-200 dark:border-slate-700`), never hardcoded hex values, so `CustomStyles.astro` keeps working.\n- Images through `~/components/common/Image.astro` with `widths`/`sizes`, and `alt` text. Icons from the Tabler set; verify the name exists in `@iconify-json/tabler/icons.json`.\n- Items with a link render an `<a>` (`const Card = href ? 'a' : 'div'`) rather than a nested button.\n- Animations use the `intersect-*` classes and are wrapped in `motion-safe:`.\n- Interaction, when unavoidable, is a small web component (`<aw-my-widget>` with a `<script>` in the same file, ≤ 40 lines) with a static fallback: `FAQs` uses `<details>`, `Gallery` a `<dialog>`, `Countdown`/`Video`/`StickyCTA` a custom element. Register it with `if (!customElements.get(...))` so view transitions do not redefine it.\n- Add a row to the catalogue in `use-widgets.md`.\n\n<!-- File: .agents/skills/add-page.md (Tokens: ~344 | Category: anthropic-skill) -->\n# Add a Page\n\n## Steps\n\n1. Create a new `.astro` file in `src/pages/`\n2. Use `PageLayout` for standard pages or `Layout` for custom layouts\n3. Compose the page using widget components from `src/components/widgets/`\n\n## Template\n\n```astro\n---\nimport Layout from '~/layouts/PageLayout.astro';\nimport Hero from '~/components/widgets/Hero.astro';\nimport Features from '~/components/widgets/Features.astro';\n\nconst metadata = {\n  title: 'Page Title',\n  description: 'Page description for SEO',\n};\n---\n\n<Layout metadata={metadata}>\n  <Hero\n    tagline=\"Optional tagline\"\n    title=\"Page Heading\"\n    subtitle=\"Supporting text\"\n    image={{\n      src: '~/assets/images/hero.png',\n      alt: 'Hero image description',\n    }}\n  />\n\n  <Features\n    title=\"Section Title\"\n    items={[\n      { title: 'Feature 1', description: 'Description', icon: 'tabler:star' },\n      { title: 'Feature 2', description: 'Description', icon: 'tabler:rocket' },\n    ]}\n  />\n</Layout>\n```\n\n## Available Widget Components\n\nHero, Features, Content, Steps, Testimonials, FAQs, Stats, Pricing, Brands, CallToAction, Contact, Team\n\n## Notes\n\n- Pages in `src/pages/` are automatically routed by filename\n- Use `PageLayout` (includes Header + Footer) or `Layout` (bare)\n- All widgets accept an `id` prop for anchor links\n- Icons use the `tabler:icon-name` format from `@iconify-json/tabler`\n\n<!-- File: CLAUDE.md (Tokens: ~25 | Category: claude-rule) -->\n# Claude Code Configuration\n\nSee [AGENTS.md](./AGENTS.md) for all project documentation and AI agent instructions.\n</yakaai_skills>"}