{"id":34601034,"url":"https://github.com/virtuslab-open-source/astro-strapi-blocks","last_synced_at":"2026-04-26T14:01:04.634Z","repository":{"id":290770228,"uuid":"975403737","full_name":"VirtusLab-Open-Source/astro-strapi-blocks","owner":"VirtusLab-Open-Source","description":"Astro blocks for Strapi Rich Text Block field","archived":false,"fork":false,"pushed_at":"2026-04-22T16:15:08.000Z","size":761,"stargazers_count":19,"open_issues_count":8,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-04-22T18:15:36.030Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://astrostrapi.io","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/VirtusLab-Open-Source.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-04-30T08:59:36.000Z","updated_at":"2026-04-22T16:13:55.000Z","dependencies_parsed_at":"2025-04-30T13:58:02.005Z","dependency_job_id":"07a137cd-54db-4c2a-a2bb-368b4f03cdb1","html_url":"https://github.com/VirtusLab-Open-Source/astro-strapi-blocks","commit_stats":null,"previous_names":["virtuslab-open-source/astro-strapi-blocks"],"tags_count":18,"template":false,"template_full_name":null,"purl":"pkg:github/VirtusLab-Open-Source/astro-strapi-blocks","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VirtusLab-Open-Source%2Fastro-strapi-blocks","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VirtusLab-Open-Source%2Fastro-strapi-blocks/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VirtusLab-Open-Source%2Fastro-strapi-blocks/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VirtusLab-Open-Source%2Fastro-strapi-blocks/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/VirtusLab-Open-Source","download_url":"https://codeload.github.com/VirtusLab-Open-Source/astro-strapi-blocks/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VirtusLab-Open-Source%2Fastro-strapi-blocks/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32299644,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-26T09:34:17.070Z","status":"ssl_error","status_checked_at":"2026-04-26T09:34:00.993Z","response_time":129,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-12-24T12:46:11.729Z","updated_at":"2026-04-26T14:01:04.621Z","avatar_url":"https://github.com/VirtusLab-Open-Source.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\" style=\"max-width: 10rem; margin: 0 auto\"\u003e\n  \u003cimg style=\"width: 150px; height: auto;\" src=\"https://www.sensinum.com/img/open-source/strapi-astro-blocks/logo.png\" alt=\"Logo - Strapi Astro Blocks\" /\u003e\n\u003c/div\u003e\n\u003cdiv align=\"center\"\u003e\n  \u003ch1\u003eAstro Strapi Blocks\u003c/h1\u003e\n  \u003cp\u003eAstro Components package for Strapi 5 Blocks Field integration\u003c/p\u003e\n  \u003ca href=\"https://www.npmjs.org/package/@sensinum/astro-strapi-blocks\"\u003e\n    \u003cimg alt=\"GitHub package.json version\" src=\"https://img.shields.io/github/package-json/v/VirtusLab-Open-Source/astro-strapi-blocks?label=npm\u0026logo=npm\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.org/package/@sensinum/astro-strapi-blocks\"\u003e\n    \u003cimg src=\"https://img.shields.io/npm/dm/%40sensinum%2Fastro-strapi-blocks.svg\" alt=\"Monthly download on NPM\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://circleci.com/gh/VirtusLab-Open-Source/astro-strapi-blocks\"\u003e\n    \u003cimg src=\"https://circleci.com/gh/VirtusLab-Open-Source/astro-strapi-blocks.svg?style=shield\" alt=\"CircleCI\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://codecov.io/gh/VirtusLab-Open-Source/astro-strapi-blocks\"\u003e\n    \u003cimg src=\"https://codecov.io/gh/VirtusLab-Open-Source/astro-strapi-blocks/coverage.svg?branch=main\" alt=\"codecov.io\" /\u003e\n  \u003c/a\u003e\n\u003c/div\u003e\n\n---\n\n## Table of Contents\n\n- 📋 [Requirements](#requirements)\n- 📦 [Installation](#installation)\n- 🚀 [Features](#features)\n- 🤖 [AI-Native support](#ai-native-support)\n- 🖥️ [Usage](#usage)\n- ⚙️ [Configuration](#configuration)\n- 🔧 [Development](#development)\n- 🤝 [Contributing](#contributing)\n- 📄 [License](#license)\n\n## 📋 Requirements\n\n- Astro ^5.5.0\n\n## 📦 Installation\n\n```bash\nyarn add @sensinum/astro-strapi-blocks@latest\n```\n\n```bash\nnpm install @sensinum/astro-strapi-blocks@latest\n```\n\n## 🚀 Features\n\n- ✨ Comprehensive support for Strapi 5 Blocks Field with built-in types:\n  - 📌 Headers (H1 - H6)\n  - 📝 Paragraph with formatting (italic, bold, underline, strikethrough, link)\n  - 📑 Quote with formatting (italic, bold, underline, strikethrough, link)\n  - 📋 List (ordered and unordered, nested lists with per-level `indent` theme)\n  - 💻 Code blocks\n  - 🖼️ Image blocks\n- 🎨 Flexible block class configuration for custom styling\n- 🔄 Custom block components support:\n  - 🎯 Override default block rendering\n  - ⚡ Full control over block output\n- 🛠️ TypeScript support with full type definitions\n\n## 🤖 AI-Native support\n\nThe repository includes agent-oriented materials so any coding assistant (IDE agents, CLIs, or models with project context) can apply consistent patterns for **integrating** `StrapiBlocks`, **theming** with `extend` / `overwrite`, **wiring Strapi data** into Astro, and **custom block** overrides.\n\n| Resource | Path | Purpose |\n|----------|------|---------|\n| Agent overview | [`.ai/AGENTS.md`](.ai/AGENTS.md) | Entry point: where to look and how to use the skill in tooling |\n| Agent skill | [`.ai/astro-strapi-blocks/SKILL.md`](.ai/astro-strapi-blocks/SKILL.md) | Step-by-step workflow, checklist, and conventions |\n| Quick reference | [`.ai/astro-strapi-blocks/reference.md`](.ai/astro-strapi-blocks/reference.md) | Theme paths and merge behavior |\n| Cursor rules | [`.cursor/rules/astro-strapi-blocks.mdc`](.cursor/rules/astro-strapi-blocks.mdc) | Project rules for `.astro` / `.ts` when using Cursor |\n\n**In another repo:** copy the `.ai/` folder (and optionally `.cursor/rules/`) into your app, or point your agent at this package’s `README` plus your local copy of `.ai/`. If you use **Cursor** and want the skill in the default skills location, symlink or copy `.ai/astro-strapi-blocks/` to `.cursor/skills/astro-strapi-blocks/`.\n\n## 🖥️ Usage\n\n```astro\n---\nimport { StrapiBlocks } from '@sensinum/astro-strapi-blocks';\n---\n\n\u003cStrapiBlocks \n  data={strapiBlockData}\n  class=\"custom-class\"\n  blocks={{\n    code: CustomCodeBlock,\n    heading: CustomHeadingBlock,\n    paragraph: CustomParagraphBlock\n  }}\n  theme={{\n    extend: { // 'extend' and/or 'overwrite'\n      paragraph: {\n        block: ['custom-paragraph-class'],\n        strong: ['custom-strong-class'],\n        italic: ['custom-em-class'],\n        link: ['custom-link-class']\n      },\n      heading: {\n        block: ['custom-heading-class']\n      },\n      list: {\n        block: ['custom-list-class']\n      },\n      quote: {\n        block: ['custom-quote-class']\n      },\n      code: {\n        block: ['custom-code-class']\n      },\n      image: {\n        block: ['custom-image-class']\n      }\n    }\n  }}\n/\u003e\n```\n\n## ⚙️ Configuration\n\n### Properties\n\n| Property    | Type     | Description |\n|------------|----------|-------------|\n| `data`     | `StrapiBlockField` | Required. The Strapi block data to render. This should be the raw block data from your Strapi API response. |\n| `class`    | `string` | Optional. Additional CSS classes to apply to the component wrapper. |\n| `theme`    | `StrapiBlockUserTheme` | Optional. Theme configuration for blocks. Allows for extending or overwriting default styles. |\n| `blocks`   | `Record\u003cstring, AstroComponent\u003e` | Optional. Custom components for specific block types. Use this to override default block rendering. Example: `{ code: CustomCodeBlock }` |\n\n### Theme Configuration\n\nThe `theme` property allows you to customize the styling of different block types and their nested elements. You can either extend the default theme or completely overwrite it. Here's a detailed breakdown of the configuration options:\n\n```typescript\ntype StrapiBlockUserTheme = {\n  extend?: {\n    block?: string[];\n    heading?: {\n      block?: string[];\n      h1?: string[];\n      h2?: string[];\n      h3?: string[];\n      h4?: string[];\n      h5?: string[];\n      h6?: string[];\n      content: {\n        block?: string[];\n        span?: string[];\n        strong?: string[];\n        italic?: string[];\n        underline?: string[];\n        strikethrough?: string[];\n        link?: string[];\n      } \n    };\n    paragraph?: {\n      block?: string[];\n      span?: string[];\n      strong?: string[];\n      italic?: string[];\n      underline?: string[];\n      strikethrough?: string[];\n      link?: string[];\n    };\n    quote?: {\n      block?: string[];\n      span?: string[];\n      strong?: string[];\n      italic?: string[];\n      underline?: string[];\n      strikethrough?: string[];\n      link?: string[];\n    };\n    list?: {\n      block?: string[];\n      ordered?: string[];\n      unordered?: string[];\n      item?: string[];\n      nested?: string[];\n      indent?: {\n        ordered?: string[];\n        unordered?: string[];\n      };\n    };\n    code?: {\n      block?: string[];\n      language?: string[];\n    };\n    image?: {\n      block?: string[];\n      image?: string[];\n      caption?: string[];\n    };\n  };\n  overwrite?: {\n    // Same structure as extend, but will replace default values instead of extending them\n  };\n}\n```\n\n#### Default Theme Reference\n\nHere's the complete default theme object that you can use as a reference when extending or overwriting:\n\n```typescript\nconst StrapiBlockThemeDefault = {\n    block: ['astro-strapi-block'],\n    heading: {\n        block: ['astro-strapi-block-heading'],\n        h1: ['text-6xl', 'font-bold', 'mb-4'],\n        h2: ['text-5xl', 'font-bold', 'mb-4'],\n        h3: ['text-4xl', 'font-bold', 'mb-4'],\n        h4: ['text-3xl', 'font-bold', 'mb-4'],\n        h5: ['text-2xl', 'font-bold', 'mb-4'],\n        h6: ['text-xl', 'font-bold', 'mb-4'],\n        content: {\n            block: [],\n            span: [],\n            strong: ['font-bold'],\n            italic: ['italic'],\n            underline: ['underline'],\n            strikethrough: ['line-through'],\n            link: ['text-blue-500', 'underline', 'hover:text-blue-800']\n        },\n    },\n    paragraph: {\n        block: ['astro-strapi-block-paragraph', 'mb-4'],\n        span: [],\n        strong: ['font-bold'],\n        italic: ['italic'],\n        underline: ['underline'],\n        strikethrough: ['line-through'],\n        link: ['text-blue-500', 'underline', 'hover:text-blue-800']\n    },\n    quote: {\n        block: ['astro-strapi-block-quote', 'border-l-4', 'border-gray-300', 'pl-4', 'mb-4'],\n        span: [],\n        strong: ['font-bold'],\n        italic: ['italic'],\n        underline: ['underline'],\n        strikethrough: ['line-through'],\n        link: ['text-blue-500', 'underline', 'hover:text-blue-800']\n    },\n    list: {\n        block: ['astro-strapi-block-list', 'my-4'],\n        ordered: ['pl-6'],\n        unordered: ['pl-6'],\n        item: ['mb-2', 'last:mb-0'],\n        nested: ['mb-2'],\n        indent: {\n            ordered: [\n                'list-decimal', 'list-[lower-latin]', 'list-[lower-roman]', 'list-[upper-latin]', 'list-[upper-roman]', 'list-decimal',\n            ],\n            unordered: [\n                'list-disc', 'list-[circle]', 'list-[square]', 'list-disk', 'list-[circle]', 'list-[square]',\n            ],\n        },\n    },\n    code: {\n        block: ['astro-strapi-block-code', 'mb-4', 'bg-gray-200', 'p-4', 'rounded-md', 'text-sm', 'font-mono', 'last:mb-0'],\n        language: ['astro-strapi-block-code-language', 'inline-block', 'text-xs', 'font-sans', 'font-medium', 'bg-gray-300', 'py-1', 'px-4', 'mb-2', 'rounded-full', 'text-gray-700']\n    },\n    image: {\n        block: ['mb-4', 'w-full', 'h-auto', 'flex', 'items-center', 'justify-center', 'last:mb-0'],\n        image: ['rounded-md'],\n        caption: ['text-sm', 'mb-2', 'text-gray-900', 'text-center', 'italic']\n    },\n}\n```\n\nThis default theme provides a clean, modern look using Tailwind CSS classes. You can use this as a starting point for your custom themes.\n\n#### Lists: nested lists and `indent`\n\nList styling is split between the base list (`list.ordered` / `list.unordered`), list items (`list.item`), optional spacing when the tree contains sublists (`list.nested`), and **per–nesting-level** marker classes (`list.indent`).\n\n- **`list.indent.ordered`** and **`list.indent.unordered`** are **arrays of class strings**: index `0` is used for the top-level list, index `1` for the first nested list, and so on. The renderer uses Strapi’s optional `indentLevel` on a `list` node so that, when a child list is flagged with `indentLevel`, the depth is incremented for that subtree. If the index is out of range, no extra indent class is applied for that level.\n- The theme helpers support a **three-segment** path for this branch: `getPropertyClass(theme, ['list', 'indent', 'ordered' | 'unordered'])` returns that array, and you can pick a single level with `[indentLevel]`. The two-segment `renderPropertyClasses(theme, ['list', 'ordered' | 'unordered'])` (and the same for `item`, `nested`, etc.) is unchanged. Using `renderPropertyClasses(theme, ['list', 'indent', format])` **joins the entire** `indent` array into one class string, which is appropriate only if you want all marker utilities on one element; for per-level markers, use `getPropertyClass` and index as above.\n\nExample — extend only nested marker styles (Tailwind list-style steps):\n\n```typescript\ntheme={{\n  extend: {\n    list: {\n      indent: {\n        ordered: ['list-decimal', 'list-[lower-alpha]', 'list-[lower-roman]'],\n        unordered: ['list-disc', 'list-[circle]', 'list-[square]'],\n      },\n    },\n  },\n}}\n```\n\n#### Examples\n\n1. Extending default theme:\n```astro\n\u003cStrapiBlocks \n  theme={{\n    extend: {\n      paragraph: {\n        block: ['my-paragraph-class'],\n        strong: ['font-bold', 'text-primary'],\n        italic: ['italic', 'text-secondary'],\n        link: ['text-accent', 'hover:underline']\n      },\n      heading: {\n        block: ['my-heading-class'],\n        h1: ['text-4xl', 'font-bold']\n      }\n    }\n  }}\n/\u003e\n```\n\n2. Overwriting default theme:\n```astro\n\u003cStrapiBlocks \n  theme={{\n    overwrite: {\n      paragraph: {\n        block: ['my-paragraph-class'],\n        strong: ['font-bold'],\n        italic: ['italic'],\n        link: ['text-blue-500']\n      }\n    }\n  }}\n/\u003e\n```\n\n3. Mixed configuration (extend and overwrite):\n```astro\n\u003cStrapiBlocks \n  theme={{\n    extend: {\n      paragraph: {\n        strong: ['font-bold'],\n        italic: ['italic']\n      }\n    },\n    overwrite: {\n      heading: {\n        block: ['text-2xl'],\n        h1: ['text-4xl', 'font-bold']\n      }\n    }\n  }}\n/\u003e\n```\n\nThe default theme includes Tailwind CSS classes for common styling needs. You can extend or overwrite these classes to match your design requirements.\n\n### Component Customization\n\nYou can override any built-in block component with your own Astro component. This allows for complete control over the rendering of each block type while maintaining the same input props structure.\n\n#### Usage\n\n```astro\n---\nimport { StrapiBlocks } from '@sensinum/astro-strapi-blocks';\nimport MyCustomHeading from '../components/MyCustomHeading.astro';\nimport MyCustomParagraph from '../components/MyCustomParagraph.astro';\n---\n\n\u003cStrapiBlocks \n  data={strapiBlockData}\n  blocks={{\n    heading: MyCustomHeading,\n    paragraph: MyCustomParagraph\n  }}\n/\u003e\n```\n\n#### Available Block Types\n\nYou can override any of the following block types:\n- `heading` - For header blocks (H1-H6)\n- `paragraph` - For paragraph blocks\n- `quote` - For quote blocks\n- `list` - For ordered and unordered lists\n- `code` - For code blocks\n- `image` - For image blocks\n\n#### Block Type Properties\n\nEach block type has its own specific properties. Here's a detailed breakdown of all available properties for each block type:\n\n##### Heading Block\n```typescript\ntype HeadingBlockProps = {\n  data: Array\u003cStrapiBlockNode\u003e;  // Text content nodes\n  class?: string;                // Additional CSS classes\n  theme: StrapiBlockTheme;       // Theme configuration\n  level: 1 | 2 | 3 | 4 | 5 | 6; // Heading level (h1-h6)\n}\n```\n\n##### Paragraph Block\n```typescript\ntype ParagraphBlockProps = {\n  data: Array\u003cStrapiBlockNode\u003e;  // Text content nodes with formatting\n  class?: string;                // Additional CSS classes\n  theme: StrapiBlockTheme;       // Theme configuration\n}\n```\n\n##### Quote Block\n```typescript\ntype QuoteBlockProps = {\n  data: Array\u003cStrapiBlockNode\u003e;  // Text content nodes with formatting\n  class?: string;                // Additional CSS classes\n  theme: StrapiBlockTheme;       // Theme configuration\n}\n```\n\n##### List Block\n```typescript\ntype ListBlockProps = {\n  data: Array\u003cStrapiBlockListItem | StrapiBlockList\u003e; // List items and nested lists\n  class?: string;                 // Additional CSS classes\n  theme: StrapiBlockTheme;        // Theme configuration\n  format: 'ordered' | 'unordered'; // List type\n  nested?: boolean;               // True when the tree contains sublists\n}\n```\n\n`StrapiBlockList` nodes in `data` may include an optional `indentLevel` field from Strapi; the default list component uses it together with `theme.list.indent` to choose list-style classes by nesting depth. Import `StrapiBlockListItem` and `StrapiBlockList` from the package types when you type custom list blocks.\n\n##### Code Block\n```typescript\ntype CodeBlockProps = {\n  data: Array\u003cStrapiBlockNode\u003e;  // Code content nodes\n  class?: string;                // Additional CSS classes\n  theme: StrapiBlockTheme;       // Theme configuration\n  language: string;              // Programming language\n}\n```\n\n##### Image Block\n```typescript\ntype ImageBlockProps = {\n  data: Array\u003cStrapiBlockNode\u003e;  // Image content nodes\n  class?: string;                // Additional CSS classes\n  theme: StrapiBlockTheme;       // Theme configuration\n  url: string;                   // Image URL\n  alternativeText?: string;      // Alt text for accessibility\n  caption?: string;              // Image caption\n}\n```\n\n#### Example Custom Component\n\nHere's an example of a custom heading component:\n\n```astro\n---\n// MyCustomHeading.astro\nimport { renderPropertyClasses } from '@sensinum/astro-strapi-blocks';\nimport type { StrapiBlockNode, StrapiBlockTheme } from '@sensinum/astro-strapi-blocks';\n\ntype Props = {\n  data: Array\u003cStrapiBlockNode\u003e;\n  class?: string;\n  theme: StrapiBlockTheme;\n  level?: 1 | 2 | 3 | 4 | 5 | 6;\n}\n\nconst { data, class: classes = '', theme, level = 1 } = Astro.props;\nconst Tag = `h${level}`;\n---\n\n\u003cTag class={renderPropertyClasses(theme, ['heading', `h${level}`], classes)}\u003e\n  {data.map((item) =\u003e item.text).join('')}\n\u003c/Tag\u003e\n```\n\n## 🔧 Development\n\n1. Clone the repository\n2. Install dependencies:\n   ```bash\n   yarn\n   ```\n3. Run development mode:\n   ```bash\n   yarn dev\n   ```\n4. Check types:\n   ```bash\n   yarn check\n   ```\n\n## 🤝 Contributing\n\nWe welcome contributions to this project! Here's how you can help:\n\n1. Fork the repository\n2. Create your feature branch (`git checkout -b feature/amazing-feature`)\n3. Commit your changes (`git commit -m 'Add some amazing feature'`)\n4. Push to the branch (`git push origin feature/amazing-feature`)\n5. Open a Pull Request\n\nPlease make sure to:\n- Follow the existing code style\n- Write tests for new features\n- Update documentation as needed\n- Keep your PR focused and concise\n\n## 📄 License\n\nCopyright © [Sensinum](https://sensinum.com) \u0026 [VirtusLab](https://virtuslab.com)\n\nThis project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details. ","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvirtuslab-open-source%2Fastro-strapi-blocks","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvirtuslab-open-source%2Fastro-strapi-blocks","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvirtuslab-open-source%2Fastro-strapi-blocks/lists"}