reroute-js 0.45.11 → 0.46.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/README.md +100 -2
- package/_/blog/src/client/routes/blog/[layout].tsx +45 -13
- package/_/blog/src/client/routes/blog/content/pt-BR/1-hello-world.tsx +27 -0
- package/_/blog/src/client/routes/index.tsx +4 -4
- package/_/search/src/client/routes/docs/content/content-collections.md +18 -0
- package/cli/bin.d.ts +2 -2
- package/cli/bin.js +1175 -431
- package/cli/bin.js.map +33 -24
- package/cli/index.d.ts +2 -2
- package/cli/index.js +5 -5
- package/cli/index.js.map +1 -1
- package/cli/src/cli.d.ts +2 -2
- package/cli/src/commands/analyze.d.ts +2 -2
- package/cli/src/commands/build.d.ts +2 -2
- package/cli/src/commands/dev.d.ts +2 -2
- package/cli/src/commands/gen.d.ts +2 -2
- package/cli/src/commands/gen.d.ts.map +1 -1
- package/cli/src/commands/index.d.ts +2 -2
- package/cli/src/commands/init.d.ts +2 -2
- package/cli/src/commands/lib/assets.d.ts +2 -2
- package/cli/src/commands/lib/bundler.d.ts +2 -2
- package/cli/src/commands/lib/command.d.ts +2 -2
- package/cli/src/commands/lib/env.d.ts +2 -2
- package/cli/src/commands/lib/index.d.ts +2 -2
- package/cli/src/commands/lib/log.d.ts +2 -2
- package/cli/src/commands/lib/markdown/availability.d.ts +2 -2
- package/cli/src/commands/lib/markdown/index.d.ts +2 -2
- package/cli/src/commands/lib/markdown/processor.d.ts +2 -2
- package/cli/src/commands/lib/production.d.ts +2 -2
- package/cli/src/commands/lib/server.d.ts +2 -2
- package/cli/src/commands/lib/streaming/analyzer.d.ts +2 -2
- package/cli/src/commands/lib/streaming/suspense.d.ts +2 -2
- package/cli/src/commands/lib/tailwind.d.ts +2 -2
- package/cli/src/commands/lib/terminal-ui.d.ts +2 -2
- package/cli/src/commands/lib/version.d.ts +2 -2
- package/cli/src/commands/og.d.ts +2 -2
- package/cli/src/commands/start.d.ts +2 -2
- package/cli/src/index.d.ts +2 -2
- package/core/index.d.ts +2 -2
- package/core/index.js +827 -192
- package/core/index.js.map +32 -23
- package/core/src/bundler/hash.d.ts +2 -2
- package/core/src/bundler/index.d.ts +2 -2
- package/core/src/config.d.ts +6 -3
- package/core/src/config.d.ts.map +1 -1
- package/core/src/content/discovery.d.ts +2 -2
- package/core/src/content/index.d.ts +2 -2
- package/core/src/content/metadata.d.ts +2 -2
- package/core/src/i18n/catalog.d.ts +17 -0
- package/core/src/i18n/catalog.d.ts.map +1 -0
- package/core/src/i18n/discover.d.ts +19 -0
- package/core/src/i18n/discover.d.ts.map +1 -0
- package/core/src/i18n/index.d.ts +17 -0
- package/core/src/i18n/index.d.ts.map +1 -0
- package/core/src/i18n/messages.d.ts +18 -0
- package/core/src/i18n/messages.d.ts.map +1 -0
- package/core/src/i18n/negotiate.d.ts +18 -0
- package/core/src/i18n/negotiate.d.ts.map +1 -0
- package/core/src/i18n/pathname.d.ts +34 -0
- package/core/src/i18n/pathname.d.ts.map +1 -0
- package/core/src/i18n/resolve.d.ts +22 -0
- package/core/src/i18n/resolve.d.ts.map +1 -0
- package/core/src/i18n/types.d.ts +68 -0
- package/core/src/i18n/types.d.ts.map +1 -0
- package/core/src/index.d.ts +3 -2
- package/core/src/index.d.ts.map +1 -1
- package/core/src/llms/extractor.d.ts +2 -2
- package/core/src/llms/formatter.d.ts +2 -2
- package/core/src/llms/full-generator.d.ts +2 -2
- package/core/src/llms/index-generator.d.ts +2 -2
- package/core/src/llms/index.d.ts +2 -2
- package/core/src/og/discovery.d.ts +2 -2
- package/core/src/og/discovery.d.ts.map +1 -1
- package/core/src/og/index.d.ts +2 -2
- package/core/src/og/meta.d.ts +2 -2
- package/core/src/og/render.d.ts +2 -2
- package/core/src/og/types.d.ts +2 -2
- package/core/src/robots/discovery.d.ts +2 -2
- package/core/src/robots/generator.d.ts +2 -2
- package/core/src/robots/index.d.ts +2 -2
- package/core/src/robots/policies.d.ts +2 -2
- package/core/src/rss/discovery.d.ts +4 -2
- package/core/src/rss/discovery.d.ts.map +1 -1
- package/core/src/rss/generator.d.ts +2 -2
- package/core/src/rss/index.d.ts +2 -2
- package/core/src/sitemap/discovery.d.ts +7 -2
- package/core/src/sitemap/discovery.d.ts.map +1 -1
- package/core/src/sitemap/generator.d.ts +2 -2
- package/core/src/sitemap/generator.d.ts.map +1 -1
- package/core/src/sitemap/index.d.ts +2 -2
- package/core/src/ssr/index.d.ts +2 -2
- package/core/src/ssr/lib/cache.d.ts +2 -2
- package/core/src/ssr/lib/cleanup.d.ts +2 -2
- package/core/src/ssr/lib/collections.d.ts +2 -2
- package/core/src/ssr/lib/compression.d.ts +2 -2
- package/core/src/ssr/lib/compute/content.d.ts +2 -9
- package/core/src/ssr/lib/compute/content.d.ts.map +1 -1
- package/core/src/ssr/lib/compute/index.d.ts +2 -2
- package/core/src/ssr/lib/compute/index.d.ts.map +1 -1
- package/core/src/ssr/lib/compute/layouts.d.ts +2 -2
- package/core/src/ssr/lib/compute/routes.d.ts +2 -2
- package/core/src/ssr/lib/compute/routes.d.ts.map +1 -1
- package/core/src/ssr/lib/content-path.d.ts +22 -0
- package/core/src/ssr/lib/content-path.d.ts.map +1 -0
- package/core/src/ssr/lib/data.d.ts +2 -2
- package/core/src/ssr/lib/data.d.ts.map +1 -1
- package/core/src/ssr/lib/html.d.ts +2 -2
- package/core/src/ssr/lib/imports.d.ts +2 -2
- package/core/src/ssr/lib/index.d.ts +3 -2
- package/core/src/ssr/lib/index.d.ts.map +1 -1
- package/core/src/ssr/lib/layouts.d.ts +2 -2
- package/core/src/ssr/lib/metadata.d.ts +2 -2
- package/core/src/ssr/lib/metadata.d.ts.map +1 -1
- package/core/src/ssr/lib/mime.d.ts +2 -2
- package/core/src/ssr/lib/modules.d.ts +4 -4
- package/core/src/ssr/lib/modules.d.ts.map +1 -1
- package/core/src/ssr/lib/path.d.ts +2 -2
- package/core/src/ssr/lib/preload.d.ts +2 -2
- package/core/src/ssr/lib/preload.d.ts.map +1 -1
- package/core/src/ssr/lib/route-match.d.ts +20 -0
- package/core/src/ssr/lib/route-match.d.ts.map +1 -0
- package/core/src/ssr/lib/scripts/collections.d.ts +2 -2
- package/core/src/ssr/lib/scripts/data.d.ts +3 -3
- package/core/src/ssr/lib/scripts/data.d.ts.map +1 -1
- package/core/src/ssr/lib/scripts/escape.d.ts +2 -2
- package/core/src/ssr/lib/scripts/feeds.d.ts +2 -2
- package/core/src/ssr/lib/scripts/index.d.ts +2 -2
- package/core/src/ssr/lib/seed.d.ts +2 -2
- package/core/src/ssr/lib/seed.d.ts.map +1 -1
- package/core/src/ssr/lib/serialize.d.ts +2 -2
- package/core/src/ssr/lib/setup.d.ts +3 -3
- package/core/src/ssr/lib/setup.d.ts.map +1 -1
- package/core/src/ssr/lib/styles.d.ts +2 -2
- package/core/src/ssr/lib/template.d.ts +2 -2
- package/core/src/ssr/lib/types.d.ts +2 -2
- package/core/src/ssr/render.d.ts +4 -2
- package/core/src/ssr/render.d.ts.map +1 -1
- package/core/src/ssr/stream.d.ts +4 -2
- package/core/src/ssr/stream.d.ts.map +1 -1
- package/elysia/index.d.ts +2 -2
- package/elysia/index.js +1072 -276
- package/elysia/index.js.map +37 -27
- package/elysia/src/index.d.ts +2 -2
- package/elysia/src/libs/assets.d.ts +2 -2
- package/elysia/src/libs/cache.d.ts +2 -2
- package/elysia/src/libs/caching.d.ts +2 -2
- package/elysia/src/libs/http.d.ts +2 -2
- package/elysia/src/libs/i18n.d.ts +26 -0
- package/elysia/src/libs/i18n.d.ts.map +1 -0
- package/elysia/src/libs/image.d.ts +2 -2
- package/elysia/src/libs/index.d.ts +2 -2
- package/elysia/src/libs/llms.d.ts +2 -2
- package/elysia/src/libs/response.d.ts +2 -2
- package/elysia/src/libs/serving.d.ts +2 -2
- package/elysia/src/plugin.d.ts +2 -2
- package/elysia/src/routes/artifacts.d.ts +2 -2
- package/elysia/src/routes/content.d.ts +2 -2
- package/elysia/src/routes/image.d.ts +2 -2
- package/elysia/src/routes/index.d.ts +2 -2
- package/elysia/src/routes/internal.d.ts +2 -2
- package/elysia/src/routes/llms.d.ts +2 -2
- package/elysia/src/routes/og.d.ts +2 -2
- package/elysia/src/routes/og.d.ts.map +1 -1
- package/elysia/src/routes/redirects.d.ts +2 -2
- package/elysia/src/routes/robots.d.ts +2 -2
- package/elysia/src/routes/rss.d.ts +2 -2
- package/elysia/src/routes/rss.d.ts.map +1 -1
- package/elysia/src/routes/search.d.ts +2 -2
- package/elysia/src/routes/search.d.ts.map +1 -1
- package/elysia/src/routes/sitemap.d.ts +2 -2
- package/elysia/src/routes/ssr.d.ts +2 -2
- package/elysia/src/routes/ssr.d.ts.map +1 -1
- package/elysia/src/routes/static.d.ts +2 -2
- package/elysia/src/types.d.ts +2 -2
- package/package.json +7 -6
- package/react/index.d.ts +2 -2
- package/react/index.js +565 -171
- package/react/index.js.map +12 -10
- package/react/src/components/ClientOnly.d.ts +2 -2
- package/react/src/components/ContentRoute.d.ts +3 -3
- package/react/src/components/ContentRoute.d.ts.map +1 -1
- package/react/src/components/Image.d.ts +2 -2
- package/react/src/components/LazyRoute.d.ts +2 -2
- package/react/src/components/Link.d.ts +2 -2
- package/react/src/components/Link.d.ts.map +1 -1
- package/react/src/components/Markdown.d.ts +2 -2
- package/react/src/components/Outlet.d.ts +2 -2
- package/react/src/components/index.d.ts +2 -2
- package/react/src/hooks/index.d.ts +2 -2
- package/react/src/hooks/useContent.d.ts +2 -2
- package/react/src/hooks/useContent.d.ts.map +1 -1
- package/react/src/hooks/useData.d.ts +2 -2
- package/react/src/hooks/useFeed.d.ts +2 -2
- package/react/src/hooks/useLayoutData.d.ts +2 -2
- package/react/src/hooks/useLlms.d.ts +2 -2
- package/react/src/hooks/useNavigate.d.ts +2 -2
- package/react/src/hooks/useParams.d.ts +2 -2
- package/react/src/hooks/useRouter.d.ts +2 -2
- package/react/src/hooks/useSearch.d.ts +2 -2
- package/react/src/hooks/useSearch.d.ts.map +1 -1
- package/react/src/hooks/useSearchParams.d.ts +2 -2
- package/react/src/hooks/useToc.d.ts +2 -2
- package/react/src/i18n/LocaleProvider.d.ts +49 -0
- package/react/src/i18n/LocaleProvider.d.ts.map +1 -0
- package/react/src/i18n/helpers.d.ts +24 -0
- package/react/src/i18n/helpers.d.ts.map +1 -0
- package/react/src/i18n/index.d.ts +13 -0
- package/react/src/i18n/index.d.ts.map +1 -0
- package/react/src/index.d.ts +3 -2
- package/react/src/index.d.ts.map +1 -1
- package/react/src/lib/collection.d.ts +2 -2
- package/react/src/lib/content.d.ts +4 -3
- package/react/src/lib/content.d.ts.map +1 -1
- package/react/src/lib/head.d.ts +2 -2
- package/react/src/lib/index.d.ts +2 -2
- package/react/src/lib/lazy-route.d.ts +2 -2
- package/react/src/lib/route-loader.d.ts +2 -2
- package/react/src/providers/ContentProvider.d.ts +3 -3
- package/react/src/providers/ContentProvider.d.ts.map +1 -1
- package/react/src/providers/RerouteProvider.d.ts +8 -6
- package/react/src/providers/RerouteProvider.d.ts.map +1 -1
- package/react/src/providers/RouterProvider.d.ts +2 -2
- package/react/src/providers/index.d.ts +2 -2
- package/react/src/types/any.d.ts +2 -2
- package/react/src/types/index.d.ts +2 -2
- package/react/src/types/router.d.ts +2 -2
- package/telemetry/react.d.ts +2 -2
- package/telemetry/react.js +8 -4
- package/telemetry/react.js.map +2 -2
- package/telemetry/server.d.ts +2 -2
- package/telemetry/server.js +60 -5
- package/telemetry/server.js.map +22 -17
- package/telemetry/src/react/api.d.ts +2 -2
- package/telemetry/src/react/context.d.ts +2 -2
- package/telemetry/src/react/index.d.ts +2 -2
- package/telemetry/src/react/telemetry.d.ts +2 -2
- package/telemetry/src/server/context.d.ts +2 -2
- package/telemetry/src/server/headers/extractor.d.ts +2 -2
- package/telemetry/src/server/headers/index.d.ts +2 -2
- package/telemetry/src/server/headers/presets.d.ts +2 -2
- package/telemetry/src/server/index.d.ts +2 -2
- package/telemetry/src/server/instrumentation.d.ts +2 -2
- package/telemetry/src/server/plugin.d.ts +2 -2
- package/telemetry/src/server/sourcemap.d.ts +2 -2
package/README.md
CHANGED
|
@@ -22,6 +22,12 @@ Reroute is a feature-rich file-based routing framework for building fullstack Re
|
|
|
22
22
|
- [Environment Files](#environment-files)
|
|
23
23
|
- [Security](#security)
|
|
24
24
|
- [TypeScript Support](#typescript-support)
|
|
25
|
+
- [🌍 Internationalization (i18n)](#-internationalization-i18n)
|
|
26
|
+
- [Enable](#enable)
|
|
27
|
+
- [URL Rules](#url-rules)
|
|
28
|
+
- [UI Strings](#ui-strings)
|
|
29
|
+
- [SEO & Feeds](#seo--feeds)
|
|
30
|
+
- [Config](#config)
|
|
25
31
|
- [📝 Markdown Routes](#-markdown-routes)
|
|
26
32
|
- [Installation](#installation)
|
|
27
33
|
- [Creating Markdown Routes](#creating-markdown-routes)
|
|
@@ -74,6 +80,7 @@ Reroute is a feature-rich file-based routing framework for building fullstack Re
|
|
|
74
80
|
|
|
75
81
|
### 📄 Content Management
|
|
76
82
|
- 📚 **Content Collections** - Organize content by collections (blog posts, docs, etc.)
|
|
83
|
+
- 🌍 **Internationalization** - Opt-in, collection-scoped i18n via `locales/` + `content/{locale}/`
|
|
77
84
|
- 🔍 **Content Discovery** - Automatic scanning and indexing of content files
|
|
78
85
|
- 🏷️ **Metadata Extraction** - Support for content metadata
|
|
79
86
|
- 📑 **Content Registry** - Pre-generated content index for fast lookups
|
|
@@ -116,8 +123,11 @@ Reroute is a feature-rich file-based routing framework for building fullstack Re
|
|
|
116
123
|
- `useLlms()` - Discover LLM-friendly content URLs for current route
|
|
117
124
|
- `useSearch()` - Client-side content search with debouncing
|
|
118
125
|
- `useToc()` - Auto-extract table of contents from markdown headings
|
|
126
|
+
- 🌍 **i18n**:
|
|
127
|
+
- `t(key, values?)` - Plain translator (ICU MessageFormat); not a hook
|
|
128
|
+
- `useLocale()` - Active locale, available locales, and `setLocale()`
|
|
119
129
|
- 🧩 **Components**:
|
|
120
|
-
- `<Link>` - Client-side navigation with automatic prefetching
|
|
130
|
+
- `<Link>` - Client-side navigation with automatic prefetching (localizes content hrefs)
|
|
121
131
|
- `<Image>` - Optimized images with automatic format negotiation and lazy loading
|
|
122
132
|
- `<Outlet>` - Render nested route components
|
|
123
133
|
- `<ContentRoute>` - Dynamic content rendering with metadata injection
|
|
@@ -208,6 +218,7 @@ Reroute is a feature-rich file-based routing framework for building fullstack Re
|
|
|
208
218
|
### 🗺️ Sitemap Generation
|
|
209
219
|
- 🔍 **Auto-Discovery** - Automatically discovers static routes, content collections, and ssr.data routes
|
|
210
220
|
- 📄 **XML Generation** - Standards-compliant sitemap.xml following Google's specifications
|
|
221
|
+
- 🌍 **i18n Alternates** - `xhtml:link` hreflang entries for localized content
|
|
211
222
|
- 💾 **Smart Caching** - Generated on first request and cached according to maxAge
|
|
212
223
|
- 📊 **Auto-Pagination** - Automatically splits into multiple files for sites with 50k+ URLs
|
|
213
224
|
- 🎨 **Custom Extractors** - Content-agnostic URL and date extraction via configuration
|
|
@@ -225,6 +236,7 @@ Reroute is a feature-rich file-based routing framework for building fullstack Re
|
|
|
225
236
|
- 🔍 **Auto-Discovery** - Discovers content collections, route ssr.data, and layout ssr.data
|
|
226
237
|
- 📄 **RSS & Atom Support** - Standards-compliant RSS 2.0 and Atom 1.0 formats
|
|
227
238
|
- 📚 **Per-Collection Feeds** - Each collection gets its own feed (e.g., /blog/feed.xml)
|
|
239
|
+
- 🌍 **Locale Filter** - `?lang=` filters feed items by content locale
|
|
228
240
|
- 💾 **Smart Caching** - Generated on first request and cached according to maxAge
|
|
229
241
|
- 🎨 **Custom Extractors** - Content-agnostic extraction for title, description, author, pubDate
|
|
230
242
|
|
|
@@ -623,6 +635,92 @@ interface ImportMeta {
|
|
|
623
635
|
}
|
|
624
636
|
```
|
|
625
637
|
|
|
638
|
+
## 🌍 Internationalization (i18n)
|
|
639
|
+
|
|
640
|
+
Opt-in and **collection-scoped** — not site-wide locale prefixes. Enabled only when a `locales/` directory exists at the app root.
|
|
641
|
+
|
|
642
|
+
### Enable
|
|
643
|
+
|
|
644
|
+
```
|
|
645
|
+
locales/
|
|
646
|
+
en-US.json # default locale catalog
|
|
647
|
+
pt-BR.json
|
|
648
|
+
src/client/routes/blog/content/
|
|
649
|
+
hello-world.tsx # default locale (unprefixed URL)
|
|
650
|
+
pt-BR/
|
|
651
|
+
hello-world.tsx # /blog/pt-BR/hello-world
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
```json
|
|
655
|
+
// locales/en-US.json
|
|
656
|
+
{
|
|
657
|
+
"nav": { "home": "Home" },
|
|
658
|
+
"blog": {
|
|
659
|
+
"postsCount": "{count, plural, =0 {No posts} one {# post} other {# posts}}"
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
### URL Rules
|
|
665
|
+
|
|
666
|
+
| Locale | URL |
|
|
667
|
+
|--------|-----|
|
|
668
|
+
| Default (`en-US`) | `/blog/hello-world` |
|
|
669
|
+
| Other | `/blog/pt-BR/hello-world` |
|
|
670
|
+
| Non-content routes | unchanged (`/about`, `/`) |
|
|
671
|
+
|
|
672
|
+
- Flat files under `content/` are the default locale; nest under `content/{locale}/` for translations
|
|
673
|
+
- Collections without locale folders behave as before
|
|
674
|
+
- Default-locale prefix (`/blog/en-US/...`) 302s to the unprefixed URL
|
|
675
|
+
- Optional negotiate: `Accept-Language` / cookie can 302 default content URLs to a localized path (`i18n.redirectContentOnNegotiate`, default `true`)
|
|
676
|
+
|
|
677
|
+
### UI Strings
|
|
678
|
+
|
|
679
|
+
```tsx
|
|
680
|
+
import { t, useLocale, Link } from 'reroute-js/react';
|
|
681
|
+
|
|
682
|
+
function Nav() {
|
|
683
|
+
const { locale, locales, setLocale } = useLocale();
|
|
684
|
+
return (
|
|
685
|
+
<>
|
|
686
|
+
<Link to="/">{t('nav.home')}</Link>
|
|
687
|
+
<select value={locale} onChange={(e) => setLocale(e.target.value)}>
|
|
688
|
+
{locales.map((l) => (
|
|
689
|
+
<option key={l} value={l}>{l}</option>
|
|
690
|
+
))}
|
|
691
|
+
</select>
|
|
692
|
+
<footer>{t('blog.postsCount', { count: 5 })}</footer>
|
|
693
|
+
</>
|
|
694
|
+
);
|
|
695
|
+
}
|
|
696
|
+
```
|
|
697
|
+
|
|
698
|
+
- `t(key, values?)` — plain function (not a hook); ICU MessageFormat supported
|
|
699
|
+
- `useLocale()` — `{ locale, locales, defaultLocale, enabled, setLocale }`
|
|
700
|
+
- `Link` auto-localizes content hrefs; cookie (`reroute-locale`) + `Accept-Language` resolve UI locale
|
|
701
|
+
|
|
702
|
+
### SEO & Feeds
|
|
703
|
+
|
|
704
|
+
- `hreflang` + `og:locale` on content pages
|
|
705
|
+
- Sitemap includes `xhtml:link` alternates
|
|
706
|
+
- RSS / search accept `?lang=` to filter by locale
|
|
707
|
+
|
|
708
|
+
### Config
|
|
709
|
+
|
|
710
|
+
```tsx
|
|
711
|
+
// reroute.config.ts
|
|
712
|
+
export default defineConfig({
|
|
713
|
+
i18n: {
|
|
714
|
+
defaultLocale: 'en-US', // unprefixed content URLs
|
|
715
|
+
localesDir: 'locales', // catalog directory
|
|
716
|
+
cookie: 'reroute-locale',
|
|
717
|
+
redirectContentOnNegotiate: true, // 302 default content → localized URL
|
|
718
|
+
},
|
|
719
|
+
});
|
|
720
|
+
```
|
|
721
|
+
|
|
722
|
+
Feature still requires a `locales/` directory — config only overrides defaults.
|
|
723
|
+
|
|
626
724
|
## 📝 Markdown Routes
|
|
627
725
|
|
|
628
726
|
Reroute supports native markdown and MDX files as routes with frontmatter support and syntax highlighting.
|
|
@@ -1693,7 +1791,7 @@ Built-in tracing for debugging SSR, 404s, and cache behavior. Automatically trac
|
|
|
1693
1791
|
|
|
1694
1792
|
- [Examples](./examples) - Example projects to get started
|
|
1695
1793
|
- [Packages](./packages) - Reroute entrypoints
|
|
1696
|
-
- [GitHub](https://github.com/
|
|
1794
|
+
- [GitHub](https://github.com/Intenseloop/reroute) - Source code and issues
|
|
1697
1795
|
|
|
1698
1796
|
## 🏗️ Build & Deployment
|
|
1699
1797
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Link, Outlet, useData } from 'reroute-js/react';
|
|
2
1
|
import type { SSR } from 'reroute-js/core';
|
|
2
|
+
import { Link, Outlet, t, useData, useLocale } from 'reroute-js/react';
|
|
3
3
|
|
|
4
4
|
// Layout data type
|
|
5
5
|
type LayoutData = {
|
|
@@ -16,13 +16,17 @@ export const ssr: SSR<LayoutData> = {
|
|
|
16
16
|
// Get last updated timestamp from package.json mtime
|
|
17
17
|
let lastUpdated: string | undefined;
|
|
18
18
|
try {
|
|
19
|
-
const pkgPath = await import('node:path').then(p =>
|
|
20
|
-
|
|
19
|
+
const pkgPath = await import('node:path').then((p) =>
|
|
20
|
+
p.join(process.cwd(), 'package.json'),
|
|
21
|
+
);
|
|
22
|
+
const stats = await import('node:fs/promises').then((fs) =>
|
|
23
|
+
fs.stat(pkgPath),
|
|
24
|
+
);
|
|
21
25
|
lastUpdated = stats.mtime.toISOString();
|
|
22
26
|
} catch {
|
|
23
27
|
lastUpdated = new Date().toISOString();
|
|
24
28
|
}
|
|
25
|
-
|
|
29
|
+
|
|
26
30
|
return {
|
|
27
31
|
siteTitle: 'Reroute Blog',
|
|
28
32
|
tagline: 'Fast, Modern, File-Based Routing',
|
|
@@ -39,11 +43,11 @@ export const meta = {
|
|
|
39
43
|
};
|
|
40
44
|
|
|
41
45
|
export default function BlogLayout() {
|
|
42
|
-
// Access layout data - it just works!
|
|
43
46
|
const data = useData<LayoutData>();
|
|
47
|
+
const { locale, locales, setLocale, enabled } = useLocale();
|
|
48
|
+
|
|
44
49
|
return (
|
|
45
50
|
<div style={{ minHeight: '100vh', background: '#f9f9f9' }}>
|
|
46
|
-
{/* Blog Header */}
|
|
47
51
|
<header
|
|
48
52
|
style={{
|
|
49
53
|
background: '#fff',
|
|
@@ -57,6 +61,8 @@ export default function BlogLayout() {
|
|
|
57
61
|
display: 'flex',
|
|
58
62
|
alignItems: 'center',
|
|
59
63
|
justifyContent: 'space-between',
|
|
64
|
+
gap: '1rem',
|
|
65
|
+
flexWrap: 'wrap',
|
|
60
66
|
}}
|
|
61
67
|
>
|
|
62
68
|
<Link
|
|
@@ -68,7 +74,7 @@ export default function BlogLayout() {
|
|
|
68
74
|
color: '#333',
|
|
69
75
|
}}
|
|
70
76
|
>
|
|
71
|
-
📝 {
|
|
77
|
+
📝 {t('blog.title')}
|
|
72
78
|
</Link>
|
|
73
79
|
<div
|
|
74
80
|
style={{ display: 'flex', gap: '1.5rem', alignItems: 'center' }}
|
|
@@ -81,7 +87,7 @@ export default function BlogLayout() {
|
|
|
81
87
|
fontSize: '0.875rem',
|
|
82
88
|
}}
|
|
83
89
|
>
|
|
84
|
-
|
|
90
|
+
{t('nav.home')}
|
|
85
91
|
</Link>
|
|
86
92
|
<Link
|
|
87
93
|
to='/about'
|
|
@@ -91,21 +97,43 @@ export default function BlogLayout() {
|
|
|
91
97
|
fontSize: '0.875rem',
|
|
92
98
|
}}
|
|
93
99
|
>
|
|
94
|
-
|
|
100
|
+
{t('nav.about')}
|
|
95
101
|
</Link>
|
|
102
|
+
{enabled && locales.length > 1 && (
|
|
103
|
+
<label
|
|
104
|
+
style={{
|
|
105
|
+
display: 'flex',
|
|
106
|
+
alignItems: 'center',
|
|
107
|
+
gap: '0.35rem',
|
|
108
|
+
fontSize: '0.875rem',
|
|
109
|
+
color: '#666',
|
|
110
|
+
}}
|
|
111
|
+
>
|
|
112
|
+
{t('blog.language')}
|
|
113
|
+
<select
|
|
114
|
+
value={locale}
|
|
115
|
+
onChange={(e) => setLocale(e.target.value)}
|
|
116
|
+
style={{ fontSize: '0.875rem' }}
|
|
117
|
+
>
|
|
118
|
+
{locales.map((loc) => (
|
|
119
|
+
<option key={loc} value={loc}>
|
|
120
|
+
{loc}
|
|
121
|
+
</option>
|
|
122
|
+
))}
|
|
123
|
+
</select>
|
|
124
|
+
</label>
|
|
125
|
+
)}
|
|
96
126
|
</div>
|
|
97
127
|
</nav>
|
|
98
128
|
</div>
|
|
99
129
|
</header>
|
|
100
130
|
|
|
101
|
-
{/* Blog Content */}
|
|
102
131
|
<main>
|
|
103
132
|
<div style={{ maxWidth: '800px', margin: '0 auto' }}>
|
|
104
133
|
<Outlet />
|
|
105
134
|
</div>
|
|
106
135
|
</main>
|
|
107
136
|
|
|
108
|
-
{/* Blog Footer */}
|
|
109
137
|
<footer
|
|
110
138
|
style={{
|
|
111
139
|
marginTop: '4rem',
|
|
@@ -117,10 +145,14 @@ export default function BlogLayout() {
|
|
|
117
145
|
background: '#fff',
|
|
118
146
|
}}
|
|
119
147
|
>
|
|
120
|
-
<p
|
|
148
|
+
<p>
|
|
149
|
+
© {new Date().getFullYear()} {t('blog.title')}. Built with Bun,
|
|
150
|
+
Elysia, and React.
|
|
151
|
+
</p>
|
|
121
152
|
{data?.totalPosts && (
|
|
122
153
|
<p style={{ marginTop: '0.5rem', fontSize: '0.75rem' }}>
|
|
123
|
-
{data.totalPosts}
|
|
154
|
+
{t('blog.postsCount', { count: data.totalPosts })} • Last updated:{' '}
|
|
155
|
+
{new Date(data.lastUpdated).toLocaleString(locale)}
|
|
124
156
|
</p>
|
|
125
157
|
)}
|
|
126
158
|
</footer>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Page metadata and optional SSR extras. Reroute SSR will use these
|
|
2
|
+
// to generate <title>, <meta name="description"> and append any custom head.
|
|
3
|
+
const meta = {
|
|
4
|
+
title: 'Olá Mundo',
|
|
5
|
+
description: 'Este é o primeiro post usando Reroute 🎉',
|
|
6
|
+
excerpt: 'Este é um ótimo post',
|
|
7
|
+
date: '2025-10-20',
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const ssr = {
|
|
11
|
+
head: [
|
|
12
|
+
'<meta property="og:type" content="article" />',
|
|
13
|
+
'<meta name="twitter:card" content="summary_large_image" />',
|
|
14
|
+
],
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
function BlogPost() {
|
|
18
|
+
return (
|
|
19
|
+
<div>
|
|
20
|
+
<h1>Olá Mundo</h1>
|
|
21
|
+
<p>Bem-vindo ao meu blog!!!</p>
|
|
22
|
+
</div>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export { meta, ssr };
|
|
27
|
+
export default BlogPost;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { Link } from 'reroute-js/react';
|
|
1
|
+
import { Link, t } from 'reroute-js/react';
|
|
2
2
|
|
|
3
3
|
export default function HomePage() {
|
|
4
4
|
return (
|
|
5
5
|
<main style={{ padding: '2rem', maxWidth: '1200px', margin: '0 auto' }}>
|
|
6
6
|
<h1>🏠 Welcome to Reroute!</h1>
|
|
7
|
-
<p>
|
|
7
|
+
<p>{t('home.headline')}</p>
|
|
8
8
|
|
|
9
9
|
<section style={{ marginTop: '2rem' }}>
|
|
10
10
|
<h2>Navigation</h2>
|
|
@@ -25,7 +25,7 @@ export default function HomePage() {
|
|
|
25
25
|
borderRadius: '4px',
|
|
26
26
|
}}
|
|
27
27
|
>
|
|
28
|
-
|
|
28
|
+
{t('nav.about')}
|
|
29
29
|
</Link>
|
|
30
30
|
<Link
|
|
31
31
|
to='/blog'
|
|
@@ -36,7 +36,7 @@ export default function HomePage() {
|
|
|
36
36
|
borderRadius: '4px',
|
|
37
37
|
}}
|
|
38
38
|
>
|
|
39
|
-
|
|
39
|
+
{t('home.cta')}
|
|
40
40
|
</Link>
|
|
41
41
|
<Link
|
|
42
42
|
to='/docs'
|
|
@@ -35,6 +35,24 @@ src/client/routes/
|
|
|
35
35
|
└── post-3.tsx
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
+
### Multilingual content (opt-in)
|
|
39
|
+
|
|
40
|
+
Add a `locales/` folder at the app root with JSON catalogs (e.g. `en-US.json`, `pt-BR.json`) to enable i18n. Then nest translations under `content/{locale}/`:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
locales/
|
|
44
|
+
en-US.json
|
|
45
|
+
pt-BR.json
|
|
46
|
+
src/client/routes/blog/content/
|
|
47
|
+
en-US/post-1.md # or keep flat files as the default locale
|
|
48
|
+
pt-BR/post-1.md
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
- Default locale URLs stay unprefixed: `/blog/post-1`
|
|
52
|
+
- Other locales: `/blog/pt-BR/post-1`
|
|
53
|
+
- Collections without locale folders are unchanged
|
|
54
|
+
- Use `t('nav.home')` for UI strings (ICU MessageFormat supported)
|
|
55
|
+
|
|
38
56
|
### Content Files
|
|
39
57
|
|
|
40
58
|
#### Markdown Files
|
package/cli/bin.d.ts
CHANGED