leptos_next_metadata/
lib.rs

1//! # leptos-next-metadata
2//!
3//! Next.js-style metadata management for Leptos applications with type-safe APIs,
4//! blazing-fast OG image generation, and comprehensive SEO optimization.
5//!
6//! ## Quick Example
7//!
8//! ```rust
9//! use leptos_next_metadata::prelude::*;
10//!
11//! // Create metadata for a page
12//! let metadata = Metadata {
13//!     title: Some(Title::Static("My Page".into())),
14//!     description: Some("Page description".into()),
15//!     ..Default::default()
16//! };
17//!
18//! // Use in your Leptos component
19//! ```
20//!
21//! ## Features
22//!
23//! - 🚀 **2-7x faster** OG image generation than browser-based solutions
24//! - 🦀 **Type-safe** metadata with compile-time validation
25//! - 🎯 **Next.js compatible** API for easy migration
26//! - 🖼️ **Dynamic OG images** with SVG templates and custom fonts
27//! - 📊 **JSON-LD support** with Schema.org types
28//! - 🔍 **SEO validation** with best practices enforcement
29//! - ⚡ **SSR/CSR/Islands** - works with all Leptos rendering modes
30//! - 📁 **File conventions** - automatic favicon, robots.txt, sitemap detection
31//! - 🎨 **Template system** - Liquid templates for OG images
32//! - 💾 **Smart caching** - multi-level caching for optimal performance
33//!
34//! ## Feature Flags
35//!
36//! - `ssr` - Server-side rendering support (default)
37//! - `csr` - Client-side rendering support
38//! - `hydrate` - Hydration support
39//! - `og-images` - Open Graph image generation (default)
40//! - `file-conventions` - File-based metadata conventions (default)
41//! - `json-ld` - JSON-LD structured data support
42//! - `caching` - Advanced caching with LRU and TTL
43//! - `http` - HTTP client for external metadata fetching
44//! - `debug` - Debug logging and validation
45//!
46//! ## Modules
47//!
48//! - [`metadata`] - Core metadata types and traits
49//! - [`og_image`] - Open Graph image generation
50//! - [`json_ld`] - JSON-LD structured data
51//! - [`conventions`] - File convention scanning
52//! - [`macros`] - Procedural macros for metadata
53//! - [`utils`] - Utility functions and helpers
54
55pub mod body;
56pub mod competitive_analysis;
57pub mod enhanced_title;
58pub mod hashed_stylesheet;
59pub mod html;
60pub mod json_ld;
61pub mod macros;
62pub mod meta_tags;
63pub mod metadata;
64
65// Server-only modules (exclude from WASM)
66#[cfg(not(target_arch = "wasm32"))]
67pub mod og_image;
68
69#[cfg(not(target_arch = "wasm32"))]
70pub mod conventions;
71
72#[cfg(all(not(target_arch = "wasm32"), feature = "api-contracts"))]
73pub mod api;
74
75// WASM-specific modules
76#[cfg(target_arch = "wasm32")]
77pub mod wasm;
78
79pub mod analytics;
80pub mod canvas_types;
81pub mod error;
82pub mod themes;
83pub mod utils;
84
85/// Re-exports for common use cases
86pub mod prelude {
87    pub use crate::metadata::{
88        AlternateLink, Article, Authors, CanonicalUrl, ColorScheme, Description, FormatDetection,
89        Keywords, Metadata, OpenGraph, Profile, ReferrerPolicy, Robots, ThemeColor, Title, Twitter,
90        TwitterCard, Viewport,
91    };
92
93    #[cfg(not(target_arch = "wasm32"))]
94    pub use crate::conventions::{ConventionScanner, FileConventions};
95    #[cfg(feature = "json-ld")]
96    pub use crate::json_ld::{JsonLd, SchemaOrg};
97    #[cfg(not(target_arch = "wasm32"))]
98    pub use crate::og_image::{GeneratedOgImage, OgImageGenerator, OgImageParams};
99
100    // Advanced canvas types (available for both WASM and native for testing)
101    pub use crate::canvas_types::{
102        CanvasOgParams, GradientType, ImageLayer, LogoPosition, OgImageLayer, OgImageTemplate,
103        ShapeLayer, ShapeType, TextAlign, TextGradient, TextLayer, TextOutline, TextShadow,
104    };
105
106    // Theme system types
107    pub use crate::themes::{
108        BorderEffects, BorderStyle, ColorPalette, ContentAlignment, FontWeights, GradientConfig,
109        Layout, LogoPosition as ThemeLogoPosition, PatternConfig, PatternType, QuickThemes,
110        TextAlignment, TextEffects, Theme, ThemeBuilder, ThemeCategory, ThemeHelpers, ThemeManager,
111        ThemeMetadata, VisualEffects,
112    };
113
114    #[cfg(feature = "macros")]
115    pub use crate::macros::{generate_metadata, metadata};
116
117    // WASM-specific re-exports
118    #[cfg(target_arch = "wasm32")]
119    pub use crate::wasm::browser_api::BrowserApi;
120    #[cfg(target_arch = "wasm32")]
121    pub use crate::wasm::canvas_og::{
122        CanvasOgGenerator, CanvasOgParams, CanvasOgResult, CanvasOgUtils, GradientType, ImageLayer,
123        LogoPosition, OgImageLayer, OgImageTemplate, ShapeLayer, ShapeType, TextAlign,
124        TextGradient, TextLayer, TextOutline, TextShadow,
125    };
126    #[cfg(target_arch = "wasm32")]
127    pub use crate::wasm::context::{StorageBackend, WasmContext};
128    #[cfg(target_arch = "wasm32")]
129    pub use crate::wasm::error_handler::{
130        QueueStatus, WasmErrorContext, WasmErrorHandler, WasmErrorReporter, WasmErrorUtils,
131    };
132    #[cfg(target_arch = "wasm32")]
133    pub use crate::wasm::feature_detection::FeatureDetection;
134    #[cfg(target_arch = "wasm32")]
135    pub use crate::wasm::performance::{
136        BrowserPerformanceInfo, BundleOptimizer, BundleRecommendations, BundleSavings,
137        MemoryOptimization, MemoryPressure, OptimizationStatus, PerformanceMonitor,
138        PerformanceSummary, PerformanceTip, RuntimeOptimizer, WasmProfiler,
139    };
140    #[cfg(target_arch = "wasm32")]
141    pub use crate::wasm::security::{
142        ComplianceStatus, CspConfig, SecureDefaults, SecurityAudit, SecurityCategory,
143        SecurityConfig, SecurityIssue, SecuritySeverity, SecurityUtils, SecurityValidator,
144        ValidationConfig, ValidationIssue, ValidationResult, ValidationSeverity,
145    };
146    #[cfg(target_arch = "wasm32")]
147    pub use crate::wasm::storage::{MetadataStorage, StorageFactory};
148    #[cfg(target_arch = "wasm32")]
149    pub use crate::wasm::worker_manager::{WasmWorkerManager, WorkerResult, WorkerTask};
150    #[cfg(target_arch = "wasm32")]
151    pub use crate::wasm::{WasmCapabilities, WasmMetadataContext, WasmStorage};
152
153    pub use crate::body::Body;
154    pub use crate::enhanced_title::EnhancedTitle;
155    pub use crate::hashed_stylesheet::HashedStylesheet;
156    pub use crate::html::Html;
157    pub use crate::meta_tags::MetaTags;
158    pub use crate::metadata::context::{
159        provide_metadata_context, MetadataContext, MetadataProvider,
160    };
161
162    // Competitive analysis
163    pub use crate::competitive_analysis::{
164        BenchmarkReport, BenchmarkScenario, Capability, ClientValue, CompetitiveAnalysisService,
165        CompetitiveBenchmark, Competitor, CompetitorCategory, DemoCreator, ImplementationType,
166        PerformanceMetrics,
167    };
168
169    // Error handling
170    pub use crate::error::{
171        ErrorContext, ErrorContextBuilder, ErrorHandler, ErrorKind, ErrorReportingConfig,
172        ErrorSeverity, ErrorStats, ErrorUtils, MetadataError, MetadataResult,
173    };
174}
175
176pub use body::Body;
177#[cfg(not(target_arch = "wasm32"))]
178pub use conventions::{ConventionScanner, FileConventions};
179pub use enhanced_title::EnhancedTitle;
180pub use hashed_stylesheet::HashedStylesheet;
181pub use html::Html;
182#[cfg(feature = "json-ld")]
183pub use json_ld::{
184    Answer, Article, BlogPosting, BreadcrumbList, FAQPage, JsonLd, ListItem, Organization, Person,
185    Product, Question, SchemaOrg, WebPage,
186};
187pub use meta_tags::MetaTags;
188/// Re-export commonly used types
189pub use metadata::{
190    Authors, CanonicalUrl, ColorScheme, Description, FormatDetection, Keywords, Metadata,
191    OpenGraph, ReferrerPolicy, Robots, ThemeColor, Title, Twitter, TwitterCard, Viewport,
192};
193#[cfg(not(target_arch = "wasm32"))]
194pub use og_image::{GeneratedOgImage, OgImageGenerator, OgImageParams};
195
196#[cfg(feature = "macros")]
197pub use macros::*;
198
199/// Result type for metadata operations
200pub type Result<T> = std::result::Result<T, Error>;
201
202/// Error type for metadata operations
203#[derive(Debug, thiserror::Error)]
204pub enum Error {
205    #[error("Metadata context not provided")]
206    ContextNotProvided,
207
208    #[error("Invalid metadata: {0}")]
209    InvalidMetadata(String),
210
211    #[error("Template error: {0}")]
212    TemplateError(String),
213
214    #[error("Image generation error: {0}")]
215    ImageError(String),
216
217    #[error("Performance limit exceeded: {0}")]
218    PerformanceLimitExceeded(String),
219
220    #[error("IO error: {0}")]
221    IoError(#[from] std::io::Error),
222
223    #[error("Serialization error: {0}")]
224    SerializationError(String),
225
226    #[error("URL error: {0}")]
227    UrlError(#[from] url::ParseError),
228
229    #[error("Configuration error: {0}")]
230    ConfigError(String),
231
232    #[error("Cache error: {0}")]
233    CacheError(String),
234
235    #[error("Validation error: {0}")]
236    ValidationError(String),
237}
238
239/// Configuration for the metadata system
240#[derive(Debug, Clone, Default)]
241pub struct MetadataConfig {
242    /// Cache configuration
243    pub cache: CacheConfig,
244
245    /// OG image generation configuration
246    pub og_image: OgImageConfig,
247
248    /// File conventions configuration
249    pub conventions: ConventionConfig,
250
251    /// Debug configuration
252    pub debug: DebugConfig,
253
254    /// Resource limits
255    pub limits: LimitConfig,
256}
257
258/// Cache configuration
259#[derive(Debug, Clone)]
260pub struct CacheConfig {
261    /// Enable memory caching
262    pub memory_cache_enabled: bool,
263
264    /// Memory cache size (number of items)
265    pub memory_cache_size: usize,
266
267    /// Memory cache TTL in seconds
268    pub memory_cache_ttl: u64,
269
270    /// Enable disk caching
271    pub disk_cache_enabled: bool,
272
273    /// Disk cache path
274    pub disk_cache_path: String,
275
276    /// OG image cache size in MB
277    pub og_image_cache_size: usize,
278}
279
280/// OG image configuration
281#[derive(Debug, Clone)]
282pub struct OgImageConfig {
283    /// Default image dimensions
284    pub default_size: (u32, u32),
285
286    /// Font configuration
287    pub fonts: Vec<FontConfig>,
288
289    /// Template directory
290    pub template_dir: String,
291
292    /// Output format
293    pub format: ImageFormat,
294
295    /// Quality (for JPEG)
296    pub quality: u8,
297}
298
299/// Font configuration
300#[derive(Debug, Clone)]
301pub struct FontConfig {
302    /// Font family name
303    pub family: String,
304
305    /// Font weight
306    pub weight: FontWeight,
307
308    /// Font data
309    pub data: Vec<u8>,
310}
311
312/// Font weight enumeration
313#[derive(Debug, Clone, Copy, PartialEq, Eq)]
314pub enum FontWeight {
315    Thin = 100,
316    ExtraLight = 200,
317    Light = 300,
318    Regular = 400,
319    Medium = 500,
320    SemiBold = 600,
321    Bold = 700,
322    ExtraBold = 800,
323    Black = 900,
324}
325
326/// Image format enumeration
327#[derive(Debug, Clone, Copy, PartialEq, Eq)]
328pub enum ImageFormat {
329    PNG,
330    JPEG,
331    WebP,
332}
333
334/// Convention configuration
335#[derive(Debug, Clone)]
336pub struct ConventionConfig {
337    /// Root directory for file conventions
338    pub root_dir: String,
339
340    /// Enable automatic detection
341    pub auto_detect: bool,
342
343    /// Custom convention patterns
344    pub patterns: Vec<String>,
345}
346
347/// Debug configuration
348#[derive(Debug, Clone, Default)]
349pub struct DebugConfig {
350    /// Log metadata resolution
351    pub log_metadata_resolution: bool,
352
353    /// Log cache hits/misses
354    pub log_cache_hits: bool,
355
356    /// Log generation time
357    pub log_generation_time: bool,
358
359    /// Validate output
360    pub validate_output: bool,
361}
362
363/// Resource limits configuration
364#[derive(Debug, Clone)]
365pub struct LimitConfig {
366    /// Maximum OG image size in bytes
367    pub max_og_image_size: usize,
368
369    /// Maximum template size in bytes
370    pub max_template_size: usize,
371
372    /// Maximum cache memory in bytes
373    pub max_cache_memory: usize,
374
375    /// Maximum generation time in milliseconds
376    pub max_generation_time: u64,
377}
378
379impl Default for CacheConfig {
380    fn default() -> Self {
381        Self {
382            memory_cache_enabled: true,
383            memory_cache_size: 1000,
384            memory_cache_ttl: 3600,
385            disk_cache_enabled: false,
386            disk_cache_path: "./cache".to_string(),
387            og_image_cache_size: 100,
388        }
389    }
390}
391
392impl Default for OgImageConfig {
393    fn default() -> Self {
394        Self {
395            default_size: (1200, 630),
396            fonts: Vec::new(),
397            template_dir: "./templates".to_string(),
398            format: ImageFormat::PNG,
399            quality: 90,
400        }
401    }
402}
403
404impl Default for ConventionConfig {
405    fn default() -> Self {
406        Self {
407            root_dir: "./app".to_string(),
408            auto_detect: true,
409            patterns: Vec::new(),
410        }
411    }
412}
413
414impl Default for LimitConfig {
415    fn default() -> Self {
416        Self {
417            max_og_image_size: 10_000_000, // 10MB
418            max_template_size: 1_000_000,  // 1MB
419            max_cache_memory: 100_000_000, // 100MB
420            max_generation_time: 5000,     // 5s
421        }
422    }
423}