{"id":15016481,"url":"https://github.com/signalkuppe/eleventy-react","last_synced_at":"2025-06-23T17:10:11.896Z","repository":{"id":56320047,"uuid":"289558635","full_name":"signalkuppe/eleventy-react","owner":"signalkuppe","description":"Use React components in Eleventy.","archived":false,"fork":false,"pushed_at":"2021-07-21T06:30:04.000Z","size":5488,"stargazers_count":87,"open_issues_count":2,"forks_count":14,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-12T09:43:24.126Z","etag":null,"topics":["eleventy","react","storybook","styled-components"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/signalkuppe.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-08-22T20:04:57.000Z","updated_at":"2025-02-18T07:54:51.000Z","dependencies_parsed_at":"2022-08-15T16:40:15.846Z","dependency_job_id":null,"html_url":"https://github.com/signalkuppe/eleventy-react","commit_stats":null,"previous_names":[],"tags_count":23,"template":false,"template_full_name":null,"purl":"pkg:github/signalkuppe/eleventy-react","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/signalkuppe%2Feleventy-react","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/signalkuppe%2Feleventy-react/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/signalkuppe%2Feleventy-react/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/signalkuppe%2Feleventy-react/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/signalkuppe","download_url":"https://codeload.github.com/signalkuppe/eleventy-react/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/signalkuppe%2Feleventy-react/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261519072,"owners_count":23171228,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["eleventy","react","storybook","styled-components"],"created_at":"2024-09-24T19:48:58.071Z","updated_at":"2025-06-23T17:10:06.878Z","avatar_url":"https://github.com/signalkuppe.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# eleventy-react\n\n\u003e Use [React](https://reactjs.org/) components in [Eleventy](https://www.11ty.dev/).\n\nIf you want a lighter version, without eleventy dependency, try [pequeno](https://github.com/signalkuppe/pequeno)\n\n## Demo\n\n[https://eleventy-react.netlify.app/](https://eleventy-react.netlify.app/)\n\n## Why\n\nEleventy is a great static site generator, but I don’t like template engines.\nThey introduce a lot of custom syntax, and it’s almost impossibile to convert them to a component-based dev flow.\n\n## Installation\n\n### 1. Clone or download the repository\n\n```shell\ngit clone git@github.com:signalkuppe/eleventy-react.git eleventy-react\n```\n\n### 2. Go to the working directory\n\n```shell\ncd eleventy-react\n```\n\n### 3. Install the project dependencies\n\n```shell\nnpm install\n\n```\n\n### 3. Run development mode\n\n```shell\nnpm run dev\n```\n\nBuild you site for deploy\n\n```shell\nnpm run build\n```\n\n## Features\n\n### Integration with data file and custom template data\n\njust add a `data export` to your jsx file\n\n```js\nimport React from 'react';\nimport DefaultLayout from '../components/layout/Default';\nimport P from '../components/primitives/P';\nimport Span from '../components/primitives/Span';\nimport H1 from '../components/primitives/H1';\n\n// custom template data\nexport const data = {\n    name: 'John Doe',\n};\n\nexport default function Index({ site, name }) {\n    // site comes from site.js data file in _data\n    const { title } = site;\n\n    return (\n        \u003cDefaultLayout\u003e\n            \u003cH1\u003e{title}\u003c/H1\u003e\n            \u003cP\u003e\n                This name is from custom template data: \u003cSpan bold\u003e{name}\u003c/Span\u003e\n            \u003c/P\u003e\n        \u003c/DefaultLayout\u003e\n    );\n}\n```\n\n### Support for pagination: you can generate pages from data\n\n```js\nimport React from 'react';\nimport { slug } from './utils/user';\nimport DefaultLayout from '../components/layout/Default';\nimport H1 from '../components/primitives/H1';\n\n/**\n * A template that renders a page for each user in the users collection\n */\n\nexport const data = {\n    pagination: {\n        data: 'users',\n        size: 1,\n        alias: 'user',\n    },\n    permalink: function (data) {\n        return slug(data.user);\n    },\n};\n\nexport default function User({ site, user }) {\n    return (\n        \u003cDefaultLayout\u003e\n            \u003cH1\u003e{user.name}\u003c/H1\u003e\n        \u003c/DefaultLayout\u003e\n    );\n}\n```\n\n### Support for markdown content\n\nWrite your content in markdown format, and use .jsx files as layouts. Print html markup with a custom withHtml HOC that uses our primitives styles\n\n`_includes/layouts/post.jsx`\n\n```js\nimport React from 'react';\nimport DefaultLayout from '../../../components/layout/Default';\nimport Section from '../../../components/primitives/Section';\nimport Img from '../../../components/primitives/Img';\nimport Span from '../../../components/primitives/Span';\nimport VerticalSpace from '../../../components/ui/VerticalSpace';\nimport withHtml from '../../../components/hoc/withHtml';\nimport { postSlug } from '../../../components/features/posts/utils';\n\n/**\n * A template that renders a page for each post in the post collection (_posts/*.md)\n */\n\nconst PostBodySection = withHtml(Section);\n\nexport const data = {\n    permalink: function (data) {\n        return postSlug(data.page);\n    },\n};\n\nexport default function Post(data) {\n    const { title, content, cover, tags } = data;\n    return (\n        \u003cDefaultLayout\u003e\n            \u003cImg src={cover} alt={title} /\u003e\n            \u003cPostBodySection\u003e{content}\u003c/PostBodySection\u003e\n            {tags?.length \u0026\u0026 (\n                \u003c\u003e\n                    \u003cVerticalSpace /\u003e\n                    {tags.map((tag, i) =\u003e (\n                        \u003cSpan key={i} italic\u003e\n                            {tag}\n                            {i \u003c tags.length - 1 \u0026\u0026 ', '}\n                        \u003c/Span\u003e\n                    ))}\n                \u003c/\u003e\n            )}\n        \u003c/DefaultLayout\u003e\n    );\n}\n```\n\n### Integration with styled components\n\nstyles are extracted and inserted into the `\u003chead\u003e` tag\n\n```js\nimport React from 'react';\nimport styled from 'styled-components';\n\nconst StyledText = styled.span`\n    font-weight: ${(props) =\u003e {\n        if (props.bold) {\n            return 700;\n        } else {\n            return 400;\n        }\n    }};\n`;\n\nexport default function Span({ children, ...props }) {\n    return \u003cStyledText {...props}\u003e{children}\u003c/StyledText\u003e;\n}\n```\n\n### Integration with [storybook](https://storybook.js.org/)\n\nDevelop your UI in isolation adding stories for your components and run storybook with\n\n```shell\nnpm run storybook\n```\n\nBuild storybook inside eleventy’s \\_site folder\n\n```shell\nnpm run build-storybook\n```\n\nstories are written in [.mdx](https://storybook.js.org/docs/react/writing-docs/mdx) format\n\n### Some basic scaffolding included\n\nbasic ui/primitives/features components included to give an idea of the approach\n\n### Inline svg parser included\n\nimport and use inline svgs in your react components\n\n### Babel plugins included\n\n-   @babel/plugin-proposal-optional-chaining\n\n## Dealing with client-side js\n\n**React is not included in the build,** so you can use any js approach on the client.\nI think that adding hydration would go against Eleventy’s philosophy.\n\nDevelopers like to write code in a **component-fashioned way** so there’s a helper to deal with client-side js code.\n\nSay you have **a component that need some vanilla client-side js logic** and maybe an external library, like an [accordion](https://github.com/signalkuppe/fisarmonica).\nJust add the `\u003cScript\u003e` component in you code like this\n\n```js\nimport React, { Fragment } from 'react';\nimport Dl from '../../primitives/Dl';\nimport Dt from '../../primitives/Dt';\nimport Dd from '../../primitives/Dd';\nimport Button from '../../primitives/Button';\nimport Script, { outputLibDir } from '../Script';\nimport client from './index.client.js';\n\nexport default function Accordion({ items }) {\n    return (\n        \u003c\u003e\n            \u003cDl reset id=\"accordion\"\u003e\n                {items.map((item, i) =\u003e (\n                    \u003cFragment key={i}\u003e\n                        \u003cDt\u003e\n                            \u003cButton\u003e{item.title}\u003c/Button\u003e\n                        \u003c/Dt\u003e\n                        \u003cDd\u003e{item.description}\u003c/Dd\u003e\n                    \u003c/Fragment\u003e\n                ))}\n            \u003c/Dl\u003e\n            \u003cScript\n                libs={[\n                    {\n                        js: `/${outputLibDir}/fisarmonica/src/fisarmonica.js`,\n                        css: `/${outputLibDir}/fisarmonica/src/fisarmonica.css`,\n                    },\n                ]}\n            \u003e\n                {client}\n            \u003c/Script\u003e\n        \u003c/\u003e\n    );\n}\n```\n\nWith the libs param **you can add as many libraries as you want,** adding the required js and css files.\n**Write you logic in a .client.js file** in the component folder, import it and place it as a children of the `\u003cScript\u003e` component.\n\nStyles and scripts will be extracted at build time and placed in the right place in the DOM.\nThere is also a Storybook decorator that adds the client-side logic to stories\n\nBe sure to pass the libs installed via npm to the output folder in the `.eleventy.js` config file.\n\n```js\n// add this client side js lib to our otuput dir\n\neleventyConfig.addPassthroughCopy({\n    'node_modules/fisarmonica': `${config.outputLibDir}/fisarmonica`,\n});\n```\n\n### Theme variables are exposed to the client\n\nSometimes you have to use your theme variables in client-side logic.\nA global `THEME` variable containing our styled-components settings is exposed to the client.\n\n```js\nconst THEME = {\n    colors: {\n        background: '#282c34',\n        backgroundDark: '#20232a',\n        primary: '#61dafb',\n        white: 'white',\n        grey: '#32363e',\n    },\n    type: {\n        fontSans: '-apple-system, “Segoe UI”, “Roboto”',\n        fontMono: 'source-code-pro, Menlo, Monaco, Consolas, monospace',\n        leading: 1.4,\n        root: '112.5%',\n        base: '1rem',\n        headingsBase: 2,\n        scale: 1.333,\n    },\n};\n```\n\n## TODO\n\n-   reduce storybook bundle site for production build\n-   test other eleventy’s features\n-   use React components in \\_data files\n\n## Warnings\n\n_⚠️ very much a work in progress_\n\nRequires experimental features in Eleventy, specifically: [Custom File Extension Handlers feature from Eleventy](https://github.com/11ty/eleventy/issues/117)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsignalkuppe%2Feleventy-react","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsignalkuppe%2Feleventy-react","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsignalkuppe%2Feleventy-react/lists"}