From bd66525c85fe267731b994cfb9aff9bc33de1fa7 Mon Sep 17 00:00:00 2001 From: Gallay Lajos Date: Thu, 26 Mar 2026 09:30:20 +0100 Subject: [PATCH 1/6] adjusted tagging --- src/content/posts/001-welcome.md | 2 +- .../posts/002-getting-started-with-a-boilerplate.md | 2 +- src/content/posts/003-getting-started-with-inject.md | 2 +- .../posts/004-getting-started-with-data-stores.md | 11 ++++++++++- .../posts/005-getting-started-with-repository.md | 2 +- src/content/posts/006-getting-started-with-rest.md | 11 ++++++++++- .../007-data-validation-with-rest-and-json-schema.md | 3 +++ src/content/posts/008-byebye-extension-methods.md | 3 +++ src/content/posts/009-inject-refactor.md | 2 +- src/content/posts/010-showcase-app.md | 10 +++++++++- src/content/posts/012-gatsby-to-astro-migration.md | 2 +- src/content/posts/013-shades-vnode-refactor.md | 2 +- src/content/posts/014-showcase-updates.md | 10 +++++++++- src/content/posts/015-nested-router.md | 10 +++++++++- 14 files changed, 60 insertions(+), 12 deletions(-) diff --git a/src/content/posts/001-welcome.md b/src/content/posts/001-welcome.md index 06376d6..6e7868a 100644 --- a/src/content/posts/001-welcome.md +++ b/src/content/posts/001-welcome.md @@ -2,7 +2,7 @@ layout: post title: 'Welcome to FuryStack, Gatsby 💙' author: [gallayl] -tags: ['Welcome'] +tags: ['Announcement', 'Welcome', 'site'] image: img/001-welcome-cover.jpg date: '2021-06-23T08:38:20.257Z' draft: false diff --git a/src/content/posts/002-getting-started-with-a-boilerplate.md b/src/content/posts/002-getting-started-with-a-boilerplate.md index 8457704..b91b499 100644 --- a/src/content/posts/002-getting-started-with-a-boilerplate.md +++ b/src/content/posts/002-getting-started-with-a-boilerplate.md @@ -2,7 +2,7 @@ layout: post title: 'Getting started with the Boilerplate 🏁' author: [gallayl] -tags: ['Getting Started', 'boilerplate'] +tags: ['Getting Started', 'tutorial', 'boilerplate'] image: img/002-getting-started-with-a-boilerplate-cover.jpg date: '2021-06-23T08:48:20.257Z' draft: false diff --git a/src/content/posts/003-getting-started-with-inject.md b/src/content/posts/003-getting-started-with-inject.md index 5cf67a0..26d79e4 100644 --- a/src/content/posts/003-getting-started-with-inject.md +++ b/src/content/posts/003-getting-started-with-inject.md @@ -2,7 +2,7 @@ layout: post title: 'DI / IOC with @furystack/inject 💉' author: [gallayl] -tags: ['Getting Started', 'inject'] +tags: ['Getting Started', 'tutorial', 'dependency-injection', 'inject'] image: img/003-getting-started-with-inject-cover.jpg date: '2021-06-23T08:58:20.257Z' draft: false diff --git a/src/content/posts/004-getting-started-with-data-stores.md b/src/content/posts/004-getting-started-with-data-stores.md index c4f6a89..8251145 100644 --- a/src/content/posts/004-getting-started-with-data-stores.md +++ b/src/content/posts/004-getting-started-with-data-stores.md @@ -3,7 +3,16 @@ layout: post title: Let's store some freaking data 📦 author: [gallayl] tags: - ['Getting Started', 'core', 'filesystem-store', 'sequelize-store', 'mongodb-store', 'redis-store'] + [ + 'Getting Started', + 'tutorial', + 'data-storage', + 'core', + 'filesystem-store', + 'sequelize-store', + 'mongodb-store', + 'redis-store', + ] image: img/004-getting-started-with-data-stores-cover.jpg date: '2021-06-23T09:58:20.257Z' draft: false diff --git a/src/content/posts/005-getting-started-with-repository.md b/src/content/posts/005-getting-started-with-repository.md index d8857c5..e1717ab 100644 --- a/src/content/posts/005-getting-started-with-repository.md +++ b/src/content/posts/005-getting-started-with-repository.md @@ -2,7 +2,7 @@ layout: post title: Build a business layer with a Repository author: [gallayl] -tags: ['Getting Started', 'repository'] +tags: ['Getting Started', 'tutorial', 'data-storage', 'repository'] image: img/005-getting-started-with-repository-cover.jpg date: '2021-06-23T10:58:20.257Z' draft: false diff --git a/src/content/posts/006-getting-started-with-rest.md b/src/content/posts/006-getting-started-with-rest.md index df68028..6c41a24 100644 --- a/src/content/posts/006-getting-started-with-rest.md +++ b/src/content/posts/006-getting-started-with-rest.md @@ -2,7 +2,16 @@ layout: post title: REST in peace author: [gallayl] -tags: ['Getting Started', 'rest', 'rest-service', 'rest-client-fetch', 'rest-client-got'] +tags: + [ + 'Getting Started', + 'tutorial', + 'rest-api', + 'rest', + 'rest-service', + 'rest-client-fetch', + 'rest-client-got', + ] image: img/006-getting-started-with-rest-cover.jpg date: '2021-06-23T12:58:20.257Z' draft: false diff --git a/src/content/posts/007-data-validation-with-rest-and-json-schema.md b/src/content/posts/007-data-validation-with-rest-and-json-schema.md index 5e27205..b38940f 100644 --- a/src/content/posts/007-data-validation-with-rest-and-json-schema.md +++ b/src/content/posts/007-data-validation-with-rest-and-json-schema.md @@ -5,6 +5,9 @@ author: [gallayl] tags: [ 'Getting Started', + 'tutorial', + 'rest-api', + 'validation', 'rest', 'rest-service', 'rest-client-fetch', diff --git a/src/content/posts/008-byebye-extension-methods.md b/src/content/posts/008-byebye-extension-methods.md index 2a21131..7d5b426 100644 --- a/src/content/posts/008-byebye-extension-methods.md +++ b/src/content/posts/008-byebye-extension-methods.md @@ -4,6 +4,9 @@ title: Bye-bye extension methods author: [gallayl] tags: [ + 'Architecture', + 'refactoring', + 'breaking-changes', 'FuryStack', 'core', 'filesystem-store', diff --git a/src/content/posts/009-inject-refactor.md b/src/content/posts/009-inject-refactor.md index f31620b..a25573e 100644 --- a/src/content/posts/009-inject-refactor.md +++ b/src/content/posts/009-inject-refactor.md @@ -2,7 +2,7 @@ layout: post title: A little bit of Inject refactor author: [gallayl] -tags: ['inject'] +tags: ['Architecture', 'refactoring', 'breaking-changes', 'dependency-injection', 'inject'] image: img/009-inject-refactor.jpg date: '2022-08-12T18:00:00.257Z' draft: false diff --git a/src/content/posts/010-showcase-app.md b/src/content/posts/010-showcase-app.md index 385501b..3646100 100644 --- a/src/content/posts/010-showcase-app.md +++ b/src/content/posts/010-showcase-app.md @@ -2,7 +2,15 @@ layout: post title: Showcase-time author: [gallayl] -tags: ['shades', 'shades-common-components', 'shades-showcase-app'] +tags: + [ + 'Frontend', + 'showcase', + 'ui-components', + 'shades', + 'shades-common-components', + 'shades-showcase-app', + ] image: img/010-showcase-app.jpg date: '2022-08-16T21:00:00.257Z' draft: false diff --git a/src/content/posts/012-gatsby-to-astro-migration.md b/src/content/posts/012-gatsby-to-astro-migration.md index a6a34ab..74e9b91 100644 --- a/src/content/posts/012-gatsby-to-astro-migration.md +++ b/src/content/posts/012-gatsby-to-astro-migration.md @@ -1,7 +1,7 @@ --- title: 'Bye Gatsby, Hello Astro 🚀' author: [gallayl] -tags: ['FuryStack'] +tags: ['Announcement', 'migration', 'site', 'FuryStack'] date: '2026-03-05T12:00:00.000Z' draft: false image: img/012-astro-migration.jpg diff --git a/src/content/posts/013-shades-vnode-refactor.md b/src/content/posts/013-shades-vnode-refactor.md index 6846bfa..dbf39f5 100644 --- a/src/content/posts/013-shades-vnode-refactor.md +++ b/src/content/posts/013-shades-vnode-refactor.md @@ -1,7 +1,7 @@ --- title: 'Shades 12: The VNode Refactor' author: [gallayl] -tags: ['shades'] +tags: ['Architecture', 'Frontend', 'refactoring', 'shades'] date: '2026-03-05T18:00:00.000Z' draft: false image: img/013-vnode.jpg diff --git a/src/content/posts/014-showcase-updates.md b/src/content/posts/014-showcase-updates.md index 2d9e7fe..c5242a4 100644 --- a/src/content/posts/014-showcase-updates.md +++ b/src/content/posts/014-showcase-updates.md @@ -1,7 +1,15 @@ --- title: 'The Showcase Strikes Back' author: [gallayl] -tags: ['shades', 'shades-common-components', 'shades-showcase-app'] +tags: + [ + 'Frontend', + 'showcase', + 'ui-components', + 'shades', + 'shades-common-components', + 'shades-showcase-app', + ] date: '2026-03-07T12:00:00.000Z' draft: false image: img/014-showcase-updates.jpg diff --git a/src/content/posts/015-nested-router.md b/src/content/posts/015-nested-router.md index 493b535..01cfb06 100644 --- a/src/content/posts/015-nested-router.md +++ b/src/content/posts/015-nested-router.md @@ -1,7 +1,15 @@ --- title: 'Routing, But Make It Nested' author: [gallayl] -tags: ['shades', 'shades-common-components', 'shades-showcase-app'] +tags: + [ + 'Frontend', + 'routing', + 'ui-components', + 'shades', + 'shades-common-components', + 'shades-showcase-app', + ] date: '2026-03-12T12:00:00.000Z' draft: false image: img/015-nested-router.jpg From a1b5773f44c795525134656eee9f779766708d41 Mon Sep 17 00:00:00 2001 From: Gallay Lajos Date: Thu, 26 Mar 2026 09:30:38 +0100 Subject: [PATCH 2/6] post review skill --- .cursor/skills/review-blog-post/SKILL.md | 115 +++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 .cursor/skills/review-blog-post/SKILL.md diff --git a/.cursor/skills/review-blog-post/SKILL.md b/.cursor/skills/review-blog-post/SKILL.md new file mode 100644 index 0000000..4d2dcb9 --- /dev/null +++ b/.cursor/skills/review-blog-post/SKILL.md @@ -0,0 +1,115 @@ +--- +name: review-blog-post +description: >- + Review blog posts for the FuryStack site. Use when the user asks to review a + blog post, check tagging, validate frontmatter, or verify post conventions. + Also use when a branch contains new or modified posts and the user asks for a + review. +--- + +# Reviewing Blog Posts for FuryStack + +When reviewing a blog post, check each of the following areas and report issues grouped by severity. + +## 1. Frontmatter validation + +Posts live in `src/content/posts/` as Markdown files named `{NNN}-{slug}.md`. + +```yaml +--- +title: 'Post Title' +author: [gallayl] +tags: ['PrimaryCategory', 'thematic-tag', 'package-tag'] +date: '2026-03-12T12:00:00.000Z' +draft: false +image: img/{NNN}-{short-slug}.jpg +excerpt: One or two sentences shown on cards and in RSS. +--- +``` + +Check: + +- All required fields present: `title`, `author`, `tags`, `date`, `draft`, `excerpt`. +- `date` is a valid ISO 8601 string. +- `excerpt` is concise (1-2 sentences) — it appears on post cards and in the RSS feed. +- `image` path (if present) points to an existing file in `src/content/posts/img/`. +- File numbering is sequential (check surrounding files for gaps or collisions). + +## 2. Tagging review + +This is the most important part of the review. Tags drive post card display, related-post discovery, and package page links. + +### Tag structure + +Tags are ordered in three tiers: + +1. **Category tag** (first in the array) — displayed on post cards and the post header. +2. **Thematic tags** — cross-cutting topics that drive related-post discovery. +3. **Package tags** — `@furystack/*` package short names linking from the packages page. + +### Category tags (exactly one, must be first) + +| Tag | Use when the post... | +| ----------------- | --------------------------------------------------------------- | +| `Getting Started` | is a tutorial teaching how to use a feature | +| `Announcement` | is news, an introduction, or a site/project update | +| `Architecture` | covers design decisions, refactoring, or internals | +| `Frontend` | is about the Shades UI library, components, routing, or theming | + +### Thematic tags (at least one, all that apply) + +| Tag | Use when the post... | +| ---------------------- | ------------------------------------------------------ | +| `tutorial` | walks through steps to achieve something | +| `refactoring` | describes code or API refactoring | +| `breaking-changes` | covers breaking API changes | +| `dependency-injection` | discusses DI / IoC patterns | +| `data-storage` | is about stores, repositories, or the data layer | +| `rest-api` | covers REST API design, implementation, or consumption | +| `ui-components` | is about UI components, theming, or layout | +| `showcase` | relates to the Shades Showcase App | +| `routing` | covers client-side routing | +| `migration` | is a migration story or upgrade guide | +| `site` | is about this blog or the FuryStack website itself | +| `validation` | covers data validation or schema enforcement | + +### Package tags (for each relevant `@furystack/*` package) + +Use the npm short name (e.g. `inject`, `shades`, `rest`, `core`, `repository`). +Only tag packages that are a **primary focus** of the post. + +### Tag checklist + +- [ ] Exactly one category tag, placed first +- [ ] At least one thematic tag +- [ ] Package tags for primary packages discussed (if any) +- [ ] All tags have entries in `src/data/tags.yaml` — if not, flag as missing +- [ ] Tag order is: category, then thematic, then package + +If a new thematic tag is warranted, suggest it along with a description for `src/data/tags.yaml`. + +## 3. Content review + +- `##` should be the top heading level (the `title` field renders as `

`). +- Links to other posts use relative paths: `/posts/{slug}/`. +- Code examples have language tags on fenced blocks. +- No broken links to GitHub or internal pages. +- Tone matches existing posts: informal, direct, first person, occasional humor. + +## 4. Review output format + +``` +## Tagging +- ...issues or suggestions... + +## Frontmatter +- ...issues or suggestions... + +## Content +- ...issues or suggestions... + +## Summary +[One-line verdict: ready to publish / needs changes] +``` + +Omit sections with no issues. Always include the Summary. From b46c3062ad2199b00bdb1f326bb0f9f77e63d371 Mon Sep 17 00:00:00 2001 From: Gallay Lajos Date: Thu, 26 Mar 2026 09:48:21 +0100 Subject: [PATCH 3/6] tag updates --- src/data/tags.yaml | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/data/tags.yaml b/src/data/tags.yaml index efa22f5..16e5fad 100644 --- a/src/data/tags.yaml +++ b/src/data/tags.yaml @@ -1,10 +1,47 @@ +## Category tags (displayed as primary tag on post cards) - id: Getting Started description: Guides about basic concepts image: img/tag-getting-started.jpg +- id: Announcement + description: News, introductions, and site updates about FuryStack +- id: Architecture + description: Design decisions, refactoring, and framework internals +- id: Frontend + description: Shades UI library, components, routing, and theming + +## Thematic tags (cross-cutting topics for related post discovery) +- id: tutorial + description: Step-by-step instructional posts +- id: refactoring + description: Posts about code or API refactoring +- id: breaking-changes + description: Posts covering breaking API changes +- id: dependency-injection + description: Dependency injection and Inversion of Control patterns +- id: data-storage + description: Data stores, repositories, and the data layer +- id: rest-api + description: REST API design, implementation, and consumption +- id: ui-components + description: UI components, theming, and layout systems +- id: showcase + description: The Shades Showcase App and its evolution +- id: routing + description: Client-side routing concepts and implementations +- id: migration + description: Migration stories and upgrade guides +- id: site + description: Posts about this blog and the FuryStack website +- id: validation + description: Data validation and schema enforcement + +## General tags - id: FuryStack description: General announcements and updates about the FuryStack framework - id: Welcome description: Introductory posts about the FuryStack site and project + +## Package tags - id: boilerplate description: The Boilerplate project is your best friend if you want to get familiar with FuryStack or start a new FuryStack project image: img/tag-boilerplate.jpg From b94af9ef8de1efd20b3ffd6e3b345ba3aa5345d2 Mon Sep 17 00:00:00 2001 From: Gallay Lajos Date: Thu, 26 Mar 2026 09:48:30 +0100 Subject: [PATCH 4/6] landing page and logo updates --- src/components/icons/FuryStackLogo.astro | 194 +++++++++--------- .../icons/FuryStackLogoClassic.astro | 68 ++++++ src/components/icons/ShadesLogo.astro | 107 ++++++++++ src/pages/index.astro | 160 +++++++++++---- 4 files changed, 397 insertions(+), 132 deletions(-) create mode 100644 src/components/icons/FuryStackLogoClassic.astro create mode 100644 src/components/icons/ShadesLogo.astro diff --git a/src/components/icons/FuryStackLogo.astro b/src/components/icons/FuryStackLogo.astro index 4ccaffb..2369079 100644 --- a/src/components/icons/FuryStackLogo.astro +++ b/src/components/icons/FuryStackLogo.astro @@ -16,26 +16,32 @@ const { size = 96 } = Astro.props; > FuryStack - - - + + + - - - - + + + - - - - + + + - - - - - - + + + + + + + + + + + + + + @@ -43,110 +49,106 @@ const { size = 96 } = Astro.props; - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + diff --git a/src/components/icons/ShadesLogo.astro b/src/components/icons/ShadesLogo.astro new file mode 100644 index 0000000..7100748 --- /dev/null +++ b/src/components/icons/ShadesLogo.astro @@ -0,0 +1,107 @@ +--- +interface Props { + size?: number; +} + +const { size = 96 } = Astro.props; +--- + + + + diff --git a/src/pages/index.astro b/src/pages/index.astro index 082e504..578ff3e 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -3,6 +3,7 @@ import BaseLayout from '../layouts/BaseLayout.astro'; import PostCard from '../components/PostCard.astro'; import GitHubIcon from '../components/icons/GitHubIcon.astro'; import FuryStackLogo from '../components/icons/FuryStackLogo.astro'; +import ShadesLogo from '../components/icons/ShadesLogo.astro'; import { getCollection } from 'astro:content'; import { SITE_TITLE, SITE_DESCRIPTION, SITE_URL, SOCIAL } from '../consts'; @@ -18,9 +19,20 @@ const ogImage = `${SITE_URL}/images/blog-cover.png`;
- -

FuryStack

-

{SITE_DESCRIPTION}

+
+
+ + FuryStack + End-to-end framework +
+ + +
+ + Shades + Frontend UI library +
+
+

{SITE_DESCRIPTION}

Get Started @@ -207,55 +219,131 @@ const ogImage = `${SITE_URL}/images/blog-cover.png`; .hero-aurora { position: absolute; - inset: -50% -50%; - width: 200%; - height: 200%; - background: conic-gradient( - from 220deg at 50% 50%, - rgba(59, 130, 246, 0.18) 0deg, - rgba(99, 102, 241, 0.14) 72deg, - rgba(139, 92, 246, 0.12) 144deg, - rgba(59, 130, 246, 0.18) 216deg, - rgba(37, 99, 235, 0.1) 288deg, - rgba(59, 130, 246, 0.18) 360deg - ); - animation: aurora-rotate 20s linear infinite; + inset: 0; + overflow: hidden; pointer-events: none; + background: radial-gradient(ellipse at 65% 25%, rgba(139, 92, 246, 0.1) 0%, transparent 55%); + } + + .hero-aurora::before, + .hero-aurora::after { + content: ''; + position: absolute; + width: 50vmax; + height: 50vmax; + border-radius: 50%; + filter: blur(80px); + } + + .hero-aurora::before { + top: -15vmax; + left: -10vmax; + background: radial-gradient(circle, rgba(59, 130, 246, 0.25) 0%, transparent 70%); + animation: aurora-drift-1 14s ease-in-out infinite alternate; + } + + .hero-aurora::after { + bottom: -10vmax; + right: -8vmax; + background: radial-gradient(circle, rgba(99, 102, 241, 0.2) 0%, transparent 70%); + animation: aurora-drift-2 18s ease-in-out infinite alternate; } - @keyframes aurora-rotate { + + @keyframes aurora-drift-1 { + from { + transform: translate(0, 0) scale(1); + } + to { + transform: translate(15vw, 10vh) scale(1.1); + } + } + + @keyframes aurora-drift-2 { + from { + transform: translate(0, 0) scale(1); + } to { - transform: rotate(360deg); + transform: translate(-12vw, -8vh) scale(1.15); } } .hero-inner { position: relative; z-index: 1; - max-width: 640px; + max-width: 780px; margin: 0 auto; } - .hero-logo { - width: 96px; - height: 96px; - margin: 0 auto 24px; - filter: drop-shadow(0 0 24px rgba(59, 130, 246, 0.4)) - drop-shadow(0 0 56px rgba(99, 102, 241, 0.18)); + .hero-brands { + display: flex; + align-items: center; + justify-content: center; + gap: 24px; + margin: 0 auto 36px; + } + @media (max-width: 600px) { + .hero-brands { + flex-direction: column; + gap: 16px; + } + } + + .hero-brand-card { + display: flex; + flex-direction: column; + align-items: center; + gap: 14px; + padding: 32px 40px 24px; + background: rgba(255, 255, 255, 0.04); + border: 1px solid rgba(255, 255, 255, 0.08); + border-radius: 20px; + backdrop-filter: blur(8px); + transition: + transform 0.3s ease, + border-color 0.3s ease, + box-shadow 0.3s ease; + } + .hero-brand-card:hover { + transform: translateY(-3px); + border-color: rgba(255, 255, 255, 0.14); + box-shadow: 0 8px 32px rgba(59, 130, 246, 0.15); + } + @media (max-width: 600px) { + .hero-brand-card { + flex-direction: row; + gap: 20px; + padding: 20px 28px; + width: 100%; + } + } + + .hero-brand-name { + font-size: 1.8rem; + font-weight: 700; + letter-spacing: -0.01em; + color: #fff; + } + + .hero-brand-tagline { + font-size: 1.2rem; + color: rgba(255, 255, 255, 0.45); + font-weight: 400; + } + @media (max-width: 600px) { + .hero-brand-tagline { + display: none; + } } - .hero-title { - font-size: 5.2rem; - font-weight: 800; - letter-spacing: -0.03em; - margin-bottom: 12px; - background: linear-gradient(135deg, #60a5fa 0%, #a78bfa 50%, #818cf8 100%); - -webkit-background-clip: text; - background-clip: text; - -webkit-text-fill-color: transparent; + .hero-brand-plus { + font-size: 2rem; + font-weight: 300; + color: rgba(255, 255, 255, 0.25); + flex-shrink: 0; } @media (max-width: 600px) { - .hero-title { - font-size: 3.6rem; + .hero-brand-plus { + display: none; } } From 267af5f46264e5defd364f546b0cc35edcf9773a Mon Sep 17 00:00:00 2001 From: Gallay Lajos Date: Thu, 26 Mar 2026 10:03:05 +0100 Subject: [PATCH 5/6] updated logos, favicons, getting started guide --- public/favicon.ico | Bin 15086 -> 6541 bytes public/favicon.svg | 29 + src/components/Footer.astro | 13 +- src/components/SiteNav.astro | 13 +- src/consts.ts | 1 - .../002-getting-started-with-a-boilerplate.md | 2 + src/layouts/BaseLayout.astro | 3 +- src/pages/getting-started/boilerplate.astro | 295 +++++++++ src/pages/getting-started/from-scratch.astro | 595 ++++++++++++++++++ src/pages/getting-started/index.astro | 250 ++++++++ src/pages/index.astro | 2 +- 11 files changed, 1187 insertions(+), 16 deletions(-) create mode 100644 public/favicon.svg create mode 100644 src/pages/getting-started/boilerplate.astro create mode 100644 src/pages/getting-started/from-scratch.astro create mode 100644 src/pages/getting-started/index.astro diff --git a/public/favicon.ico b/public/favicon.ico index db6ad813ffcff15a23ac02d1828a194b708689ba..7753255dcbea3d990d80f313899b9e313d39bb7f 100644 GIT binary patch literal 6541 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 literal 15086 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/components/Footer.astro b/src/components/Footer.astro index 9f66806..014d327 100644 --- a/src/components/Footer.astro +++ b/src/components/Footer.astro @@ -1,7 +1,6 @@ --- -import { Image } from 'astro:assets'; import { SITE_TITLE, SOCIAL } from '../consts'; -import logo from '../../public/images/furystack-logo-512.png'; +import FuryStackLogo from './icons/FuryStackLogo.astro'; ---