@zoyth/simple-site-framework 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +572 -0
- package/bin/create-simple-site.js +390 -0
- package/bin/simple-site.js +664 -0
- package/dist/client.js +135 -0
- package/dist/client.js.map +1 -0
- package/dist/client.mjs +107 -0
- package/dist/client.mjs.map +1 -0
- package/dist/components/index.d.mts +3936 -0
- package/dist/components/index.d.ts +3936 -0
- package/dist/components/index.js +38265 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/index.mjs +38173 -0
- package/dist/components/index.mjs.map +1 -0
- package/dist/config/index.d.mts +298 -0
- package/dist/config/index.d.ts +298 -0
- package/dist/config/index.js +19 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/index.mjs +1 -0
- package/dist/config/index.mjs.map +1 -0
- package/dist/index.d.mts +2184 -0
- package/dist/index.d.ts +2184 -0
- package/dist/index.js +1713 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1605 -0
- package/dist/index.mjs.map +1 -0
- package/dist/lib/i18n/index.js +665 -0
- package/dist/lib/i18n/index.js.map +1 -0
- package/dist/lib/i18n/index.mjs +621 -0
- package/dist/lib/i18n/index.mjs.map +1 -0
- package/docs/DOCUMENTATION-STRUCTURE.md +1156 -0
- package/docs/EXPORTS.md +125 -0
- package/docs/PERFORMANCE.md +757 -0
- package/docs/POLICY-PAGES.md +867 -0
- package/docs/ROADMAP.md +334 -0
- package/docs/SEO.md +455 -0
- package/docs/SITEMAP.md +708 -0
- package/docs/STRUCTURED-DATA.md +671 -0
- package/docs/accessibility/common-patterns.md +529 -0
- package/docs/accessibility/keyboard-navigation.md +263 -0
- package/docs/accessibility/overview.md +122 -0
- package/docs/accessibility/screen-readers.md +311 -0
- package/docs/accessibility/wcag-compliance.md +159 -0
- package/docs/api/README.md +164 -0
- package/docs/api/components/Accessibility.md +356 -0
- package/docs/api/components/Button.md +240 -0
- package/docs/api/components/HeroSection.md +306 -0
- package/docs/architecture/decisions.md +449 -0
- package/docs/components/AnalyticsTracker.md +58 -0
- package/docs/components/AnimatedCounter.md +48 -0
- package/docs/components/AnimatedSection.md +56 -0
- package/docs/components/BlogCard.md +42 -0
- package/docs/components/Checkbox.md +56 -0
- package/docs/components/CodeBlock.md +52 -0
- package/docs/components/ComparisonTable.md +40 -0
- package/docs/components/ComponentDemo.md +38 -0
- package/docs/components/CountdownTimer.md +51 -0
- package/docs/components/ExitIntentModal.md +56 -0
- package/docs/components/FAQAccordion.md +66 -0
- package/docs/components/FeaturesGrid.md +55 -0
- package/docs/components/FileUpload.md +54 -0
- package/docs/components/I18nMetaTags.md +55 -0
- package/docs/components/Icon.md +53 -0
- package/docs/components/LazySection.md +46 -0
- package/docs/components/LiveProof.md +53 -0
- package/docs/components/LoadingSpinner.md +46 -0
- package/docs/components/MultiStepForm.md +48 -0
- package/docs/components/PolicyLayout.md +55 -0
- package/docs/components/PricingTable.md +49 -0
- package/docs/components/Radio.md +59 -0
- package/docs/components/SEOMetaTags.md +58 -0
- package/docs/components/ScriptInjector.md +50 -0
- package/docs/components/Select.md +72 -0
- package/docs/components/Skeleton.md +47 -0
- package/docs/components/StatsSection.md +48 -0
- package/docs/components/StickyBar.md +62 -0
- package/docs/components/StructuredData.md +99 -0
- package/docs/components/StyleGuide.md +46 -0
- package/docs/components/TableOfContents.md +47 -0
- package/docs/components/TestimonialCarousel.md +42 -0
- package/docs/components/Timeline.md +51 -0
- package/docs/components/Toast.md +59 -0
- package/docs/components/TrackedLink.md +62 -0
- package/docs/components/TrustBadges.md +44 -0
- package/docs/components/conversion/MobileCTA.md +363 -0
- package/docs/components/forms/ContactForm.md +75 -0
- package/docs/components/forms/FormField.md +74 -0
- package/docs/components/layout/Footer.md +601 -0
- package/docs/components/layout/Header.md +549 -0
- package/docs/components/layout/LanguageSelector.md +54 -0
- package/docs/components/layout/LanguageSwitcher.md +24 -0
- package/docs/components/overview.md +447 -0
- package/docs/components/sections/AboutSection.md +48 -0
- package/docs/components/sections/CTASection.md +596 -0
- package/docs/components/sections/CaseStudySection.md +47 -0
- package/docs/components/sections/ContactSection.md +599 -0
- package/docs/components/sections/FeatureSection.md +44 -0
- package/docs/components/sections/HeroSection.md +404 -0
- package/docs/components/sections/LogosSection.md +47 -0
- package/docs/components/sections/PersonalTaxesSection.md +23 -0
- package/docs/components/sections/RecruitingSection.md +23 -0
- package/docs/components/sections/SecurePortalSection.md +23 -0
- package/docs/components/sections/ServicePageLayout.md +52 -0
- package/docs/components/sections/ServicesSection.md +49 -0
- package/docs/components/sections/TestimonialSection.md +44 -0
- package/docs/components/sections/WhyChooseUsSection.md +54 -0
- package/docs/components/ui/Breadcrumb.md +70 -0
- package/docs/components/ui/Button.md +514 -0
- package/docs/components/ui/Card.md +501 -0
- package/docs/components/ui/Input.md +54 -0
- package/docs/components/ui/MobileLinks.md +43 -0
- package/docs/components/ui/Modal.md +60 -0
- package/docs/components/ui/Tabs.md +62 -0
- package/docs/components/ui/Textarea.md +52 -0
- package/docs/core-concepts/configuration-driven.md +552 -0
- package/docs/core-concepts/overview.md +351 -0
- package/docs/features/accessibility/README.md +73 -0
- package/docs/features/accessibility/aria-support.md +177 -0
- package/docs/features/accessibility/color-contrast.md +155 -0
- package/docs/features/accessibility/focus-management.md +187 -0
- package/docs/features/accessibility/testing.md +196 -0
- package/docs/features/analytics/README.md +51 -0
- package/docs/features/analytics/ab-testing.md +171 -0
- package/docs/features/analytics/conversion-tracking.md +207 -0
- package/docs/features/analytics/custom-events.md +219 -0
- package/docs/features/analytics/privacy.md +198 -0
- package/docs/features/analytics/setup.md +114 -0
- package/docs/features/analytics/tracking-events.md +224 -0
- package/docs/features/i18n/README.md +51 -0
- package/docs/features/i18n/best-practices.md +273 -0
- package/docs/features/i18n/configuration.md +84 -0
- package/docs/features/i18n/formatting.md +133 -0
- package/docs/features/i18n/locale-detection.md +122 -0
- package/docs/features/i18n/routing.md +99 -0
- package/docs/features/i18n/rtl-support.md +191 -0
- package/docs/features/i18n/translations.md +129 -0
- package/docs/features/internationalization.md +595 -0
- package/docs/features/performance/README.md +77 -0
- package/docs/features/performance/bundle-size.md +134 -0
- package/docs/features/performance/caching.md +131 -0
- package/docs/features/performance/code-splitting.md +121 -0
- package/docs/features/performance/image-optimization.md +110 -0
- package/docs/features/performance/lazy-loading.md +92 -0
- package/docs/features/performance/monitoring.md +148 -0
- package/docs/features/seo/README.md +51 -0
- package/docs/features/seo/best-practices.md +184 -0
- package/docs/features/seo/canonical-urls.md +182 -0
- package/docs/features/seo/meta-tags.md +126 -0
- package/docs/features/seo/open-graph.md +166 -0
- package/docs/features/seo/robots-txt.md +146 -0
- package/docs/features/seo/sitemaps.md +162 -0
- package/docs/features/seo/structured-data.md +166 -0
- package/docs/getting-started/installation.md +292 -0
- package/docs/getting-started/introduction.md +195 -0
- package/docs/getting-started/quick-start.md +460 -0
- package/docs/guides/analytics-setup.md +616 -0
- package/docs/i18n/CONFIGURATION.md +353 -0
- package/docs/i18n/EXAMPLES.md +402 -0
- package/docs/i18n/MIGRATION.md +260 -0
- package/docs/i18n/SEO.md +392 -0
- package/docs/i18n/STATIC-GENERATION-FIX.md +71 -0
- package/docs/migration/changelog.md +136 -0
- package/docs/migration/overview.md +233 -0
- package/docs/recipes/adding-animations.md +475 -0
- package/docs/recipes/forms-with-validation.md +393 -0
- package/package.json +152 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# Performance Monitoring
|
|
2
|
+
|
|
3
|
+
Measure, track, and improve site performance.
|
|
4
|
+
|
|
5
|
+
## Core Web Vitals
|
|
6
|
+
|
|
7
|
+
The three metrics Google uses for page experience ranking:
|
|
8
|
+
|
|
9
|
+
### LCP (Largest Contentful Paint)
|
|
10
|
+
|
|
11
|
+
Time until the largest visible content element renders.
|
|
12
|
+
|
|
13
|
+
| Rating | Threshold |
|
|
14
|
+
|--------|-----------|
|
|
15
|
+
| Good | < 2.5s |
|
|
16
|
+
| Needs Improvement | 2.5s - 4.0s |
|
|
17
|
+
| Poor | > 4.0s |
|
|
18
|
+
|
|
19
|
+
**Improve LCP:**
|
|
20
|
+
- Use `priority` on hero images
|
|
21
|
+
- Preload critical fonts
|
|
22
|
+
- Minimize render-blocking resources
|
|
23
|
+
|
|
24
|
+
### FID / INP (First Input Delay / Interaction to Next Paint)
|
|
25
|
+
|
|
26
|
+
Time from user interaction to browser response.
|
|
27
|
+
|
|
28
|
+
| Rating | Threshold |
|
|
29
|
+
|--------|-----------|
|
|
30
|
+
| Good | < 100ms (FID) / < 200ms (INP) |
|
|
31
|
+
| Needs Improvement | 100-300ms / 200-500ms |
|
|
32
|
+
| Poor | > 300ms / > 500ms |
|
|
33
|
+
|
|
34
|
+
**Improve FID/INP:**
|
|
35
|
+
- Minimize client-side JavaScript
|
|
36
|
+
- Use Server Components
|
|
37
|
+
- Break up long tasks
|
|
38
|
+
|
|
39
|
+
### CLS (Cumulative Layout Shift)
|
|
40
|
+
|
|
41
|
+
Visual stability - how much content shifts during load.
|
|
42
|
+
|
|
43
|
+
| Rating | Threshold |
|
|
44
|
+
|--------|-----------|
|
|
45
|
+
| Good | < 0.1 |
|
|
46
|
+
| Needs Improvement | 0.1 - 0.25 |
|
|
47
|
+
| Poor | > 0.25 |
|
|
48
|
+
|
|
49
|
+
**Improve CLS:**
|
|
50
|
+
- Set explicit width/height on images
|
|
51
|
+
- Reserve space for dynamic content
|
|
52
|
+
- Avoid inserting content above existing content
|
|
53
|
+
|
|
54
|
+
## Measurement Tools
|
|
55
|
+
|
|
56
|
+
### Google PageSpeed Insights
|
|
57
|
+
|
|
58
|
+
Test any URL:
|
|
59
|
+
- [PageSpeed Insights](https://pagespeed.web.dev/)
|
|
60
|
+
- Provides both lab and field data
|
|
61
|
+
- Actionable recommendations
|
|
62
|
+
|
|
63
|
+
### Chrome DevTools Lighthouse
|
|
64
|
+
|
|
65
|
+
1. Open DevTools (F12)
|
|
66
|
+
2. Go to Lighthouse tab
|
|
67
|
+
3. Select "Performance"
|
|
68
|
+
4. Run audit
|
|
69
|
+
|
|
70
|
+
### Google Search Console
|
|
71
|
+
|
|
72
|
+
Monitor real-user data:
|
|
73
|
+
1. Search Console > Core Web Vitals
|
|
74
|
+
2. See URL-level performance
|
|
75
|
+
3. Track improvements over time
|
|
76
|
+
|
|
77
|
+
### Chrome DevTools Performance Tab
|
|
78
|
+
|
|
79
|
+
Detailed analysis:
|
|
80
|
+
1. Open DevTools > Performance
|
|
81
|
+
2. Click Record
|
|
82
|
+
3. Interact with page
|
|
83
|
+
4. Stop recording
|
|
84
|
+
5. Analyze flame chart
|
|
85
|
+
|
|
86
|
+
## Web Vitals in Code
|
|
87
|
+
|
|
88
|
+
Track Core Web Vitals programmatically:
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
// app/layout.tsx
|
|
92
|
+
import { useReportWebVitals } from 'next/web-vitals';
|
|
93
|
+
|
|
94
|
+
export function WebVitalsReporter() {
|
|
95
|
+
useReportWebVitals((metric) => {
|
|
96
|
+
// Send to analytics
|
|
97
|
+
trackEvent('web_vital', {
|
|
98
|
+
name: metric.name, // CLS, FID, LCP, etc.
|
|
99
|
+
value: metric.value,
|
|
100
|
+
rating: metric.rating, // good, needs-improvement, poor
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Performance Budgets
|
|
109
|
+
|
|
110
|
+
Set budgets and alert when exceeded:
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
// next.config.js
|
|
114
|
+
module.exports = {
|
|
115
|
+
experimental: {
|
|
116
|
+
// Warn when page JS exceeds budget
|
|
117
|
+
largePageDataBytes: 128 * 1000, // 128KB
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Monitoring Checklist
|
|
123
|
+
|
|
124
|
+
### Weekly
|
|
125
|
+
|
|
126
|
+
- [ ] Check Core Web Vitals in Search Console
|
|
127
|
+
- [ ] Review PageSpeed Insights for key pages
|
|
128
|
+
- [ ] Check build output for bundle size changes
|
|
129
|
+
|
|
130
|
+
### Per Release
|
|
131
|
+
|
|
132
|
+
- [ ] Run Lighthouse on key pages
|
|
133
|
+
- [ ] Compare bundle sizes with previous build
|
|
134
|
+
- [ ] Test on slow network (Chrome DevTools > Network > Slow 3G)
|
|
135
|
+
- [ ] Test on low-end device simulation
|
|
136
|
+
|
|
137
|
+
### Monthly
|
|
138
|
+
|
|
139
|
+
- [ ] Review real-user performance data
|
|
140
|
+
- [ ] Identify pages with poor metrics
|
|
141
|
+
- [ ] Plan performance improvements
|
|
142
|
+
- [ ] Update performance budgets if needed
|
|
143
|
+
|
|
144
|
+
## See Also
|
|
145
|
+
|
|
146
|
+
- [Bundle Size](./bundle-size.md)
|
|
147
|
+
- [Lazy Loading](./lazy-loading.md)
|
|
148
|
+
- [Existing Performance Documentation](../../PERFORMANCE.md)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# SEO
|
|
2
|
+
|
|
3
|
+
Search engine optimization tools and components.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Simple Site Framework provides built-in SEO support:
|
|
8
|
+
|
|
9
|
+
- Meta tag management
|
|
10
|
+
- Structured data (Schema.org)
|
|
11
|
+
- XML sitemap generation
|
|
12
|
+
- Open Graph / social media previews
|
|
13
|
+
- Canonical URL management
|
|
14
|
+
- Multi-language SEO (hreflang)
|
|
15
|
+
|
|
16
|
+
## Quick Start
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
import { SEOMetaTags, StructuredData } from '@zoyth/simple-site-framework/components';
|
|
20
|
+
|
|
21
|
+
<SEOMetaTags
|
|
22
|
+
title="My Page"
|
|
23
|
+
description="Page description for search results"
|
|
24
|
+
canonical="https://example.com/page"
|
|
25
|
+
/>
|
|
26
|
+
|
|
27
|
+
<StructuredData
|
|
28
|
+
data={{
|
|
29
|
+
'@type': 'Organization',
|
|
30
|
+
name: 'My Company',
|
|
31
|
+
url: 'https://example.com',
|
|
32
|
+
}}
|
|
33
|
+
/>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Topics
|
|
37
|
+
|
|
38
|
+
- [Meta Tags](./meta-tags.md) - Title, description, and meta tags
|
|
39
|
+
- [Structured Data](./structured-data.md) - Schema.org JSON-LD markup
|
|
40
|
+
- [Sitemaps](./sitemaps.md) - XML sitemap generation
|
|
41
|
+
- [Open Graph](./open-graph.md) - Social media preview cards
|
|
42
|
+
- [Robots.txt](./robots-txt.md) - Search engine crawl rules
|
|
43
|
+
- [Canonical URLs](./canonical-urls.md) - Canonical URL management
|
|
44
|
+
- [Best Practices](./best-practices.md) - SEO optimization tips
|
|
45
|
+
|
|
46
|
+
## See Also
|
|
47
|
+
|
|
48
|
+
- [SEO Optimization Guide](../../guides/seo-optimization.md)
|
|
49
|
+
- [SEOMetaTags Component](../../components/SEOMetaTags.md)
|
|
50
|
+
- [StructuredData Component](../../components/StructuredData.md)
|
|
51
|
+
- [Existing SEO Documentation](../../SEO.md)
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# SEO Best Practices
|
|
2
|
+
|
|
3
|
+
Optimization guidelines for search engine visibility.
|
|
4
|
+
|
|
5
|
+
## Technical SEO Checklist
|
|
6
|
+
|
|
7
|
+
### Must Have
|
|
8
|
+
|
|
9
|
+
- [ ] Unique title and description per page
|
|
10
|
+
- [ ] Canonical URLs on all pages
|
|
11
|
+
- [ ] XML sitemap submitted to Search Console
|
|
12
|
+
- [ ] robots.txt configured
|
|
13
|
+
- [ ] HTTPS enabled
|
|
14
|
+
- [ ] Mobile-responsive design
|
|
15
|
+
- [ ] Fast page load times
|
|
16
|
+
|
|
17
|
+
### Recommended
|
|
18
|
+
|
|
19
|
+
- [ ] Structured data (Schema.org) on key pages
|
|
20
|
+
- [ ] Open Graph tags for social sharing
|
|
21
|
+
- [ ] hreflang tags for multi-language sites
|
|
22
|
+
- [ ] Breadcrumb navigation with structured data
|
|
23
|
+
- [ ] Image alt text on all images
|
|
24
|
+
- [ ] Internal linking between related pages
|
|
25
|
+
|
|
26
|
+
## Page Speed
|
|
27
|
+
|
|
28
|
+
Search engines favor fast sites. Use framework performance features:
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
import { LazySection } from '@zoyth/simple-site-framework/components';
|
|
32
|
+
|
|
33
|
+
// Lazy-load below-the-fold sections
|
|
34
|
+
<LazySection>
|
|
35
|
+
<TestimonialSection testimonials={testimonials} />
|
|
36
|
+
</LazySection>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Key metrics:
|
|
40
|
+
- **LCP** (Largest Contentful Paint): < 2.5s
|
|
41
|
+
- **FID** (First Input Delay): < 100ms
|
|
42
|
+
- **CLS** (Cumulative Layout Shift): < 0.1
|
|
43
|
+
|
|
44
|
+
## Content Optimization
|
|
45
|
+
|
|
46
|
+
### Headings
|
|
47
|
+
|
|
48
|
+
Use proper heading hierarchy:
|
|
49
|
+
|
|
50
|
+
```tsx
|
|
51
|
+
<h1>Main Page Title</h1> {/* One per page */}
|
|
52
|
+
<h2>Section Title</h2> {/* Major sections */}
|
|
53
|
+
<h3>Sub-section</h3> {/* Sub-sections */}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Internal Linking
|
|
57
|
+
|
|
58
|
+
Link related content to distribute page authority:
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
<TrackedLink href="/services/tax-preparation">
|
|
62
|
+
Learn about our tax services
|
|
63
|
+
</TrackedLink>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Image SEO
|
|
67
|
+
|
|
68
|
+
Always include descriptive alt text:
|
|
69
|
+
|
|
70
|
+
```tsx
|
|
71
|
+
<img
|
|
72
|
+
src="/team-photo.jpg"
|
|
73
|
+
alt="Our accounting team in the Montreal office"
|
|
74
|
+
width={800}
|
|
75
|
+
height={600}
|
|
76
|
+
/>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## URL Structure
|
|
80
|
+
|
|
81
|
+
### Clean URLs
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
✅ /services/tax-preparation
|
|
85
|
+
✅ /about
|
|
86
|
+
✅ /blog/getting-started-guide
|
|
87
|
+
|
|
88
|
+
❌ /page?id=123
|
|
89
|
+
❌ /services/tax_preparation_page_v2
|
|
90
|
+
❌ /p/123/svc
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Locale URLs
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
✅ /fr/services/preparation-impots (French)
|
|
97
|
+
✅ /services/tax-preparation (English default)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Multi-Language SEO
|
|
101
|
+
|
|
102
|
+
### Required Tags
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
// On every localized page
|
|
106
|
+
<SEOMetaTags
|
|
107
|
+
title={localizedTitle}
|
|
108
|
+
description={localizedDescription}
|
|
109
|
+
canonical={canonicalUrl}
|
|
110
|
+
/>
|
|
111
|
+
|
|
112
|
+
<I18nMetaTags
|
|
113
|
+
currentLocale={locale}
|
|
114
|
+
pathname={pathname}
|
|
115
|
+
baseUrl="https://example.com"
|
|
116
|
+
/>
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Separate Content
|
|
120
|
+
|
|
121
|
+
Each locale should have unique, translated content - not machine-translated copies.
|
|
122
|
+
|
|
123
|
+
### Localized URLs
|
|
124
|
+
|
|
125
|
+
Use translated slugs when possible:
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
/en/services/tax-preparation
|
|
129
|
+
/fr/services/preparation-impots
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Common SEO Mistakes
|
|
133
|
+
|
|
134
|
+
### Duplicate Content
|
|
135
|
+
|
|
136
|
+
- Missing canonical tags
|
|
137
|
+
- Same content on multiple URLs
|
|
138
|
+
- HTTP and HTTPS both accessible
|
|
139
|
+
- www and non-www both accessible
|
|
140
|
+
|
|
141
|
+
### Missing Meta Tags
|
|
142
|
+
|
|
143
|
+
- No meta description (search engine generates one)
|
|
144
|
+
- Generic titles ("Home", "Page 1")
|
|
145
|
+
- Same title on every page
|
|
146
|
+
|
|
147
|
+
### Poor Mobile Experience
|
|
148
|
+
|
|
149
|
+
- Non-responsive layouts
|
|
150
|
+
- Small tap targets
|
|
151
|
+
- Content wider than viewport
|
|
152
|
+
- Interstitials blocking content
|
|
153
|
+
|
|
154
|
+
### Slow Performance
|
|
155
|
+
|
|
156
|
+
- Large unoptimized images
|
|
157
|
+
- Blocking JavaScript
|
|
158
|
+
- No lazy loading for below-the-fold content
|
|
159
|
+
- Missing caching headers
|
|
160
|
+
|
|
161
|
+
## Monitoring
|
|
162
|
+
|
|
163
|
+
### Google Search Console
|
|
164
|
+
|
|
165
|
+
- Monitor indexing status
|
|
166
|
+
- Check for crawl errors
|
|
167
|
+
- Review search performance
|
|
168
|
+
- Submit sitemaps
|
|
169
|
+
- Test URLs
|
|
170
|
+
|
|
171
|
+
### Core Web Vitals
|
|
172
|
+
|
|
173
|
+
Monitor in:
|
|
174
|
+
- Google Search Console > Core Web Vitals
|
|
175
|
+
- PageSpeed Insights
|
|
176
|
+
- Chrome DevTools > Lighthouse
|
|
177
|
+
|
|
178
|
+
## See Also
|
|
179
|
+
|
|
180
|
+
- [Meta Tags](./meta-tags.md)
|
|
181
|
+
- [Structured Data](./structured-data.md)
|
|
182
|
+
- [Sitemaps](./sitemaps.md)
|
|
183
|
+
- [Performance Features](../performance/README.md)
|
|
184
|
+
- [Existing SEO Documentation](../../SEO.md)
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# Canonical URLs
|
|
2
|
+
|
|
3
|
+
Prevent duplicate content issues with canonical URL management.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Canonical URLs tell search engines which version of a page is the "official" one, preventing duplicate content penalties when the same content is accessible at multiple URLs.
|
|
8
|
+
|
|
9
|
+
## Setting Canonical URLs
|
|
10
|
+
|
|
11
|
+
### Via SEOMetaTags
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { SEOMetaTags } from '@zoyth/simple-site-framework/components';
|
|
15
|
+
|
|
16
|
+
<SEOMetaTags
|
|
17
|
+
title="About Us"
|
|
18
|
+
description="Learn about our company"
|
|
19
|
+
canonical="https://example.com/about"
|
|
20
|
+
/>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Via Next.js Metadata
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
// app/about/page.tsx
|
|
27
|
+
export const metadata = {
|
|
28
|
+
alternates: {
|
|
29
|
+
canonical: 'https://example.com/about',
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## When Canonicals Matter
|
|
35
|
+
|
|
36
|
+
### Trailing Slashes
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
https://example.com/about
|
|
40
|
+
https://example.com/about/
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Set canonical to one version consistently.
|
|
44
|
+
|
|
45
|
+
### Query Parameters
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
https://example.com/products
|
|
49
|
+
https://example.com/products?sort=price
|
|
50
|
+
https://example.com/products?page=2
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Canonical should point to the base URL (without parameters) unless the parameter creates unique content.
|
|
54
|
+
|
|
55
|
+
### HTTP vs HTTPS
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
http://example.com/about
|
|
59
|
+
https://example.com/about
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Always canonicalize to HTTPS.
|
|
63
|
+
|
|
64
|
+
### WWW vs Non-WWW
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
https://www.example.com/about
|
|
68
|
+
https://example.com/about
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Pick one and canonicalize consistently.
|
|
72
|
+
|
|
73
|
+
## Multi-Language Canonicals
|
|
74
|
+
|
|
75
|
+
Each locale should have its own canonical:
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
// English page
|
|
79
|
+
<SEOMetaTags
|
|
80
|
+
canonical="https://example.com/about"
|
|
81
|
+
/>
|
|
82
|
+
|
|
83
|
+
// French page
|
|
84
|
+
<SEOMetaTags
|
|
85
|
+
canonical="https://example.com/fr/about"
|
|
86
|
+
/>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Combined with hreflang tags:
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
import { I18nMetaTags } from '@zoyth/simple-site-framework/components';
|
|
93
|
+
|
|
94
|
+
<I18nMetaTags
|
|
95
|
+
currentLocale={locale}
|
|
96
|
+
pathname="/about"
|
|
97
|
+
baseUrl="https://example.com"
|
|
98
|
+
/>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
This generates:
|
|
102
|
+
```html
|
|
103
|
+
<link rel="alternate" hreflang="en" href="https://example.com/about" />
|
|
104
|
+
<link rel="alternate" hreflang="fr" href="https://example.com/fr/about" />
|
|
105
|
+
<link rel="alternate" hreflang="x-default" href="https://example.com/about" />
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Dynamic Canonical URLs
|
|
109
|
+
|
|
110
|
+
Generate canonicals from route parameters:
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
// app/[locale]/services/[slug]/page.tsx
|
|
114
|
+
export default function ServicePage({ params }) {
|
|
115
|
+
const { locale, slug } = params;
|
|
116
|
+
const baseUrl = 'https://example.com';
|
|
117
|
+
const canonical = locale === 'en'
|
|
118
|
+
? `${baseUrl}/services/${slug}`
|
|
119
|
+
: `${baseUrl}/${locale}/services/${slug}`;
|
|
120
|
+
|
|
121
|
+
return (
|
|
122
|
+
<SEOMetaTags
|
|
123
|
+
title={service.title}
|
|
124
|
+
description={service.description}
|
|
125
|
+
canonical={canonical}
|
|
126
|
+
/>
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Common Mistakes
|
|
132
|
+
|
|
133
|
+
### Self-Referencing Canonicals
|
|
134
|
+
|
|
135
|
+
Every page should have a canonical pointing to itself (this is correct, not a mistake):
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
// ✅ Good - self-referencing canonical
|
|
139
|
+
<SEOMetaTags canonical="https://example.com/about" />
|
|
140
|
+
// on the page https://example.com/about
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Missing Canonicals
|
|
144
|
+
|
|
145
|
+
Pages without canonicals may confuse search engines:
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
// ❌ Bad - no canonical
|
|
149
|
+
<SEOMetaTags title="About" description="..." />
|
|
150
|
+
|
|
151
|
+
// ✅ Good - always include canonical
|
|
152
|
+
<SEOMetaTags
|
|
153
|
+
title="About"
|
|
154
|
+
description="..."
|
|
155
|
+
canonical="https://example.com/about"
|
|
156
|
+
/>
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Relative URLs
|
|
160
|
+
|
|
161
|
+
Always use absolute URLs:
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
// ❌ Bad
|
|
165
|
+
<SEOMetaTags canonical="/about" />
|
|
166
|
+
|
|
167
|
+
// ✅ Good
|
|
168
|
+
<SEOMetaTags canonical="https://example.com/about" />
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Verification
|
|
172
|
+
|
|
173
|
+
Check canonical tags in:
|
|
174
|
+
1. Page source (View Source)
|
|
175
|
+
2. Google Search Console > URL Inspection
|
|
176
|
+
3. Browser DevTools > Elements > `<head>`
|
|
177
|
+
|
|
178
|
+
## See Also
|
|
179
|
+
|
|
180
|
+
- [Meta Tags](./meta-tags.md)
|
|
181
|
+
- [Sitemaps](./sitemaps.md)
|
|
182
|
+
- [I18nMetaTags Component](../../components/I18nMetaTags.md)
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Meta Tags
|
|
2
|
+
|
|
3
|
+
Configure page titles, descriptions, and meta tags for search engines.
|
|
4
|
+
|
|
5
|
+
## SEOMetaTags Component
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { SEOMetaTags } from '@zoyth/simple-site-framework/components';
|
|
9
|
+
|
|
10
|
+
<SEOMetaTags
|
|
11
|
+
title="About Us | My Company"
|
|
12
|
+
description="Learn about our team and mission"
|
|
13
|
+
canonical="https://example.com/about"
|
|
14
|
+
keywords={['company', 'about', 'team']}
|
|
15
|
+
robots="index, follow"
|
|
16
|
+
/>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Props
|
|
20
|
+
|
|
21
|
+
| Prop | Type | Required | Description |
|
|
22
|
+
|------|------|----------|-------------|
|
|
23
|
+
| `title` | `string` | Yes | Page title (displayed in browser tab and search results) |
|
|
24
|
+
| `description` | `string` | Yes | Meta description (displayed in search result snippets) |
|
|
25
|
+
| `canonical` | `string` | No | Canonical URL for the page |
|
|
26
|
+
| `keywords` | `string[]` | No | Meta keywords (low SEO value but still used) |
|
|
27
|
+
| `robots` | `string` | No | Robots directive (default: 'index, follow') |
|
|
28
|
+
| `openGraph` | `OpenGraphProps` | No | Open Graph metadata |
|
|
29
|
+
| `twitter` | `TwitterProps` | No | Twitter Card metadata |
|
|
30
|
+
|
|
31
|
+
## Page Titles
|
|
32
|
+
|
|
33
|
+
### Format
|
|
34
|
+
|
|
35
|
+
Follow consistent title patterns:
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
// Page title | Site name
|
|
39
|
+
<SEOMetaTags title="About Us | My Company" />
|
|
40
|
+
|
|
41
|
+
// For homepage
|
|
42
|
+
<SEOMetaTags title="My Company - Professional Services" />
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Guidelines
|
|
46
|
+
|
|
47
|
+
- 50-60 characters maximum
|
|
48
|
+
- Include primary keyword
|
|
49
|
+
- Place important words first
|
|
50
|
+
- Include brand name
|
|
51
|
+
|
|
52
|
+
## Meta Descriptions
|
|
53
|
+
|
|
54
|
+
### Guidelines
|
|
55
|
+
|
|
56
|
+
- 150-160 characters maximum
|
|
57
|
+
- Include target keywords naturally
|
|
58
|
+
- Write compelling copy that encourages clicks
|
|
59
|
+
- Unique per page
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
<SEOMetaTags
|
|
63
|
+
description="Get professional accounting services tailored to small businesses. Free consultation available."
|
|
64
|
+
/>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Robots Directives
|
|
68
|
+
|
|
69
|
+
Control search engine behavior:
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
// Default - index and follow links
|
|
73
|
+
<SEOMetaTags robots="index, follow" />
|
|
74
|
+
|
|
75
|
+
// Don't index but follow links
|
|
76
|
+
<SEOMetaTags robots="noindex, follow" />
|
|
77
|
+
|
|
78
|
+
// Don't index or follow
|
|
79
|
+
<SEOMetaTags robots="noindex, nofollow" />
|
|
80
|
+
|
|
81
|
+
// No archive/cache
|
|
82
|
+
<SEOMetaTags robots="index, follow, noarchive" />
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Localized Meta Tags
|
|
86
|
+
|
|
87
|
+
Use with i18n:
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
const title = {
|
|
91
|
+
en: 'About Us | My Company',
|
|
92
|
+
fr: 'À propos | Mon Entreprise',
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const description = {
|
|
96
|
+
en: 'Learn about our team',
|
|
97
|
+
fr: 'Découvrez notre équipe',
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
<SEOMetaTags
|
|
101
|
+
title={getLocalizedString(title, locale)}
|
|
102
|
+
description={getLocalizedString(description, locale)}
|
|
103
|
+
/>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Next.js Metadata API
|
|
107
|
+
|
|
108
|
+
The framework is compatible with Next.js Metadata:
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
// app/about/page.tsx
|
|
112
|
+
import type { Metadata } from 'next';
|
|
113
|
+
|
|
114
|
+
export const metadata: Metadata = {
|
|
115
|
+
title: 'About Us | My Company',
|
|
116
|
+
description: 'Learn about our team',
|
|
117
|
+
};
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Use whichever approach fits your project. SEOMetaTags provides more dynamic control; Next.js Metadata is static and simpler.
|
|
121
|
+
|
|
122
|
+
## See Also
|
|
123
|
+
|
|
124
|
+
- [Open Graph](./open-graph.md)
|
|
125
|
+
- [Canonical URLs](./canonical-urls.md)
|
|
126
|
+
- [SEOMetaTags Component](../../components/SEOMetaTags.md)
|