{"id":50525581,"url":"https://github.com/unlayer/elements","last_synced_at":"2026-06-28T14:00:34.320Z","repository":{"id":348479881,"uuid":"1044405251","full_name":"unlayer/elements","owner":"unlayer","description":"Write once in React. Render emails, web pages, and PDFs from the same component tree.","archived":false,"fork":false,"pushed_at":"2026-06-24T18:23:34.000Z","size":19504,"stargazers_count":17,"open_issues_count":8,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-06-24T19:03:10.814Z","etag":null,"topics":["component-library","developer-tools","email-templates","nextjs","pdf-generation","react","react-email","typescript"],"latest_commit_sha":null,"homepage":"https://unlayer.com/elements","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/unlayer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","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-08-25T16:24:19.000Z","updated_at":"2026-06-24T12:32:17.000Z","dependencies_parsed_at":null,"dependency_job_id":"0fc4446e-cac1-48ee-a2bc-b7721291b74a","html_url":"https://github.com/unlayer/elements","commit_stats":null,"previous_names":["unlayer/elements"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/unlayer/elements","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unlayer%2Felements","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unlayer%2Felements/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unlayer%2Felements/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unlayer%2Felements/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/unlayer","download_url":"https://codeload.github.com/unlayer/elements/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unlayer%2Felements/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34890795,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-28T02:00:05.809Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["component-library","developer-tools","email-templates","nextjs","pdf-generation","react","react-email","typescript"],"created_at":"2026-06-03T07:31:34.413Z","updated_at":"2026-06-28T14:00:34.308Z","avatar_url":"https://github.com/unlayer.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://unlayer.com/logo_square.png\" alt=\"Unlayer Elements\" width=\"50\" /\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eUnlayer Elements\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  Write once in React. Render emails, web pages, and PDFs from the same component tree.\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://www.npmjs.com/package/@unlayer/react-elements\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/@unlayer/react-elements.svg\" alt=\"npm version\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/unlayer/elements/actions/workflows/test.yml\"\u003e\u003cimg src=\"https://github.com/unlayer/elements/actions/workflows/test.yml/badge.svg\" alt=\"CI\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/unlayer/elements/blob/main/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/npm/l/@unlayer/react-elements.svg\" alt=\"license\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/@unlayer/react-elements\"\u003e\u003cimg src=\"https://img.shields.io/npm/dm/@unlayer/react-elements.svg\" alt=\"downloads\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./assets/elements-demo.gif\" alt=\"Unlayer Elements: the same JSX rendered as email, web, and document output\" width=\"800\" /\u003e\n\u003c/p\u003e\n\nUnlayer Elements is an open-source React component library that lets you build content once and render it across three output modes:\n\n- **Email** → Outlook, Gmail, Yahoo, Apple Mail\n- **Web** → Responsive pages and embedded experiences\n- **Document** → Print-ready HTML for PDF generation\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://unlayer.com/images/unlayer-elements-dark.png\" alt=\"Unlayer Elements: Architecture\" width=\"1200\" /\u003e\n\u003c/p\u003e\n\nElements is built and maintained by the team behind [Unlayer](https://unlayer.com), the content creation platform used by thousands of companies to power email, page, and document experiences inside their products.\n\n## Why Elements?\n\n| Tool          | Email | Web | PDF |\n|---------------|:-----:|:---:|:---:|\n| React Email   |  ✅   | ❌  | ❌  |\n| MJML          |  ✅   | ❌  | ❌  |\n| PDF libraries |  ❌   | ❌  | ✅  |\n| **Elements**  |  ✅   | ✅  | ✅  |\n\nElements is designed for teams that need to generate email, web, and document experiences from a single React codebase.\n\n## Quick Start\n\n```bash\nnpm install @unlayer/react-elements\n```\n\n```tsx\nimport {\n  Email, Row, Column, ColumnLayouts,\n  Heading, Paragraph, Button, renderToHtml\n} from '@unlayer/react-elements';\n\nfunction WelcomeEmail() {\n  return (\n    \u003cEmail backgroundColor=\"#f0f0f0\" contentWidth=\"600px\"\u003e\n      \u003cRow layout={ColumnLayouts.OneColumn} backgroundColor=\"#ffffff\" padding=\"20px\"\u003e\n        \u003cColumn\u003e\n          \u003cHeading\n            fontSize=\"24px\"\n            fontFamily={{ label: \"Arial\", value: \"arial,helvetica,sans-serif\" }}\n          \u003e\n            Welcome!\n          \u003c/Heading\u003e\n          \u003cParagraph html=\"Thanks for signing up.\" fontSize=\"14px\" /\u003e\n          \u003cButton\n            href=\"https://example.com\"\n            backgroundColor=\"#0879A1\"\n            color=\"#ffffff\"\n          \u003e\n            Get Started\n          \u003c/Button\u003e\n        \u003c/Column\u003e\n      \u003c/Row\u003e\n    \u003c/Email\u003e\n  );\n}\n\n// Render to a clean HTML string — no React hydration markers\nconst html = renderToHtml(\u003cWelcomeEmail /\u003e);\n```\n\n## Features\n\n### One Component Tree\n\nBuild content once and render it as email, web, or document. Share components, styling, and content across all three output modes from the same React codebase.\n\n### React Developer Workflow\n\nWorks with React, Next.js, Remix, and Server Components. Use familiar JSX patterns and existing frontend workflows without learning a new templating language.\n\n### Production Output\n\nGenerates email-safe HTML, responsive web HTML, and print-ready HTML for PDF generation — optimized output for each destination without maintaining separate implementations.\n\n### Visual Builder Compatible\n\nExport Unlayer-compatible design JSON with `renderToJson()` for round-tripping between code and the visual editor. Ideal for teams that want the flexibility of code alongside visual editing workflows.\n\n### TypeScript First\n\nBuilt with TypeScript from the ground up — full type definitions, autocomplete for components and props, and safer development with better IDE support.\n\n### Clean HTML Output\n\n`renderToHtml()` generates production-ready HTML with no React hydration markers, no framework artifacts, and no client-side JavaScript required.\n\n### Lightweight \u0026 Tree-Shakeable\n\n~12KB gzipped (under 60KB ESM), tree-shakeable, with zero client-side JavaScript required. Designed for performance-sensitive applications and server-side rendering environments.\n\n## Real-World Use Cases\n\n### Transactional Emails\n\nBuild and maintain order confirmations, password resets, and receipts from the same React codebase that powers your application.\n\n### PDF Generation\n\nGenerate invoices, contracts, and reports server-side without maintaining a separate PDF system.\n\n### CMS-Driven Content\n\nRender content from a CMS, API, or database into emails, web pages, and documents using a shared component model.\n\n### Email + Web Parity\n\nPublish the same content as an email campaign, a web archive, and a public landing page from a single source of truth.\n\n## Components\n\n| Component | Description |\n|-----------|-------------|\n| `\u003cEmail\u003e` | Root wrapper — email-safe HTML (tables for Outlook/Gmail) |\n| `\u003cPage\u003e` | Root wrapper — responsive web (div + flexbox) |\n| `\u003cDocument\u003e` | Root wrapper — print/PDF optimized |\n| `\u003cRow\u003e` | Layout container with column layout support |\n| `\u003cColumn\u003e` | Column inside a Row |\n| `\u003cButton\u003e` | CTA button with hover states and links |\n| `\u003cHeading\u003e` | Heading (h1–h4) |\n| `\u003cParagraph\u003e` | Rich text with plain text or HTML content |\n| `\u003cImage\u003e` | Responsive image with alt text |\n| `\u003cDivider\u003e` | Horizontal separator |\n| `\u003cSocial\u003e` | Social media icon links |\n| `\u003cMenu\u003e` | Navigation menu |\n| `\u003cTable\u003e` | Data table |\n| `\u003cVideo\u003e` | YouTube/Vimeo embed |\n| `\u003cHtml\u003e` | Custom HTML passthrough |\n\n## Structure\n\nComponents follow a strict hierarchy:\n\n```\n\u003cEmail\u003e              ← sets render mode\n  \u003cRow layout={…}\u003e   ← layout container\n    \u003cColumn\u003e         ← must match layout column count\n      \u003cButton /\u003e     ← content components\n      \u003cParagraph /\u003e\n    \u003c/Column\u003e\n  \u003c/Row\u003e\n\u003c/Email\u003e\n```\n\n## Column Layouts\n\n```tsx\nimport { Row, Column, ColumnLayouts } from '@unlayer/react-elements';\n\n// Each Row must contain the matching number of \u003cColumn\u003e children.\n\u003cRow layout={ColumnLayouts.OneColumn}\u003e                {/* [1]         → 100% */}\n  \u003cColumn\u003e{/* content */}\u003c/Column\u003e\n\u003c/Row\u003e\n\u003cRow layout={ColumnLayouts.TwoEqual}\u003e                 {/* [1,1]       → 50% + 50% */}\n  \u003cColumn\u003e{/* content */}\u003c/Column\u003e\n  \u003cColumn\u003e{/* content */}\u003c/Column\u003e\n\u003c/Row\u003e\n\u003cRow layout={ColumnLayouts.TwoWideNarrow}\u003e            {/* [2,1]       → 67% + 33% */}\n  \u003cColumn\u003e{/* content */}\u003c/Column\u003e\n  \u003cColumn\u003e{/* content */}\u003c/Column\u003e\n\u003c/Row\u003e\n\u003cRow layout={ColumnLayouts.ThreeEqual}\u003e               {/* [1,1,1]     → 33% each */}\n  \u003cColumn\u003e{/* content */}\u003c/Column\u003e\n  \u003cColumn\u003e{/* content */}\u003c/Column\u003e\n  \u003cColumn\u003e{/* content */}\u003c/Column\u003e\n\u003c/Row\u003e\n\u003cRow layout={ColumnLayouts.FourEqual}\u003e                {/* [1,1,1,1]   → 25% each */}\n  \u003cColumn\u003e{/* content */}\u003c/Column\u003e\n  \u003cColumn\u003e{/* content */}\u003c/Column\u003e\n  \u003cColumn\u003e{/* content */}\u003c/Column\u003e\n  \u003cColumn\u003e{/* content */}\u003c/Column\u003e\n\u003c/Row\u003e\n\u003cRow cells={[3, 1]}\u003e                                  {/* custom ratio */}\n  \u003cColumn\u003e{/* content */}\u003c/Column\u003e\n  \u003cColumn\u003e{/* content */}\u003c/Column\u003e\n\u003c/Row\u003e\n```\n\n## Documentation\n\nFor the full API reference, component props, design patterns, and common mistakes, see the **[React package documentation](./packages/react/README.md)**.\n\n## Packages\n\n| Package | Description | Published |\n|---------|-------------|-----------|\n| [`@unlayer/react-elements`](./packages/react) | React components and renderers | [![npm](https://img.shields.io/npm/v/@unlayer/react-elements.svg)](https://www.npmjs.com/package/@unlayer/react-elements) |\n| [`@unlayer-internal/shared-elements`](./packages/shared) | Framework-agnostic shared logic | Internal |\n| [`@unlayer/elements-demo`](./packages/demo) | Demo application | — |\n\n## Development\n\n```bash\n# Prerequisites: Node.js (see .nvmrc), pnpm 9+\n\n# Install dependencies\npnpm install\n\n# Build all packages\npnpm build\n\n# Run tests\npnpm test\n\n# Run tests with coverage\npnpm test:coverage\n\n# Launch Storybook\npnpm storybook:hub\n```\n\n## Contributing\n\nSee [CONTRIBUTING.md](./CONTRIBUTING.md) for setup instructions and guidelines.\n\n## License\n\n[MIT](./LICENSE) — Unlayer, Inc.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funlayer%2Felements","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Funlayer%2Felements","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funlayer%2Felements/lists"}