routerino 2.4.0 → 2.5.1-rc1

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Routerino
2
2
 
3
- > A lightweight, SEO-optimized React router for modern websites and applications
3
+ > A lightweight, SEO-optimized React router & SSG for modern websites and applications
4
4
 
5
5
  For teams who want SPA simplicity with search-friendly static HTML, Open Graph previews, and **no framework lock-in.**
6
6
 
@@ -129,7 +129,18 @@ export const routes = [
129
129
  />;
130
130
  ```
131
131
 
132
- Links are just standard HTML anchor tags. No need to use special `<Link>` components—you can use whatever components or design system you like. For example: <a href="/some-page/">a link</a> is perfectly valid. This is very handy for markdown-based content. With standard link support in Routerino, you won't need to [transform your markdown content with custom React components](https://github.com/remarkjs/react-markdown?tab=readme-ov-file#appendix-b-components). Routerino handles same-origin anchor clicks. Cross-origin links and non-HTTP schemes (e.g., mailto:, tel:) are handled by the browser as usual.
132
+ Links are just standard HTML anchor tags. No need to use special `<Link>` components—you can use whatever components or design system you like. For example: <a href="/some-page/">a link</a> is perfectly valid. This is very handy for markdown-based content. With standard link support in Routerino, you won't need to [transform your markdown content with custom React components](https://github.com/remarkjs/react-markdown?tab=readme-ov-file#appendix-b-components).
133
+
134
+ Routerino handles same-origin anchor clicks via SPA navigation. The browser handles the rest natively, including:
135
+
136
+ - **Cross-origin links** (different domain)
137
+ - **Non-HTTP schemes** (mailto:, tel:, javascript:, etc.)
138
+ - **Modified clicks** (Ctrl/Cmd+click, Shift+click, Alt+click, right-click)
139
+ - **`target="_blank"`** links
140
+ - **`download`** attribute links
141
+ - **`rel="external"`** links
142
+ - **File extension links** — PDFs, ZIPs, images, fonts, videos, JSON, XML, and 50+ other file types are recognized automatically
143
+ - **Custom patterns** — use the [`ignorePatterns`](#ignorepatterns-string) prop for additional exclusions (e.g., `/api/`, `/legacy/`)
133
144
 
134
145
  ### Programmatic Navigation
135
146
 
@@ -224,6 +235,7 @@ All of these are optional, so it's easy to get started with nothing but a bare-b
224
235
  | [imageUrl](#imageurl-string) | string | Default image URL for sharing | `null` |
225
236
  | [touchIconUrl](#touchiconurl-string) | string | Image URL for PWA homescreen icon | `null` |
226
237
  | [debug](#debug-boolean) | boolean | Enable debug mode | `false` |
238
+ | [ignorePatterns](#ignorepatterns-string) | string[] | URL patterns to skip SPA routing | `[]` |
227
239
 
228
240
  ##### `title`: string;
229
241
 
@@ -300,7 +312,9 @@ Default: `false`
300
312
 
301
313
  ##### `baseUrl`: string;
302
314
 
303
- The base URL to use for canonical tags and og:url meta tags. If not provided, uses `window.location.origin`. This is useful when you want to specify the production URL regardless of the current environment.
315
+ The base URL to use for canonical tags and og:url meta tags. If not provided, uses `window.location.origin`.
316
+
317
+ This is useful when your site is accessible from multiple domains (for example, both example.com and example.net point to the same app). Set it to the preferred domain and all canonical and og:url tags will consistently point there. Also helpful for pinning to the production URL in development or staging environments.
304
318
 
305
319
  **Important:** The baseUrl must NOT end with a trailing slash (`/`). Correct example: `"https://example.com"`
306
320
 
@@ -338,6 +352,21 @@ Example debug output:
338
352
 
339
353
  Default: `false`
340
354
 
355
+ ##### `ignorePatterns`: string[];
356
+
357
+ An array of regex pattern strings to match against link hrefs. Any same-origin link matching one of these patterns will **not** be intercepted by the SPA router — the browser will handle the navigation natively instead.
358
+
359
+ Patterns are tested case-insensitively against the full resolved href (including origin).
360
+
361
+ ```jsx
362
+ // Skip API endpoints and a legacy section
363
+ <Routerino routes={routes} ignorePatterns={["/api/", "/admin/legacy/"]} />
364
+ ```
365
+
366
+ Routerino also has a built-in list of file extensions that are automatically skipped: `.pdf`, `.zip`, `.docx`, `.png`, `.jpg`, `.svg`, `.mp4`, `.json`, `.xml`, `.csv`, `.txt`, `.ico`, `.woff2`, `.woff`, `.ttf`, `.mp3`, `.wav`, `.epub`, `.map`, `.css`, `.js`, `.wasm`, and many more. The `ignorePatterns` prop is for additional custom patterns beyond these defaults.
367
+
368
+ Default: `[]`
369
+
341
370
  #### RouteConfig props
342
371
 
343
372
  There is a default RouteConfig that will be loaded if you don't specify any routes. The default route is a basic template that can confirm your app is working and routing is good to go.
@@ -402,6 +431,31 @@ An array of HeadTag objects that can be added to the route to manage meta tags,
402
431
 
403
432
  - `target` (string): The "target" attribute of the tag. Defines where to open the linked resource.
404
433
 
434
+ - `innerHTML` (string): Inner HTML content for tags that require a closing tag, such as `<script>` and `<style>`. When provided, the tag is rendered as `<tag attrs>innerHTML</tag>` instead of a self-closing element. This enables structured data (JSON-LD), inline CSS, and other tag-body content.
435
+
436
+ ##### Structured Data Example
437
+
438
+ ```jsx
439
+ {
440
+ path: "/about/",
441
+ element: <AboutPage />,
442
+ tags: [{
443
+ tag: "script",
444
+ type: "application/ld+json",
445
+ innerHTML: JSON.stringify({
446
+ "@context": "https://schema.org",
447
+ "@type": "BreadcrumbList",
448
+ itemListElement: [
449
+ { "@type": "ListItem", "position": 1, "name": "Home", "item": "https://example.com/" },
450
+ { "@type": "ListItem", "position": 2, "name": "About", "item": "https://example.com/about/" },
451
+ ],
452
+ }),
453
+ }],
454
+ }
455
+ ```
456
+
457
+ This works both at runtime (via `updateHeadTag`) and during static site generation (via the forge plugin).
458
+
405
459
  ### Using the `useRouterino` Hook
406
460
 
407
461
  The `useRouterino` hook provides access to router state from any child component. This is the primary way to access route information and update head tags dynamically.
@@ -471,18 +525,21 @@ import { Image } from "routerino/image";
471
525
 
472
526
  ### Image Props
473
527
 
474
- | Prop | Type | Required | Description |
475
- | --------------- | --------------------------- | -------- | ---------------------------------------------------------- |
476
- | `src` | string | ✅ | Image source URL |
477
- | `alt` | string | ✅ | Alt text for accessibility |
478
- | `priority` | boolean | ❌ | Override lazy loading for hero/LCP images |
479
- | `widths` | number[] | ❌ | Custom responsive widths (default: [480, 800, 1200, 1920]) |
480
- | `sizes` | string | ❌ | Responsive sizes attribute (has smart default) |
481
- | `className` | string | ❌ | CSS classes (Tailwind/DaisyUI ready) |
482
- | `style` | object | ❌ | Inline styles |
483
- | `loading` | "lazy" \| "eager" | ❌ | Loading behavior (auto-set based on priority) |
484
- | `decoding` | "sync" \| "async" \| "auto" | ❌ | Decode timing (default: "async") |
485
- | `fetchpriority` | "high" \| "low" \| "auto" | ❌ | Fetch priority (auto-set based on priority) |
528
+ | Prop | Type | Required | Description |
529
+ | --------------- | --------------------------- | -------- | ---------------------------------------------------------------- |
530
+ | `src` | string | ✅ | Image source URL (supports jpg, png, webp, avif, gif, bmp, tiff) |
531
+ | `alt` | string | ✅ | Alt text for accessibility |
532
+ | `priority` | boolean | ❌ | Override lazy loading for hero/LCP images |
533
+ | `widths` | number[] | ❌ | Custom responsive widths (default: [480, 800, 1200, 1920]) |
534
+ | `sizes` | string | ❌ | Responsive sizes attribute (has smart default) |
535
+ | `className` | string | ❌ | CSS classes (Tailwind/DaisyUI ready) |
536
+ | `style` | object | ❌ | Inline styles |
537
+ | `width` | number | ❌ | Explicit width attribute (CLS prevention) |
538
+ | `height` | number | ❌ | Explicit height attribute (CLS prevention) |
539
+ | `loading` | "lazy" \| "eager" | ❌ | Loading behavior (auto-set based on priority) |
540
+ | `decoding` | "sync" \| "async" \| "auto" | ❌ | Decode timing (default: "async") |
541
+ | `fetchpriority` | "high" \| "low" \| "auto" | ❌ | Fetch priority (auto-set based on priority) |
542
+ | `ref` | React.Ref | ❌ | Forwarded to the underlying `<img>` element |
486
543
 
487
544
  ### Image Usage Examples
488
545
 
@@ -717,6 +774,8 @@ With Prerender (SPA):
717
774
 
718
775
  You can override the default with `useTrailingSlash={false}` if you prefer URLs without trailing slashes. Either way, Routerino ensures search engines see consistent, canonical URLs.
719
776
 
777
+ **Multi-domain deployments**: If your site is served from multiple domains, set `baseUrl` to the preferred domain to keep all canonical and og:url tags pointing to one place. For example, `<Routerino baseUrl="https://example.com" routes={routes} />` ensures search engines see one canonical domain even when the same page is reachable at example.net.
778
+
720
779
  ### Sitemap Generation
721
780
 
722
781
  - Automate the creation of `sitemap.xml` and `robots.txt` during your build process with Routerino Forge.
@@ -808,14 +867,14 @@ This creates an engaging Twitter preview with a large image, title, and descript
808
867
  ### Additional SEO Considerations
809
868
 
810
869
  - Use semantic HTML elements in your components for better content structure.
811
- - Implement structured data (JSON-LD) where applicable to enhance rich snippets in search results.
870
+ - Implement structured data (JSON-LD) where applicable to enhance rich snippets in search results. Use the `innerHTML` property on a `<script type="application/ld+json">` head tag (see the [Structured Data Example](#structured-data-example) above).
812
871
  - Ensure your site is mobile-friendly and loads quickly for better search engine rankings.
813
872
 
814
873
  By following these practices, you'll improve your site's SEO performance and social media presence when using Routerino.
815
874
 
816
875
  ### Hash Links
817
876
 
818
- Routerino supports standard `<a href="/page#section">` links for SPA navigation after React renders the new page, it finds the element with the matching `id` and scrolls it into view.
877
+ Routerino supports standard `<a href="/page#section">` links for SPA navigation. After React renders the new page, it finds the element with the matching `id` and scrolls it into view.
819
878
 
820
879
  **Sticky headers**: If your site has a fixed header, use the CSS [`scroll-margin-top`](https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-margin-top) property to offset the scroll target so content isn't hidden behind the header:
821
880
 
@@ -870,7 +929,7 @@ export default defineConfig({
870
929
  // useTrailingSlash: true, // Set to false for /about instead of /about/
871
930
  // verbose: false,
872
931
  // ssgCacheDir: "node_modules/.cache/routerino-forge", // SSG cache directory
873
- // optimizeImages: true, // Enable image optimization (see below)
932
+ // imageOptions: {}, // Customize image optimization (see Image Optimization below)
874
933
  }),
875
934
  ],
876
935
  });
@@ -899,38 +958,42 @@ export default defineConfig({
899
958
  - Creates a 404.html page
900
959
  - Skips dynamic routes (with `:param` syntax)
901
960
  - SEO optimized: Complete HTML with meta tags
902
- - Image optimization: Automatic blur placeholders (LQIP)
961
+ - Image optimization: Automatic responsive variants + blur placeholders (LQIP)
903
962
  - Easy configuration: Works out of the box with Vite and minimal setup
904
963
 
905
964
  #### Image Optimization
906
965
 
907
- Routerino Forge can automatically optimize images in your static builds for faster loading:
966
+ Routerino Forge automatically processes `<Image>` components during the build to generate responsive image variants and LQIP (Low Quality Image Placeholder) blur-up effects. Image optimization is always enabled when ffmpeg is available — no flag needed to turn it on. Use `imageOptions` to customize:
908
967
 
909
968
  ```js
910
969
  routerinoForge({
911
- optimizeImages: true, // Enable with defaults
912
- // Or configure in detail:
913
- optimizeImages: {
914
- enabled: true,
915
- placeholderSize: 20, // Size of blur placeholder (20x20 pixels)
916
- blur: 4, // Blur radius for placeholder
917
- maxSize: 10485760, // Maximum image size to process (10MB)
918
- minSize: 1024, // Minimum image size to process (1KB)
919
- cacheDir: "node_modules/.cache/routerino-forge", // Cache directory
970
+ baseUrl: "https://example.com",
971
+ imageOptions: {
972
+ widths: [480, 800, 1200, 1920], // Responsive widths to generate
973
+ formats: ["webp"], // Extra formats (webp is always generated)
974
+ placeholderSize: 20, // Height of LQIP placeholder in px
975
+ blur: 4, // Blur radius for LQIP placeholder
976
+ maxSize: 10485760, // Max source image size to process (10MB)
977
+ minSize: 1024, // Min source image size to process (1KB)
978
+ cacheDir: "node_modules/.cache/routerino-forge",
920
979
  },
921
980
  });
922
981
  ```
923
982
 
983
+ All keys in `imageOptions` are optional — omit any to keep the default.
984
+
924
985
  **What it does:**
925
986
 
926
- - Generates tiny blur placeholders for images (base64 encoded)
927
- - Caches processed images to speed up subsequent builds
928
- - Preserves original images while enhancing loading performance
929
- - Skips external images (http/https), data URIs, and SVGs
930
- - Smart sizing: Uses aspect-ratio only to prevent layout shift without forcing dimensions
931
- - Hides images initially with `opacity: 0` to prevent broken image icons during load
987
+ - Generates responsive image variants at each configured width (WebP + original format)
988
+ - Generates LQIP blur placeholders (tiny base64 PNG shown while image loads)
989
+ - Anti-upscaling: never generates variants wider than the source image
990
+ - Caches generated variants to speed up subsequent builds
991
+ - Skips external URLs (http/https), data URIs, and SVGs
992
+ - Skips images below `minSize` or above `maxSize`
993
+ - Adds `width`/`height` attributes to `<img>` tags for CLS prevention
994
+ - Stale cache entries are automatically cleaned up (50 most recent kept)
932
995
 
933
- **Note:** Image optimization requires `ffmpeg` to be installed on your system. Install with `brew install ffmpeg` (Mac), `apt install ffmpeg` (Debian/Ubuntu), or `choco install ffmpeg` (Windows). Without ffmpeg, the Image component still works but falls back to the original image without optimization. A warning is shown during build if ffmpeg is not found but Image components are used.
996
+ **Note:** Image optimization requires `ffmpeg` to be installed on your system. Install with `brew install ffmpeg` (Mac), `apt install ffmpeg` (Debian/Ubuntu), or `choco install ffmpeg` (Windows). Without ffmpeg, the Image component still works but falls back to the original image without responsive variants or LQIP. A warning is shown during build if ffmpeg is not found but Image components are used.
934
997
 
935
998
  ##### CI/CD Setup for Image Optimization
936
999