Working with Astro v5.14.0 to evaluate SEO implementation strategies, comparing a manual meta tag approach (80+ lines in BaseHead.astro) against the astro-seo package (142K weekly downloads) for Open Graph, Twitter Cards, and canonical URL management.
Issue
The current SEO implementation requires manual maintenance of ~80 lines of repetitive meta tags across BaseHead.astro and BlogPost.astro components. Developers must manually ensure all Open Graph properties (og:type, og:url, og:title, etc.) and Twitter Card tags are consistently implemented, with no TypeScript validation or title templating system. The repetitive pattern increases maintenance overhead and risks inconsistencies between pages.
Culprit
The root cause stems from Astro’s static HTML generation approach combined with the decision to avoid external SEO dependencies. While the current implementation covers all required SEO features (Open Graph, Twitter Cards, canonical URLs, sitemap, RSS), it:
- Lacks abstraction: Each meta tag is individually declared without a component system
- Has no validation: Missing required Open Graph properties (e.g.,
og:imagewithout dimensions) won’t fail builds - Uses manual strings: Title formatting requires manual concatenation (e.g.,
"Page Title — COMPANY") - Repeats patterns: Similar structures for OG/Twitter/Canonical tags appear across components
Example of repetitive pattern:
<meta property="og:type" content="website" />
<meta property="og:url" content={Astro.url} />
<meta property="og:title" content={title} />
<!-- 5 more OG tags -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={title} />
<!-- 4 more Twitter tags -->
Solution
After evaluating the astro-seo package, the team decided to maintain the current manual implementation based on these technical factors:
Current Implementation Strengths
- Zero dependencies: Uses native HTML without external packages
- Production-ready: All SEO features work correctly (verified via platform testing)
- Full control: Direct access to every meta tag for debugging/extending
- Performance: No build step overhead (static HTML generation)
Key Technical Rationale
-
Feature parity: Current setup already includes:
- Complete Open Graph (basic + image + article)
- Full Twitter Card support
- Canonical URLs via
Astro.url - Structured data (NewsArticle schema)
- Sitemap/RSS integration
-
DX vs. Dependency Tradeoff:
- astro-seo benefits: TypeScript autocomplete, title templates, validation
- Costs: +1 dependency, build step addition, bundle size increase
- Manual alternative: Could implement title templates with 10 lines of TypeScript
-
Maintenance Reality:
- Current 80-line implementation is stable and understood by the team
astro-seowould reduce to ~20-30 lines but add abstraction complexity
Files Maintained
src/components/BaseHead.astro: Manual meta tags (unchanged)src/layouts/BlogPost.astro: NewsArticle structured data (unchanged)package.json: No new dependencies added
Future Reevaluation Triggers
The team will reconsider astro-seo if:
- Multi-language support is added (needs
languageAlternates) - Page types exceed 10+ with varying SEO requirements
- Stricter Open Graph validation becomes critical during development
- Team prefers component-based abstraction over manual control
Reference Implementation (current approach):
<!-- BaseHead.astro -->
<meta property="og:type" content="website" />
<meta property="og:url" content={Astro.url.href} />
<meta property="og:title" content={`${title} — COMPANY`} />
<meta property="og:description" content={description} />
<meta property="og:image" content={ogImageUrl} />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />