reroute-js 0.11.5 → 0.12.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.
Files changed (155) hide show
  1. package/README.md +237 -5
  2. package/_/basic/package.json +7 -6
  3. package/_/basic/reroute.config.ts +0 -5
  4. package/_/basic/src/index.ts +5 -2
  5. package/_/blog/package.json +7 -6
  6. package/_/blog/src/index.ts +2 -2
  7. package/_/redirects/package.json +7 -6
  8. package/_/rss/package.json +28 -0
  9. package/_/rss/reroute.config.ts +23 -0
  10. package/_/rss/tsconfig.json +25 -0
  11. package/_/sitemap/package.json +28 -0
  12. package/_/sitemap/reroute.config.ts +23 -0
  13. package/_/sitemap/tsconfig.json +25 -0
  14. package/_/store/package.json +7 -6
  15. package/_/store/src/index.ts +3 -6
  16. package/_/streaming/package.json +7 -6
  17. package/cli/bin.d.ts +1 -1
  18. package/cli/bin.js +894 -53
  19. package/cli/bin.js.map +17 -11
  20. package/cli/index.d.ts +1 -1
  21. package/cli/index.js +4 -4
  22. package/cli/index.js.map +1 -1
  23. package/cli/src/cli.d.ts +1 -1
  24. package/cli/src/commands/analyze.d.ts +1 -1
  25. package/cli/src/commands/build.d.ts +1 -1
  26. package/cli/src/commands/dev.d.ts +1 -1
  27. package/cli/src/commands/gen.d.ts +1 -1
  28. package/cli/src/commands/index.d.ts +1 -1
  29. package/cli/src/commands/init.d.ts +1 -1
  30. package/cli/src/commands/lib/command.d.ts +1 -1
  31. package/cli/src/commands/lib/env.d.ts +1 -1
  32. package/cli/src/commands/lib/index.d.ts +1 -1
  33. package/cli/src/commands/lib/log.d.ts +1 -1
  34. package/cli/src/commands/lib/markdown/availability.d.ts +1 -1
  35. package/cli/src/commands/lib/markdown/index.d.ts +1 -1
  36. package/cli/src/commands/lib/markdown/processor.d.ts +1 -1
  37. package/cli/src/commands/lib/production.d.ts +1 -1
  38. package/cli/src/commands/lib/server.d.ts +1 -1
  39. package/cli/src/commands/lib/streaming/analyzer.d.ts +1 -1
  40. package/cli/src/commands/lib/streaming/suspense.d.ts +1 -1
  41. package/cli/src/commands/lib/tailwind.d.ts +1 -1
  42. package/cli/src/commands/lib/version.d.ts +1 -1
  43. package/cli/src/commands/start.d.ts +1 -1
  44. package/cli/src/index.d.ts +1 -1
  45. package/core/index.d.ts +1 -1
  46. package/core/index.js +903 -67
  47. package/core/index.js.map +16 -11
  48. package/core/src/bundler/hash.d.ts +1 -1
  49. package/core/src/bundler/index.d.ts +1 -1
  50. package/core/src/config.d.ts +86 -2
  51. package/core/src/config.d.ts.map +1 -1
  52. package/core/src/content/discovery.d.ts +1 -1
  53. package/core/src/content/index.d.ts +1 -1
  54. package/core/src/content/metadata.d.ts +1 -1
  55. package/core/src/index.d.ts +3 -1
  56. package/core/src/index.d.ts.map +1 -1
  57. package/core/src/rss/discovery.d.ts +43 -0
  58. package/core/src/rss/discovery.d.ts.map +1 -0
  59. package/core/src/rss/generator.d.ts +29 -0
  60. package/core/src/rss/generator.d.ts.map +1 -0
  61. package/core/src/rss/index.d.ts +12 -0
  62. package/core/src/rss/index.d.ts.map +1 -0
  63. package/core/src/sitemap/discovery.d.ts +51 -0
  64. package/core/src/sitemap/discovery.d.ts.map +1 -0
  65. package/core/src/sitemap/generator.d.ts +42 -0
  66. package/core/src/sitemap/generator.d.ts.map +1 -0
  67. package/core/src/sitemap/index.d.ts +12 -0
  68. package/core/src/sitemap/index.d.ts.map +1 -0
  69. package/core/src/ssr/index.d.ts +1 -1
  70. package/core/src/ssr/lib/cache.d.ts +3 -2
  71. package/core/src/ssr/lib/cache.d.ts.map +1 -1
  72. package/core/src/ssr/lib/collections.d.ts +1 -1
  73. package/core/src/ssr/lib/compression.d.ts +1 -1
  74. package/core/src/ssr/lib/compute.d.ts +4 -1
  75. package/core/src/ssr/lib/compute.d.ts.map +1 -1
  76. package/core/src/ssr/lib/data.d.ts +1 -1
  77. package/core/src/ssr/lib/data.d.ts.map +1 -1
  78. package/core/src/ssr/lib/html.d.ts +1 -1
  79. package/core/src/ssr/lib/index.d.ts +1 -1
  80. package/core/src/ssr/lib/metadata.d.ts +1 -1
  81. package/core/src/ssr/lib/mime.d.ts +1 -1
  82. package/core/src/ssr/lib/modules.d.ts +1 -1
  83. package/core/src/ssr/lib/path.d.ts +1 -1
  84. package/core/src/ssr/lib/preload.d.ts +1 -1
  85. package/core/src/ssr/lib/scripts.d.ts +5 -1
  86. package/core/src/ssr/lib/scripts.d.ts.map +1 -1
  87. package/core/src/ssr/lib/seed.d.ts +1 -1
  88. package/core/src/ssr/lib/styles.d.ts +1 -1
  89. package/core/src/ssr/lib/template.d.ts +1 -1
  90. package/core/src/ssr/lib/types.d.ts +1 -1
  91. package/core/src/ssr/render.d.ts +1 -1
  92. package/core/src/ssr/render.d.ts.map +1 -1
  93. package/core/src/ssr/stream.d.ts +1 -1
  94. package/core/src/ssr/stream.d.ts.map +1 -1
  95. package/elysia/index.d.ts +1 -1
  96. package/elysia/index.js +1266 -59
  97. package/elysia/index.js.map +20 -12
  98. package/elysia/src/index.d.ts +1 -1
  99. package/elysia/src/libs/cache.d.ts +1 -1
  100. package/elysia/src/libs/http.d.ts +1 -1
  101. package/elysia/src/libs/image.d.ts +1 -1
  102. package/elysia/src/plugin.d.ts +1 -1
  103. package/elysia/src/plugin.d.ts.map +1 -1
  104. package/elysia/src/routes/artifacts.d.ts +1 -1
  105. package/elysia/src/routes/content.d.ts +1 -1
  106. package/elysia/src/routes/image.d.ts +1 -1
  107. package/elysia/src/routes/internal.d.ts +1 -1
  108. package/elysia/src/routes/redirects.d.ts +1 -1
  109. package/elysia/src/routes/rss.d.ts +27 -0
  110. package/elysia/src/routes/rss.d.ts.map +1 -0
  111. package/elysia/src/routes/sitemap.d.ts +27 -0
  112. package/elysia/src/routes/sitemap.d.ts.map +1 -0
  113. package/elysia/src/routes/ssr.d.ts +1 -1
  114. package/elysia/src/routes/static.d.ts +1 -1
  115. package/elysia/src/types.d.ts +6 -1
  116. package/elysia/src/types.d.ts.map +1 -1
  117. package/package.json +1 -1
  118. package/react/index.d.ts +1 -1
  119. package/react/index.js +61 -37
  120. package/react/index.js.map +6 -5
  121. package/react/src/components/ClientOnly.d.ts +1 -1
  122. package/react/src/components/ContentRoute.d.ts +1 -1
  123. package/react/src/components/Image.d.ts +1 -1
  124. package/react/src/components/LazyRoute.d.ts +1 -1
  125. package/react/src/components/Link.d.ts +1 -1
  126. package/react/src/components/Link.d.ts.map +1 -1
  127. package/react/src/components/Markdown.d.ts +1 -1
  128. package/react/src/components/Outlet.d.ts +1 -1
  129. package/react/src/components/index.d.ts +1 -1
  130. package/react/src/hooks/index.d.ts +2 -1
  131. package/react/src/hooks/index.d.ts.map +1 -1
  132. package/react/src/hooks/useContent.d.ts +1 -1
  133. package/react/src/hooks/useData.d.ts +1 -1
  134. package/react/src/hooks/useFeed.d.ts +49 -0
  135. package/react/src/hooks/useFeed.d.ts.map +1 -0
  136. package/react/src/hooks/useLayoutData.d.ts +1 -1
  137. package/react/src/hooks/useNavigate.d.ts +1 -1
  138. package/react/src/hooks/useParams.d.ts +1 -1
  139. package/react/src/hooks/useRouter.d.ts +1 -1
  140. package/react/src/hooks/useSearchParams.d.ts +1 -1
  141. package/react/src/index.d.ts +1 -1
  142. package/react/src/lib/content.d.ts +1 -1
  143. package/react/src/lib/head.d.ts +1 -1
  144. package/react/src/lib/index.d.ts +1 -1
  145. package/react/src/lib/lazy-route.d.ts +1 -1
  146. package/react/src/lib/route-loader.d.ts +1 -1
  147. package/react/src/providers/ContentProvider.d.ts +1 -1
  148. package/react/src/providers/RerouteProvider.d.ts +1 -1
  149. package/react/src/providers/RouterProvider.d.ts +1 -1
  150. package/react/src/providers/RouterProvider.d.ts.map +1 -1
  151. package/react/src/providers/index.d.ts +1 -1
  152. package/react/src/types/any.d.ts +1 -1
  153. package/react/src/types/index.d.ts +1 -1
  154. package/react/src/types/router.d.ts +1 -1
  155. package/_/redirects/README.md +0 -63
package/README.md CHANGED
@@ -45,15 +45,16 @@ Reroute is a dead-simple file-based routing framework for building full-stack Re
45
45
  - `useRouter()` - Access router state and utilities
46
46
  - 📚 **Content Hooks**:
47
47
  - `useContent()` - Load and manage content collections with sorting
48
+ - `useFeed()` - Discover RSS feed URLs for current route
48
49
  - 🧩 **Components**:
49
50
  - `<Link>` - Client-side navigation with automatic prefetching
50
51
  - `<Image>` - Optimized images with automatic format negotiation and lazy loading
51
52
  - `<Outlet>` - Render nested route components
52
53
  - `<ContentRoute>` - Dynamic content rendering with metadata injection
53
54
  - 🎭 **Providers**:
54
- - `<RouterProvider>` - Router context for the app
55
- - `<ContentProvider>` - Content system context
56
- - `<RerouteProvider>` - All-in-one provider wrapper
55
+ - `<RerouteProvider>` - **USE THIS** - All-in-one provider with routing + content + artifacts
56
+ - `<RouterProvider>` - Low-level router only (internal use, prefer RerouteProvider)
57
+ - `<ContentProvider>` - Content system context (internal use)
57
58
  - 🗂️ **SSR Data**:
58
59
  - `useData()` - Read route-level SSR data without loaders
59
60
  - `export const ssr = { data() {} }` - Route data function executed on server
@@ -116,6 +117,23 @@ Reroute is a dead-simple file-based routing framework for building full-stack Re
116
117
  - 🌍 **Language Attribute** - Dynamic `lang` attribute support
117
118
  - 🎯 **SEO Optimization** - Title, description, and custom meta tags
118
119
 
120
+ ### 🗺️ Sitemap Generation
121
+ - 🔍 **Auto-Discovery** - Automatically discovers static routes, content collections, and ssr.data routes
122
+ - 📄 **XML Generation** - Standards-compliant sitemap.xml following Google's specifications
123
+ - 💾 **Smart Caching** - Generated on first request and cached according to maxAge
124
+ - 📊 **Auto-Pagination** - Automatically splits into multiple files for sites with 50k+ URLs
125
+ - 🎨 **Custom Extractors** - Content-agnostic URL and date extraction via configuration
126
+ - 📅 **Metadata Support** - Includes lastmod, changefreq, and priority for each URL
127
+
128
+ ### 📰 RSS Feed Generation
129
+ - 🔍 **Auto-Discovery** - Discovers content collections, route ssr.data, and layout ssr.data
130
+ - 📄 **RSS & Atom Support** - Standards-compliant RSS 2.0 and Atom 1.0 formats
131
+ - 📚 **Per-Collection Feeds** - Each collection gets its own feed (e.g., /blog/feed.xml)
132
+ - 💾 **Smart Caching** - Generated on first request and cached according to maxAge
133
+ - 🎨 **Custom Extractors** - Content-agnostic extraction for title, description, author, pubDate
134
+ - 🔄 **Auto-Sorting** - Items sorted by publication date (newest first)
135
+ - 📏 **Limit Control** - Configurable maximum items per feed (default: 50)
136
+
119
137
  ### 📦 Configuration Options
120
138
  - 🎯 **Custom Assets Directory** - Configure where your client files live
121
139
  - 🔧 **URL Prefix** - Deploy to subdirectories with custom prefixes
@@ -152,10 +170,19 @@ import { useData, useParams } from 'reroute-js/react';
152
170
  import { getProduct } from '../lib/api';
153
171
 
154
172
  export const ssr = {
155
- async data({ params }: { params: { id?: string } }) {
173
+ async data({ params, set }: { params: { id?: string }; set: { status: number } }) {
156
174
  const id = Number.parseInt(params.id || '');
157
- if (!Number.isFinite(id)) return { product: null };
175
+ if (!Number.isFinite(id)) {
176
+ set.status = 404; // Set HTTP status code
177
+ return { product: null };
178
+ }
179
+
158
180
  const product = await getProduct(id);
181
+ if (!product) {
182
+ set.status = 404;
183
+ return { product: null };
184
+ }
185
+
159
186
  return { product };
160
187
  },
161
188
  };
@@ -171,6 +198,7 @@ Notes:
171
198
  - Works with Bun + Elysia, no client loaders needed for initial render
172
199
  - Data is injected as `window.__REROUTE_DATA__` and read during hydration
173
200
  - Use with existing content features (useContent); both can be seeded in the same page
201
+ - **HTTP Status Control:** Use `set.status` to set response status codes (follows Elysia's API). Non-200 responses are not cached
174
202
 
175
203
  ## 🔐 Environment Variables
176
204
 
@@ -391,6 +419,210 @@ export default function MyPage() {
391
419
  - **Optional**: Only bundle dependencies you actually use
392
420
 
393
421
 
422
+ ## 🗺️ Sitemap & RSS Feed Generation
423
+
424
+ Reroute provides automatic sitemap and RSS feed generation with zero configuration required.
425
+
426
+ ### Sitemap Generation
427
+
428
+ Generate standards-compliant XML sitemaps for search engines.
429
+
430
+ #### Quick Start
431
+
432
+ ```typescript
433
+ // reroute.config.ts
434
+ import { defineConfig } from 'reroute-js/core';
435
+
436
+ export default defineConfig({
437
+ sitemap: {
438
+ enabled: true, // opt-in (default: false)
439
+ baseUrl: 'https://your-domain.com',
440
+ },
441
+ });
442
+ ```
443
+
444
+ Your sitemap is now available at `/sitemap.xml`!
445
+
446
+ #### What Gets Included
447
+
448
+ All three sources are automatically discovered:
449
+
450
+ 1. **Static Routes** - Pages in `routes/` folder (e.g., `/`, `/about`, `/contact`)
451
+ 2. **Content Collections** - Items in `routes/[collection]/content/` with metadata
452
+ 3. **Route SSR Data** - Dynamic data from route `ssr.data` exports
453
+
454
+
455
+
456
+ #### Custom Configuration
457
+
458
+ For non-standard data structures:
459
+
460
+ ```typescript
461
+ sitemap: {
462
+ enabled: true,
463
+ baseUrl: 'https://your-domain.com',
464
+
465
+ // Extract URL segment from ssr.data items
466
+ extractUrl: (item, routePattern) => {
467
+ // Products use SKU instead of slug
468
+ if (routePattern === '/products' && item.sku) {
469
+ return item.sku; // /products/laptop-pro-2024
470
+ }
471
+ return null; // fall back to defaults (slug, id, name, key)
472
+ },
473
+
474
+ // Extract lastmod date
475
+ extractLastmod: (item) => item.updatedAt || item.date,
476
+
477
+ // Default settings
478
+ changefreq: 'weekly', // or 'daily', 'monthly', etc.
479
+ priority: 0.5, // 0.0 to 1.0
480
+ }
481
+ ```
482
+
483
+ #### Features
484
+
485
+ - **Runtime generation** - Generated on first request, cached according to `maxAge`
486
+ - **Auto-pagination** - Sites with 50k+ URLs automatically split into multiple files with sitemap index
487
+ - **SEO-friendly** - Includes `<lastmod>`, `<changefreq>`, and `<priority>` tags
488
+ - **Content-agnostic** - Works with any data structure via custom extractors
489
+ - **Smart caching** - Respects your `maxAge` configuration
490
+
491
+ ### RSS Feed Generation
492
+
493
+ Generate RSS 2.0 and Atom 1.0 feeds for content syndication.
494
+
495
+ #### Quick Start
496
+
497
+ ```typescript
498
+ // reroute.config.ts
499
+ import { defineConfig } from 'reroute-js/core';
500
+
501
+ export default defineConfig({
502
+ rss: {
503
+ enabled: true, // opt-in (default: false)
504
+ baseUrl: 'https://your-domain.com',
505
+ title: 'My Blog',
506
+ description: 'Latest posts and updates',
507
+ },
508
+ });
509
+ ```
510
+
511
+ Your feeds are automatically available at:
512
+ - `/feed.xml` - Main feed (combines all sources below)
513
+ - `/blog/feed.xml` - Blog collection (from `routes/blog/content/`)
514
+ - `/changelog/feed.xml` - Changelog route (from route's `ssr.data`)
515
+ - `/announcements/feed.xml` - Announcements (from layout's `ssr.data`)
516
+
517
+ Pattern:
518
+ - `/[collection]/feed.xml` - For any content collection
519
+ - `/[route]/feed.xml` - For any route/layout with `ssr.data`
520
+
521
+ #### What Gets Included
522
+
523
+ All three sources are automatically discovered:
524
+
525
+ 1. **Content Collections** - Items from `routes/[collection]/content/` folders
526
+ - Example: Blog posts with metadata (title, description, date)
527
+
528
+ 2. **Route SSR Data** - Arrays returned by route `ssr.data` functions
529
+ - Example: Changelog versions fetched from API
530
+ - Must export `ssr.data` that returns object containing arrays
531
+
532
+ 3. **Layout SSR Data** - Arrays returned by layout `ssr.data` functions
533
+ - Example: Site-wide announcements fetched in layout
534
+ - Must export `ssr.data` in `[layout].tsx` that returns object containing arrays
535
+
536
+ **Important:** For ssr.data discovery, the data must contain arrays. Nested arrays (e.g., `{ user: { notifications: [...] } }`) are automatically found via recursive discovery.
537
+
538
+ #### Custom Configuration
539
+
540
+ ```typescript
541
+ rss: {
542
+ enabled: true,
543
+ baseUrl: 'https://your-domain.com',
544
+ title: 'My Blog',
545
+ description: 'Latest updates',
546
+ limit: 50, // max items per feed (default: 50)
547
+ format: 'rss', // 'rss' (RSS 2.0) or 'atom' (Atom 1.0)
548
+
549
+ // Extract URL segment from ssr.data items
550
+ extractUrl: (item, routePattern) => {
551
+ // Changelog uses version field
552
+ if (routePattern === '/changelog' && item.version) {
553
+ return item.version; // /changelog/1.2.0
554
+ }
555
+ return null; // fall back to defaults (slug, id, name, key)
556
+ },
557
+
558
+ // Extract publication date
559
+ extractPubDate: (item) => item.publishedAt || item.date || item.createdAt,
560
+
561
+ // Extract author
562
+ extractAuthor: (item) => item.author || item.authorName,
563
+
564
+ // Extract full content (optional, for full-text feeds)
565
+ extractContent: (item) => item.body || item.content,
566
+ }
567
+ ```
568
+
569
+ #### Features
570
+
571
+ - **Multi-source** - Combines content collections, route ssr.data, and layout ssr.data
572
+ - **Per-collection feeds** - Each collection gets `/[collection]/feed.xml`
573
+ - **Per-route feeds** - Routes with ssr.data get `/[route]/feed.xml`
574
+ - **RSS & Atom** - Choose RSS 2.0 or Atom 1.0 format
575
+ - **Auto-sorting** - Items sorted by pubDate (newest first)
576
+ - **Smart caching** - Generated on first request, cached according to `maxAge`
577
+ - **Recursive discovery** - Finds arrays even in nested data (e.g., `user.notifications`)
578
+ - **Content-agnostic** - Works with any data structure via custom extractors
579
+
580
+ #### Discovering Feeds in Your UI
581
+
582
+ Use the `useFeed()` hook to automatically discover and link to RSS feeds:
583
+
584
+ ```tsx
585
+ import { useFeed } from 'reroute-js/react';
586
+
587
+ function Header() {
588
+ const feed = useFeed();
589
+
590
+ return (
591
+ <header>
592
+ {/* Show collection/route-specific feed if available */}
593
+ {feed.hasFeed && (
594
+ <a href={feed.feedUrl!} target="_blank">
595
+ Subscribe to {feed.collection}
596
+ </a>
597
+ )}
598
+
599
+ {/* Main feed always available */}
600
+ <a href={feed.mainFeedUrl}>RSS Feed</a>
601
+ </header>
602
+ );
603
+ }
604
+ ```
605
+
606
+ Returns:
607
+ - `feedUrl` - URL of the specific feed (`/blog/feed.xml`, `/changelog/feed.xml`, etc.) or `null`
608
+ - `mainFeedUrl` - Main feed URL (always `/feed.xml`)
609
+ - `collection` - Collection/route name (`'blog'`, `'changelog'`, etc.) or `null`
610
+ - `hasFeed` - Boolean indicating if current route has a specific feed
611
+
612
+ #### SPA Navigation Support
613
+
614
+ **Important:** When using layout `ssr.data`, use `<Link>` components (not `<a>` tags) for proper client-side navigation:
615
+
616
+ ```tsx
617
+ import { Link } from 'reroute-js/react';
618
+
619
+ // ✅ Good - prefetches layout data on hover
620
+ <Link to="/announcements">Announcements</Link>
621
+
622
+ // ❌ Bad - full page reload, no prefetch
623
+ <a href="/announcements">Announcements</a>
624
+ ```
625
+
394
626
  ## 📖 Learn More
395
627
 
396
628
  - [Examples](./examples) - Example projects to get started
@@ -3,12 +3,13 @@
3
3
  "description": "A Reroute application",
4
4
  "version": "0.0.0",
5
5
  "scripts": {
6
- "types": "tsc --noEmit",
7
- "gen": "reroute gen",
8
- "start": "reroute start",
9
- "dev": "reroute dev",
10
- "build": "reroute build",
11
- "analyze": "reroute analyze --prod --open"
6
+ "types": "tsc --noEmit",
7
+ "gen": "reroute gen",
8
+ "start": "reroute start --prod",
9
+ "dev": "reroute dev",
10
+ "build": "reroute build",
11
+ "kill": "bunx kill-port 3000",
12
+ "analyze": "reroute analyze --prod --open"
12
13
  },
13
14
  "private": true,
14
15
  "dependencies": {
@@ -3,10 +3,5 @@ import { defineConfig } from 'reroute-js/core';
3
3
  export default defineConfig({
4
4
  options: {
5
5
  app: './src/client/App',
6
- maxAge: 3600,
7
- compression: true
8
- },
9
- streaming: {
10
- enabled: true,
11
6
  },
12
7
  });
@@ -5,7 +5,10 @@ const app = new Elysia()
5
5
  .use(
6
6
  reroute(),
7
7
  )
8
- .get('/api/message', () => ({ message: 'Hello from server' }))
8
+ .get('/api/message', () => {
9
+ console.log('[api] log from my api')
10
+ return { message: 'Hello from server' }
11
+ })
9
12
  .listen(Number(Bun.env.PORT || '3000'));
10
13
 
11
- console.log(`[reroute] Running at ${app.server?.hostname}:${app.server?.port}`);
14
+ console.log(`[app] Running at ${app.server?.hostname}:${app.server?.port}`);
@@ -3,12 +3,13 @@
3
3
  "description": "A Reroute application",
4
4
  "version": "0.0.0",
5
5
  "scripts": {
6
- "types": "tsc --noEmit",
7
- "gen": "reroute gen",
8
- "start": "reroute start",
9
- "dev": "reroute dev",
10
- "build": "reroute build",
11
- "analyze": "reroute analyze --prod --open"
6
+ "types": "tsc --noEmit",
7
+ "gen": "reroute gen",
8
+ "start": "PORT=3001 reroute start --prod",
9
+ "dev": "PORT=3001 reroute dev",
10
+ "build": "reroute build",
11
+ "kill": "bunx kill-port 3001",
12
+ "analyze": "reroute analyze --prod --open"
12
13
  },
13
14
  "private": true,
14
15
  "dependencies": {
@@ -9,8 +9,8 @@ const app = new Elysia()
9
9
  console.log('[api] log from my api');
10
10
  return { message: 'Hello from server' };
11
11
  })
12
- .listen(Number(Bun.env.PORT || '3000'));
12
+ .listen(Number(Bun.env.PORT || '3001'));
13
13
 
14
14
  console.log(
15
- `[reroute] Blog running at ${app.server?.hostname}:${app.server?.port} on ${Bun.env.NODE_ENV || 'development'}`,
15
+ `[app] Blog running at ${app.server?.hostname}:${app.server?.port} on ${Bun.env.NODE_ENV || 'development'}`,
16
16
  );
@@ -4,12 +4,13 @@
4
4
  "description": "A Reroute application",
5
5
  "private": true,
6
6
  "scripts": {
7
- "types": "tsc --noEmit",
8
- "gen": "reroute gen",
9
- "start": "reroute start",
10
- "dev": "reroute dev",
11
- "build": "reroute build",
12
- "analyze": "reroute analyze --prod --open"
7
+ "types": "tsc --noEmit",
8
+ "gen": "reroute gen",
9
+ "start": "PORT=3002 reroute start --prod",
10
+ "dev": "PORT=3002 reroute dev",
11
+ "build": "reroute build",
12
+ "kill": "bunx kill-port 3002",
13
+ "analyze": "reroute analyze --prod --open"
13
14
  },
14
15
  "dependencies": {
15
16
  "reroute-js": "latest",
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "{{PROJECT_NAME}}",
3
+ "version": "0.0.0",
4
+ "description": "A Reroute application",
5
+ "private": true,
6
+ "scripts": {
7
+ "types": "tsc --noEmit",
8
+ "gen": "reroute gen",
9
+ "start": "PORT=3003 reroute start --prod",
10
+ "dev": "PORT=3003 reroute dev",
11
+ "build": "reroute build",
12
+ "kill": "bunx kill-port 3003",
13
+ "analyze": "reroute analyze --prod --open"
14
+ },
15
+ "dependencies": {
16
+ "reroute-js": "latest",
17
+ "elysia": "^1.4.12",
18
+ "react": "^19.2.0",
19
+ "react-dom": "^19.2.0",
20
+ "sharp": "^0.34.4"
21
+ },
22
+ "devDependencies": {
23
+ "@types/bun": "latest",
24
+ "@types/react": "^19.2.2",
25
+ "@types/react-dom": "^19.2.2",
26
+ "typescript": "^5"
27
+ }
28
+ }
@@ -0,0 +1,23 @@
1
+ import { defineConfig } from 'reroute-js/core';
2
+
3
+ export default defineConfig({
4
+ options: {
5
+ app: './src/client/App',
6
+ maxAge: 3600,
7
+ compression: true,
8
+ },
9
+ sitemap: {
10
+ enabled: true,
11
+ baseUrl: 'http://localhost:3003',
12
+ // Test pagination with small page size (default 50k)
13
+ // maxUrlsPerPage: 5,
14
+ // Custom URL extractor - products use SKU instead of default fields
15
+ extractUrl: (item, routePattern) => {
16
+ if (routePattern === '/products' && item.sku) {
17
+ return item.sku;
18
+ }
19
+ return null; // fall back to defaults (slug, id, name, etc.)
20
+ },
21
+ extractLastmod: (item) => item.updatedAt || item.date,
22
+ },
23
+ });
@@ -0,0 +1,25 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "useDefineForClassFields": true,
5
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
6
+ "module": "ESNext",
7
+ "skipLibCheck": true,
8
+ "moduleResolution": "bundler",
9
+ "isolatedModules": true,
10
+ "baseUrl": ".",
11
+ "rootDir": ".",
12
+ "declaration": true,
13
+ "declarationMap": true,
14
+ "outDir": "dist/types",
15
+ "emitDeclarationOnly": true,
16
+ "strict": true,
17
+ "noUnusedLocals": true,
18
+ "noUnusedParameters": true,
19
+ "noFallthroughCasesInSwitch": true,
20
+ "jsx": "react-jsx",
21
+ "types": ["bun", "node"]
22
+ },
23
+ "include": ["**/*.ts", "**/*.tsx"],
24
+ "exclude": ["node_modules", "dist"]
25
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "{{PROJECT_NAME}}",
3
+ "version": "0.0.0",
4
+ "description": "A Reroute application",
5
+ "private": true,
6
+ "scripts": {
7
+ "types": "tsc --noEmit",
8
+ "gen": "reroute gen",
9
+ "start": "PORT=3004 reroute start --prod",
10
+ "dev": "PORT=3004 reroute dev",
11
+ "build": "reroute build",
12
+ "kill": "bunx kill-port 3004",
13
+ "analyze": "reroute analyze --prod --open"
14
+ },
15
+ "dependencies": {
16
+ "reroute-js": "latest",
17
+ "elysia": "^1.4.12",
18
+ "react": "^19.2.0",
19
+ "react-dom": "^19.2.0",
20
+ "sharp": "^0.34.4"
21
+ },
22
+ "devDependencies": {
23
+ "@types/bun": "latest",
24
+ "@types/react": "^19.2.2",
25
+ "@types/react-dom": "^19.2.2",
26
+ "typescript": "^5"
27
+ }
28
+ }
@@ -0,0 +1,23 @@
1
+ import { defineConfig } from 'reroute-js/core';
2
+
3
+ export default defineConfig({
4
+ options: {
5
+ app: './src/client/App',
6
+ maxAge: 3600,
7
+ compression: true,
8
+ },
9
+ sitemap: {
10
+ enabled: true,
11
+ baseUrl: 'http://localhost:3003',
12
+ // Test pagination with small page size (default 50k)
13
+ // maxUrlsPerPage: 5,
14
+ // Custom URL extractor - products use SKU instead of default fields
15
+ extractUrl: (item, routePattern) => {
16
+ if (routePattern === '/products' && item.sku) {
17
+ return item.sku;
18
+ }
19
+ return null; // fall back to defaults (slug, id, name, etc.)
20
+ },
21
+ extractLastmod: (item) => item.updatedAt || item.date,
22
+ },
23
+ });
@@ -0,0 +1,25 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "useDefineForClassFields": true,
5
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
6
+ "module": "ESNext",
7
+ "skipLibCheck": true,
8
+ "moduleResolution": "bundler",
9
+ "isolatedModules": true,
10
+ "baseUrl": ".",
11
+ "rootDir": ".",
12
+ "declaration": true,
13
+ "declarationMap": true,
14
+ "outDir": "dist/types",
15
+ "emitDeclarationOnly": true,
16
+ "strict": true,
17
+ "noUnusedLocals": true,
18
+ "noUnusedParameters": true,
19
+ "noFallthroughCasesInSwitch": true,
20
+ "jsx": "react-jsx",
21
+ "types": ["bun", "node"]
22
+ },
23
+ "include": ["**/*.ts", "**/*.tsx"],
24
+ "exclude": ["node_modules", "dist"]
25
+ }
@@ -4,12 +4,13 @@
4
4
  "description": "A Reroute store application with Tailwind CSS v4",
5
5
  "private": true,
6
6
  "scripts": {
7
- "types": "tsc --noEmit",
8
- "gen": "reroute gen",
9
- "start": "reroute start",
10
- "dev": "reroute dev",
11
- "build": "reroute build",
12
- "analyze": "reroute analyze --prod --open"
7
+ "types": "tsc --noEmit",
8
+ "gen": "reroute gen",
9
+ "start": "PORT=3005 reroute start --prod",
10
+ "dev": "PORT=3005 reroute dev",
11
+ "build": "reroute build",
12
+ "kill": "bunx kill-port 3005",
13
+ "analyze": "reroute analyze --prod --open"
13
14
  },
14
15
  "dependencies": {
15
16
  "reroute-js": "latest",
@@ -1,13 +1,10 @@
1
1
  import { Elysia } from 'elysia';
2
2
  import { reroute } from 'reroute-js/elysia';
3
3
 
4
-
5
4
  const app = new Elysia()
6
- .use(
7
- reroute(),
8
- )
9
- .listen(Number(Bun.env.PORT || '3001'));
5
+ .use(reroute())
6
+ .listen(Number(Bun.env.PORT || '3005'));
10
7
 
11
8
  console.log(
12
- `[reroute] Store running at ${app.server?.hostname}:${app.server?.port} on ${Bun.env.NODE_ENV || 'development'}`,
9
+ `[app] Store example running at ${app.server?.hostname}:${app.server?.port} on ${Bun.env.NODE_ENV || 'development'}`,
13
10
  );
@@ -4,12 +4,13 @@
4
4
  "description": "A Reroute application",
5
5
  "private": true,
6
6
  "scripts": {
7
- "types": "tsc --noEmit",
8
- "gen": "reroute gen",
9
- "start": "reroute start",
10
- "dev": "reroute dev",
11
- "build": "reroute build",
12
- "analyze": "reroute analyze --prod --open"
7
+ "types": "tsc --noEmit",
8
+ "gen": "reroute gen",
9
+ "start": "PORT=3006 reroute start --prod",
10
+ "dev": "PORT=3006 reroute dev",
11
+ "build": "reroute build",
12
+ "kill": "bunx kill-port 3006",
13
+ "analyze": "reroute analyze --prod --open"
13
14
  },
14
15
  "dependencies": {
15
16
  "reroute-js": "latest",
package/cli/bin.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * reroute-js v0.11.5
2
+ * reroute-js v0.12.0
3
3
  *
4
4
  * @license MIT
5
5
  * @copyright 2025 stewones <hi@stewan.io>