feat(ui): comprehensive UI/UX improvements (#1069)

* feat(ui): replace emoji icons with SVG icon system

Replace all emoji icons with a consistent SVG icon system to improve:
- Visual consistency across platforms
- Design token control and theming
- Professional appearance

Changes:
- Add new Icon.astro component with 16 custom SVG icons
- Update index.astro to use SVG icons in resource cards
- Update index.ts to render SVG icons in search results
- Update utils.ts to return icon names instead of emojis
- Update global.css with proper SVG icon styling
- Remove emoji from Footer component

Icons added: robot, document, lightning, hook, workflow, plug, wrench, book,
plus action icons: close, copy, download, share, external, plus, search, chevron-down

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(ui): enhance hero section, add animations and mobile responsiveness

Phase 2 & 3 UI/UX improvements:

Hero Section Enhancements:
- Add gradient text effect for title (purple to orange gradient)
- Add animated floating particles in hero background
- Increase hero padding for better visual impact

Card Category Colors:
- Add category-specific accent colors (AI, docs, power, automation, etc.)
- Each category has unique glow effect on hover
- Category colors: purple (AI), orange (docs), red (power), etc.

Entrance Animations:
- Add staggered fade-in animation for cards (50ms delay each)
- Cards animate in with translateY + opacity
- Add slide-down animation for search results

Mobile Responsiveness:
- Responsive grid: 4 cols → 2 cols → 1 col
- Adjust font sizes for mobile screens
- Add safe-area-inset support for notched devices
- Ensure touch targets ≥44px

Accessibility:
- Add prefers-reduced-motion support
- Disable animations for users who prefer reduced motion
- Smooth scroll with fallback

Additional Improvements:
- Add arrow indicator on card hover
- Add loading animation for count numbers
- Enhanced scrollbar styling
- Print styles for better printing

Co-Authored-By: Claude <noreply@anthropic.com>

* feat(ui): add theme toggle, enhanced search, and back to top button

Theme Toggle:
- Create ThemeToggle.astro component with sun/moon icons
- Add theme initialization in Head.astro to prevent flash
- Store theme preference in localStorage
- Keyboard shortcut: Cmd/Ctrl + Shift + L
- Smooth icon transition animation

Back to Top Button:
- Create BackToTop.astro component
- Appears after scrolling 400px
- Smooth scroll to top on click
- Fixed position bottom-right
- Respects reduced motion preference

Enhanced Search:
- Recent searches functionality with localStorage
- Show recent searches on focus when empty
- Remove individual items or clear all
- Enhanced empty state with icon and hint
- Cmd/Ctrl + K keyboard shortcut to focus search
- Add search to recent when getting results

CSS Enhancements:
- Theme toggle container styles
- Recent searches section styling
- Search empty state with icon
- Search loading spinner
- Keyboard shortcut hint styles
- Print styles for new components

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(ui): resolve header and theme toggle issues

- Add Copilot logo to header via Starlight config with automatic theme switching
- Fix theme toggle slider direction (was reversed)
- Fix theme toggle active icon highlighting (was backwards)
- Change theme toggle from purple circle slider to bold text indicator
- Fix theme toggle slider overflow by adding overflow: hidden
- Remove duplicate banner image from home page
- Clean up conflicting logo CSS rules to prevent duplication

The header now displays: [ Copilot Icon ] Awesome GitHub Copilot [ Search ]
Theme toggle indicators are now visually clear with bold text for selected theme.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>

* fix(ui): address feedback on UI/UX improvements

- Remove logo from header per brand guidance (logo config and CSS)
- Fix back-to-top button visibility by moving to body level and using global styles
- Fix modal visibility by adding 'visible' class for CSS animations
- Fix theme toggle applying site-wide by using global styles and proper theme initialization
- Update icons to use GitHub Primer SVG icons with proper fill-based styling
- Fix plugin modal to render SVG icons instead of icon names
- Add theme initialization script to prevent flash of unstyled content

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: move modal to body level to fix z-index stacking context issue

The modal was nested inside .main-pane which has isolation: isolate,
creating a new stacking context. This caused the modal's z-index
to be evaluated within that context, unable to stack above the header.

This fix moves the modal to be a direct child of body on page load,
allowing it to properly cover the entire viewport including navbar.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
JoeVenner
2026-03-23 00:13:29 +01:00
committed by GitHub
parent c50b3563f8
commit 10e717202f
22 changed files with 1815 additions and 171 deletions

View File

@@ -5,6 +5,7 @@ import Modal from '../components/Modal.astro';
import ContributeCTA from '../components/ContributeCTA.astro';
import EmbeddedPageData from '../components/EmbeddedPageData.astro';
import PageHeader from '../components/PageHeader.astro';
import BackToTop from '../components/BackToTop.astro';
import { renderAgentsHtml, sortAgents } from '../scripts/pages/agents-render';
const initialItems = sortAgents(agentsData.items, 'title');
@@ -12,7 +13,7 @@ const initialItems = sortAgents(agentsData.items, 'title');
<StarlightPage frontmatter={{ title: 'Custom Agents', description: 'Specialized agents that enhance GitHub Copilot for specific technologies, workflows, and domains', template: 'splash', prev: false, next: false, editUrl: false }}>
<div id="main-content">
<PageHeader title="🤖 Custom Agents" description="Specialized agents that enhance GitHub Copilot for specific technologies, workflows, and domains" />
<PageHeader title="Custom Agents" description="Specialized agents that enhance GitHub Copilot for specific technologies, workflows, and domains" icon="robot" />
<div class="page-content">
<div class="container">
@@ -57,6 +58,7 @@ const initialItems = sortAgents(agentsData.items, 'title');
</div>
<Modal />
<BackToTop />
<EmbeddedPageData filename="agents.json" data={agentsData} />
<script>

View File

@@ -5,7 +5,7 @@ import PageHeader from '../components/PageHeader.astro';
<StarlightPage frontmatter={{ title: 'Contributors', description: 'The wonderful people who have contributed to Awesome GitHub Copilot', template: 'splash', prev: false, next: false, editUrl: false }}>
<div id="main-content">
<PageHeader title="🌟 Contributors" description="The wonderful people who have contributed to Awesome GitHub Copilot" />
<PageHeader title="Contributors" description="The wonderful people who have contributed to Awesome GitHub Copilot" icon="book" />
<div class="page-content">
<div class="container">

View File

@@ -4,6 +4,7 @@ import Modal from '../components/Modal.astro';
import ContributeCTA from '../components/ContributeCTA.astro';
import PageHeader from '../components/PageHeader.astro';
import EmbeddedPageData from '../components/EmbeddedPageData.astro';
import BackToTop from '../components/BackToTop.astro';
import hooksData from '../../public/data/hooks.json';
import { renderHooksHtml, sortHooks } from '../scripts/pages/hooks-render';
@@ -12,7 +13,7 @@ const initialItems = sortHooks(hooksData.items, 'title');
<StarlightPage frontmatter={{ title: 'Hooks', description: 'Automated workflows triggered by Copilot coding agent events', template: 'splash', prev: false, next: false, editUrl: false }}>
<div id="main-content">
<PageHeader title="🪝 Hooks" description="Automated workflows triggered by Copilot coding agent events" />
<PageHeader title="Hooks" description="Automated workflows triggered by Copilot coding agent events" icon="hook" />
<div class="page-content">
<div class="container">
@@ -21,7 +22,7 @@ const initialItems = sortHooks(hooksData.items, 'title');
<label for="search-input" class="sr-only">Search hooks</label>
<input type="text" id="search-input" placeholder="Search hooks..." autocomplete="off">
</div>
<div class="filters-bar" id="filters-bar">
<div class="filter-group">
<label for="filter-hook">Hook Event:</label>
@@ -41,7 +42,7 @@ const initialItems = sortHooks(hooksData.items, 'title');
<button id="clear-filters" class="btn btn-secondary btn-small">Clear Filters</button>
</div>
</div>
<div class="results-count" id="results-count" aria-live="polite">{initialItems.length} of {initialItems.length} hooks</div>
<div class="resource-list" id="resource-list" role="list" set:html={renderHooksHtml(initialItems)}></div>
<ContributeCTA resourceType="hooks" />
@@ -50,6 +51,7 @@ const initialItems = sortHooks(hooksData.items, 'title');
</div>
<Modal />
<BackToTop />
<EmbeddedPageData filename="hooks.json" data={hooksData} />
<script>

View File

@@ -1,6 +1,8 @@
---
import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro';
import Modal from '../components/Modal.astro';
import Icon from '../components/Icon.astro';
import BackToTop from '../components/BackToTop.astro';
const base = import.meta.env.BASE_URL;
---
@@ -31,7 +33,10 @@ const base = import.meta.env.BASE_URL;
<!-- Hero Section -->
<section class="hero" aria-labelledby="hero-heading">
<div class="container">
<h1 id="hero-heading">Awesome GitHub Copilot</h1>
<h1 id="hero-heading">
<span class="gradient-text">Awesome</span>
<span class="gradient-text-alt">GitHub Copilot</span>
</h1>
<p class="hero-subtitle">Community-contributed agents, instructions, and skills to enhance your GitHub Copilot experience</p>
<div class="hero-search">
<label for="global-search" class="sr-only">Search all resources</label>
@@ -39,13 +44,21 @@ const base = import.meta.env.BASE_URL;
Type at least two characters to show matching resources, then press the Down Arrow key to move into the results.
</p>
<p id="global-search-status" class="sr-only" aria-live="polite"></p>
<input
type="text"
id="global-search"
placeholder="Search all resources..."
autocomplete="off"
aria-describedby="global-search-help global-search-status"
>
<div class="search-row">
<input
type="text"
id="global-search"
placeholder="Search all resources..."
autocomplete="off"
aria-describedby="global-search-help global-search-status"
>
<a href="https://github.com/github/awesome-copilot" target="_blank" rel="noopener" class="github-btn" aria-label="View on GitHub">
<svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor">
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
</svg>
<span>GitHub</span>
</a>
</div>
<div id="search-results" class="search-results hidden" aria-label="Search results"></div>
</div>
</div>
@@ -56,64 +69,72 @@ const base = import.meta.env.BASE_URL;
<h2 id="quick-links-heading" class="sr-only">Browse Resources</h2>
<div class="container">
<div class="cards-grid">
<a href={`${base}agents/`} class="card card-with-count" id="card-agents">
<div class="card-icon" aria-hidden="true">🤖</div>
<a href={`${base}agents/`} class="card card-with-count card-category-ai" id="card-agents" style="--animation-delay: 0ms;">
<div class="card-icon" aria-hidden="true"><Icon name="robot" size={40} /></div>
<div class="card-content">
<h3>Agents</h3>
<p>Custom agents for specialized Copilot experiences</p>
</div>
<div class="card-count" data-count="agents" aria-label="Agent count">-</div>
</a>
<a href={`${base}instructions/`} class="card card-with-count" id="card-instructions">
<div class="card-icon" aria-hidden="true">📋</div>
<a href={`${base}instructions/`} class="card card-with-count card-category-docs" id="card-instructions" style="--animation-delay: 50ms;">
<div class="card-icon" aria-hidden="true"><Icon name="document" size={40} /></div>
<div class="card-content">
<h3>Instructions</h3>
<p>Coding standards and best practices for Copilot</p>
</div>
<div class="card-count" data-count="instructions" aria-label="Instruction count">-</div>
</a>
<a href={`${base}skills/`} class="card card-with-count" id="card-skills">
<div class="card-icon" aria-hidden="true"></div>
<a href={`${base}skills/`} class="card card-with-count card-category-power" id="card-skills" style="--animation-delay: 100ms;">
<div class="card-icon" aria-hidden="true"><Icon name="lightning" size={40} /></div>
<div class="card-content">
<h3>Skills</h3>
<p>Self-contained folders with instructions and resources</p>
</div>
<div class="card-count" data-count="skills" aria-label="Skill count">-</div>
</a>
<a href={`${base}hooks/`} class="card card-with-count" id="card-hooks">
<div class="card-icon" aria-hidden="true">🪝</div>
<a href={`${base}hooks/`} class="card card-with-count card-category-automation" id="card-hooks" style="--animation-delay: 150ms;">
<div class="card-icon" aria-hidden="true"><Icon name="hook" size={40} /></div>
<div class="card-content">
<h3>Hooks</h3>
<p>Automated workflows triggered by agent events</p>
</div>
<div class="card-count" data-count="hooks" aria-label="Hook count">-</div>
</a>
<a href={`${base}workflows/`} class="card card-with-count" id="card-workflows">
<div class="card-icon" aria-hidden="true">⚡</div>
<a href={`${base}workflows/`} class="card card-with-count card-category-automation" id="card-workflows" style="--animation-delay: 200ms;">
<div class="card-icon" aria-hidden="true">
<Icon name="workflow" size={40} />
</div>
<div class="card-content">
<h3>Workflows</h3>
<p>AI-powered automations for GitHub Actions</p>
</div>
<div class="card-count" data-count="workflows" aria-label="Workflow count">-</div>
</a>
<a href={`${base}plugins/`} class="card card-with-count" id="card-plugins">
<div class="card-icon" aria-hidden="true">🔌</div>
<a href={`${base}plugins/`} class="card card-with-count card-category-extension" id="card-plugins" style="--animation-delay: 250ms;">
<div class="card-icon" aria-hidden="true">
<Icon name="plug" size={40} />
</div>
<div class="card-content">
<h3>Plugins</h3>
<p>Curated plugins organized by themes</p>
</div>
<div class="card-count" data-count="plugins" aria-label="Plugin count">-</div>
</a>
<a href={`${base}tools/`} class="card card-with-count" id="card-tools">
<div class="card-icon" aria-hidden="true">🔧</div>
<a href={`${base}tools/`} class="card card-with-count card-category-dev" id="card-tools" style="--animation-delay: 300ms;">
<div class="card-icon" aria-hidden="true">
<Icon name="wrench" size={40} />
</div>
<div class="card-content">
<h3>Tools</h3>
<p>MCP servers and developer tools</p>
</div>
<div class="card-count" data-count="tools" aria-label="Tool count">-</div>
</a>
<a href={`${base}learning-hub/`} class="card card-with-count" id="card-learning-hub">
<div class="card-icon" aria-hidden="true">📚</div>
<a href={`${base}learning-hub/`} class="card card-with-count card-category-learn" id="card-learning-hub" style="--animation-delay: 350ms;">
<div class="card-icon" aria-hidden="true">
<Icon name="book" size={40} />
</div>
<div class="card-content">
<h3>Learning Hub</h3>
<p>Articles and guides to master GitHub Copilot</p>
@@ -127,6 +148,9 @@ const base = import.meta.env.BASE_URL;
<Modal />
<!-- Back to Top Button -->
<BackToTop />
<script>
import '../scripts/pages/index';
</script>

View File

@@ -5,6 +5,7 @@ import Modal from '../components/Modal.astro';
import ContributeCTA from '../components/ContributeCTA.astro';
import EmbeddedPageData from '../components/EmbeddedPageData.astro';
import PageHeader from '../components/PageHeader.astro';
import BackToTop from '../components/BackToTop.astro';
import { renderInstructionsHtml, sortInstructions } from '../scripts/pages/instructions-render';
const initialItems = sortInstructions(instructionsData.items, 'title');
@@ -12,7 +13,7 @@ const initialItems = sortInstructions(instructionsData.items, 'title');
<StarlightPage frontmatter={{ title: 'Instructions', description: 'Coding standards and best practices for GitHub Copilot', template: 'splash', prev: false, next: false, editUrl: false }}>
<div id="main-content">
<PageHeader title="📋 Instructions" description="Coding standards and best practices for GitHub Copilot" />
<PageHeader title="Instructions" description="Coding standards and best practices for GitHub Copilot" icon="document" />
<div class="page-content">
<div class="container">
@@ -21,7 +22,7 @@ const initialItems = sortInstructions(instructionsData.items, 'title');
<label for="search-input" class="sr-only">Search instructions</label>
<input type="text" id="search-input" placeholder="Search instructions..." autocomplete="off">
</div>
<div class="filters-bar" id="filters-bar">
<div class="filter-group">
<label for="filter-extension">File Extension:</label>
@@ -37,7 +38,7 @@ const initialItems = sortInstructions(instructionsData.items, 'title');
<button id="clear-filters" class="btn btn-secondary btn-small">Clear Filters</button>
</div>
</div>
<div class="results-count" id="results-count" aria-live="polite">{initialItems.length} of {initialItems.length} instructions</div>
<div class="resource-list" id="resource-list" role="list" set:html={renderInstructionsHtml(initialItems)}></div>
<ContributeCTA resourceType="instructions" />
@@ -46,6 +47,7 @@ const initialItems = sortInstructions(instructionsData.items, 'title');
</div>
<Modal />
<BackToTop />
<EmbeddedPageData filename="instructions.json" data={instructionsData} />
<script>

View File

@@ -5,6 +5,7 @@ import Modal from '../components/Modal.astro';
import ContributeCTA from '../components/ContributeCTA.astro';
import EmbeddedPageData from '../components/EmbeddedPageData.astro';
import PageHeader from '../components/PageHeader.astro';
import BackToTop from '../components/BackToTop.astro';
import { renderPluginsHtml } from '../scripts/pages/plugins-render';
const initialItems = pluginsData.items;
@@ -12,7 +13,7 @@ const initialItems = pluginsData.items;
<StarlightPage frontmatter={{ title: 'Plugins', description: 'Curated plugins of agents, hooks, and skills for specific workflows', template: 'splash', prev: false, next: false, editUrl: false }}>
<div id="main-content">
<PageHeader title="🔌 Plugins" description="Curated plugins of agents, hooks, and skills for specific workflows" />
<PageHeader title="Plugins" description="Curated plugins of agents, hooks, and skills for specific workflows" icon="plug" />
<div class="page-content">
<div class="container">
@@ -48,6 +49,7 @@ const initialItems = pluginsData.items;
</div>
<Modal />
<BackToTop />
<EmbeddedPageData filename="plugins.json" data={pluginsData} />
<script>

View File

@@ -4,6 +4,7 @@ import Modal from '../components/Modal.astro';
import ContributeCTA from '../components/ContributeCTA.astro';
import PageHeader from '../components/PageHeader.astro';
import EmbeddedPageData from '../components/EmbeddedPageData.astro';
import BackToTop from '../components/BackToTop.astro';
import skillsData from '../../public/data/skills.json';
import { renderSkillsHtml, sortSkills } from '../scripts/pages/skills-render';
@@ -12,7 +13,7 @@ const initialItems = sortSkills(skillsData.items, 'title');
<StarlightPage frontmatter={{ title: 'Skills', description: 'Self-contained agent skills with instructions and bundled resources', template: 'splash', prev: false, next: false, editUrl: false }}>
<div id="main-content">
<PageHeader title="Skills" description="Self-contained agent skills with instructions and bundled resources" />
<PageHeader title="Skills" description="Self-contained agent skills with instructions and bundled resources" icon="lightning" />
<div class="page-content">
<div class="container">
@@ -21,7 +22,7 @@ const initialItems = sortSkills(skillsData.items, 'title');
<label for="search-input" class="sr-only">Search skills</label>
<input type="text" id="search-input" placeholder="Search skills..." autocomplete="off">
</div>
<div class="filters-bar" id="filters-bar">
<div class="filter-group">
<label for="filter-category">Category:</label>
@@ -43,7 +44,7 @@ const initialItems = sortSkills(skillsData.items, 'title');
<button id="clear-filters" class="btn btn-secondary btn-small">Clear Filters</button>
</div>
</div>
<div class="results-count" id="results-count" aria-live="polite">{initialItems.length} of {initialItems.length} skills</div>
<div class="resource-list" id="resource-list" role="list" set:html={renderSkillsHtml(initialItems)}></div>
<ContributeCTA resourceType="skills" />
@@ -52,6 +53,7 @@ const initialItems = sortSkills(skillsData.items, 'title');
</div>
<Modal />
<BackToTop />
<EmbeddedPageData filename="skills.json" data={skillsData} />
<script>

View File

@@ -1,9 +1,11 @@
---
import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro';
import toolsData from '../../public/data/tools.json';
import Modal from '../components/Modal.astro';
import ContributeCTA from "../components/ContributeCTA.astro";
import EmbeddedPageData from "../components/EmbeddedPageData.astro";
import PageHeader from "../components/PageHeader.astro";
import BackToTop from '../components/BackToTop.astro';
import { renderToolsHtml } from "../scripts/pages/tools-render";
const initialItems = toolsData.items.map((item) => ({
@@ -14,7 +16,7 @@ const initialItems = toolsData.items.map((item) => ({
<StarlightPage frontmatter={{ title: 'Tools', description: 'MCP servers and developer tools for GitHub Copilot', template: 'splash', prev: false, next: false, editUrl: false }}>
<div id="main-content">
<PageHeader title="🔧 Tools" description="MCP servers and developer tools for GitHub Copilot" />
<PageHeader title="Tools" description="MCP servers and developer tools for GitHub Copilot" icon="wrench" />
<div class="page-content">
<div class="container">
@@ -57,6 +59,8 @@ const initialItems = toolsData.items.map((item) => ({
</div>
</div>
<Modal />
<BackToTop />
<EmbeddedPageData filename="tools.json" data={toolsData} />
<style is:global>

View File

@@ -5,6 +5,7 @@ import Modal from '../components/Modal.astro';
import ContributeCTA from '../components/ContributeCTA.astro';
import EmbeddedPageData from '../components/EmbeddedPageData.astro';
import PageHeader from '../components/PageHeader.astro';
import BackToTop from '../components/BackToTop.astro';
import { renderWorkflowsHtml, sortWorkflows } from '../scripts/pages/workflows-render';
const initialItems = sortWorkflows(workflowsData.items, 'title');
@@ -12,9 +13,7 @@ const initialItems = sortWorkflows(workflowsData.items, 'title');
<StarlightPage frontmatter={{ title: 'Agentic Workflows', description: 'AI-powered repository automations that run coding agents in GitHub Actions', template: 'splash', prev: false, next: false, editUrl: false }}>
<div id="main-content">
<PageHeader title="Agentic Workflows" description="">
AI-powered repository automations that run coding agents in <a href="https://gh.io/gh-aw" target="_blank" rel="noopener">GitHub Actions</a>
</PageHeader>
<PageHeader title="Agentic Workflows" description="AI-powered repository automations that run coding agents in GitHub Actions" icon="workflow" />
<div class="page-content">
<div class="container">
@@ -23,7 +22,7 @@ const initialItems = sortWorkflows(workflowsData.items, 'title');
<label for="search-input" class="sr-only">Search workflows</label>
<input type="text" id="search-input" placeholder="Search workflows..." autocomplete="off">
</div>
<div class="filters-bar" id="filters-bar">
<div class="filter-group">
<label for="filter-trigger">Trigger:</label>
@@ -39,7 +38,7 @@ const initialItems = sortWorkflows(workflowsData.items, 'title');
<button id="clear-filters" class="btn btn-secondary btn-small">Clear Filters</button>
</div>
</div>
<div class="results-count" id="results-count" aria-live="polite">{initialItems.length} of {initialItems.length} workflows</div>
<div class="resource-list" id="resource-list" role="list" set:html={renderWorkflowsHtml(initialItems)}></div>
<ContributeCTA resourceType="workflows" />
@@ -48,6 +47,7 @@ const initialItems = sortWorkflows(workflowsData.items, 'title');
</div>
<Modal />
<BackToTop />
<EmbeddedPageData filename="workflows.json" data={workflowsData} />
<script>