reroute-js 0.2.2 → 0.3.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 +14 -0
- package/_/README.md +59 -0
- package/_/basic/package.json +24 -0
- package/_/basic/src/client/App.tsx +10 -0
- package/_/basic/src/client/components/Counter.tsx +15 -0
- package/_/basic/src/client/index.html +12 -0
- package/_/basic/src/client/index.tsx +5 -0
- package/_/basic/src/client/routes/[404].tsx +18 -0
- package/_/basic/src/client/routes/about.tsx +25 -0
- package/_/basic/src/client/routes/index.tsx +57 -0
- package/_/basic/src/index.ts +20 -0
- package/_/basic/tsconfig.json +26 -0
- package/_/blog/package.json +24 -0
- package/_/blog/src/client/App.tsx +10 -0
- package/_/blog/src/client/components/Counter.tsx +14 -0
- package/_/blog/src/client/components/RecentPosts.tsx +90 -0
- package/_/blog/src/client/index.html +13 -0
- package/_/blog/src/client/index.tsx +5 -0
- package/_/blog/src/client/routes/[404].tsx +21 -0
- package/_/blog/src/client/routes/about.tsx +31 -0
- package/_/blog/src/client/routes/blog/[404].tsx +21 -0
- package/_/blog/src/client/routes/blog/[layout].tsx +84 -0
- package/_/blog/src/client/routes/blog/[slug].tsx +11 -0
- package/_/blog/src/client/routes/blog/content/1-hello-world.tsx +27 -0
- package/_/blog/src/client/routes/blog/content/2-what-is-reroute.tsx +31 -0
- package/_/blog/src/client/routes/blog/index.tsx +70 -0
- package/_/blog/src/client/routes/index.tsx +63 -0
- package/_/blog/src/index.ts +20 -0
- package/_/blog/tsconfig.json +26 -0
- package/_/store/package.json +26 -0
- package/_/store/src/client/App.tsx +17 -0
- package/_/store/src/client/components/Header.tsx +40 -0
- package/_/store/src/client/components/ProductCard.tsx +54 -0
- package/_/store/src/client/index.html +17 -0
- package/_/store/src/client/index.tsx +7 -0
- package/_/store/src/client/lib/api.ts +153 -0
- package/_/store/src/client/routes/[404].tsx +63 -0
- package/_/store/src/client/routes/categories/[category].tsx +223 -0
- package/_/store/src/client/routes/categories/index.tsx +187 -0
- package/_/store/src/client/routes/index.tsx +126 -0
- package/_/store/src/client/routes/products/[id].tsx +238 -0
- package/_/store/src/client/routes/products/index.tsx +261 -0
- package/_/store/src/client/theme.css +306 -0
- package/_/store/src/index.ts +19 -0
- package/_/store/tsconfig.json +26 -0
- package/cli/bin.d.ts +11 -0
- package/cli/bin.d.ts.map +1 -0
- package/cli/bin.js +883 -0
- package/cli/bin.js.map +15 -0
- package/cli/index.d.ts +11 -0
- package/cli/index.d.ts.map +1 -0
- package/cli/index.js +113 -0
- package/cli/index.js.map +10 -0
- package/cli/src/cli.d.ts +16 -0
- package/cli/src/cli.d.ts.map +1 -0
- package/cli/src/commands/build.d.ts +16 -0
- package/cli/src/commands/build.d.ts.map +1 -0
- package/cli/src/commands/dev.d.ts +16 -0
- package/cli/src/commands/dev.d.ts.map +1 -0
- package/cli/src/commands/gen.d.ts +11 -0
- package/cli/src/commands/gen.d.ts.map +1 -0
- package/cli/src/commands/init.d.ts +16 -0
- package/cli/src/commands/init.d.ts.map +1 -0
- package/cli/src/libs/index.d.ts +11 -0
- package/cli/src/libs/index.d.ts.map +1 -0
- package/cli/src/libs/tailwind.d.ts +20 -0
- package/cli/src/libs/tailwind.d.ts.map +1 -0
- package/core/index.d.ts +11 -0
- package/core/index.d.ts.map +1 -0
- package/core/index.js +1138 -0
- package/core/index.js.map +25 -0
- package/core/src/bundler/hash.d.ts +11 -0
- package/core/src/bundler/hash.d.ts.map +1 -0
- package/core/src/bundler/index.d.ts +12 -0
- package/core/src/bundler/index.d.ts.map +1 -0
- package/core/src/bundler/transpile.d.ts +13 -0
- package/core/src/bundler/transpile.d.ts.map +1 -0
- package/core/src/content/discovery.d.ts +14 -0
- package/core/src/content/discovery.d.ts.map +1 -0
- package/core/src/content/index.d.ts +13 -0
- package/core/src/content/index.d.ts.map +1 -0
- package/core/src/content/metadata.d.ts +18 -0
- package/core/src/content/metadata.d.ts.map +1 -0
- package/core/src/content/registry.d.ts +11 -0
- package/core/src/content/registry.d.ts.map +1 -0
- package/core/src/index.d.ts +16 -0
- package/core/src/index.d.ts.map +1 -0
- package/core/src/ssr/data.d.ts +18 -0
- package/core/src/ssr/data.d.ts.map +1 -0
- package/core/src/ssr/index.d.ts +13 -0
- package/core/src/ssr/index.d.ts.map +1 -0
- package/core/src/ssr/modules.d.ts +17 -0
- package/core/src/ssr/modules.d.ts.map +1 -0
- package/core/src/ssr/render.d.ts +29 -0
- package/core/src/ssr/render.d.ts.map +1 -0
- package/core/src/ssr/seed.d.ts +11 -0
- package/core/src/ssr/seed.d.ts.map +1 -0
- package/core/src/template/html.d.ts +13 -0
- package/core/src/template/html.d.ts.map +1 -0
- package/core/src/template/index.d.ts +11 -0
- package/core/src/template/index.d.ts.map +1 -0
- package/core/src/types.d.ts +59 -0
- package/core/src/types.d.ts.map +1 -0
- package/core/src/utils/cache.d.ts +21 -0
- package/core/src/utils/cache.d.ts.map +1 -0
- package/core/src/utils/compression.d.ts +14 -0
- package/core/src/utils/compression.d.ts.map +1 -0
- package/core/src/utils/index.d.ts +14 -0
- package/core/src/utils/index.d.ts.map +1 -0
- package/core/src/utils/mime.d.ts +12 -0
- package/core/src/utils/mime.d.ts.map +1 -0
- package/core/src/utils/path.d.ts +15 -0
- package/core/src/utils/path.d.ts.map +1 -0
- package/elysia/index.d.ts +11 -0
- package/elysia/index.d.ts.map +1 -0
- package/elysia/index.js +2101 -0
- package/elysia/index.js.map +34 -0
- package/elysia/src/index.d.ts +12 -0
- package/elysia/src/index.d.ts.map +1 -0
- package/elysia/src/libs/http.d.ts +14 -0
- package/elysia/src/libs/http.d.ts.map +1 -0
- package/elysia/src/libs/image.d.ts +38 -0
- package/elysia/src/libs/image.d.ts.map +1 -0
- package/elysia/src/plugin.d.ts +41 -0
- package/elysia/src/plugin.d.ts.map +1 -0
- package/elysia/src/routes/artifacts.d.ts +12 -0
- package/elysia/src/routes/artifacts.d.ts.map +1 -0
- package/elysia/src/routes/content.d.ts +12 -0
- package/elysia/src/routes/content.d.ts.map +1 -0
- package/elysia/src/routes/dev.d.ts +18 -0
- package/elysia/src/routes/dev.d.ts.map +1 -0
- package/elysia/src/routes/image.d.ts +23 -0
- package/elysia/src/routes/image.d.ts.map +1 -0
- package/elysia/src/routes/ssr.d.ts +32 -0
- package/elysia/src/routes/ssr.d.ts.map +1 -0
- package/elysia/src/routes/static.d.ts +28 -0
- package/elysia/src/routes/static.d.ts.map +1 -0
- package/elysia/src/types.d.ts +44 -0
- package/elysia/src/types.d.ts.map +1 -0
- package/package.json +6 -5
- package/react/index.d.ts +11 -0
- package/react/index.d.ts.map +1 -0
- package/react/index.js +1370 -0
- package/react/index.js.map +24 -0
- package/react/src/components/ContentRoute.d.ts +22 -0
- package/react/src/components/ContentRoute.d.ts.map +1 -0
- package/react/src/components/Image.d.ts +53 -0
- package/react/src/components/Image.d.ts.map +1 -0
- package/react/src/components/Link.d.ts +17 -0
- package/react/src/components/Link.d.ts.map +1 -0
- package/react/src/components/Outlet.d.ts +16 -0
- package/react/src/components/Outlet.d.ts.map +1 -0
- package/react/src/components/index.d.ts +14 -0
- package/react/src/components/index.d.ts.map +1 -0
- package/react/src/hooks/index.d.ts +16 -0
- package/react/src/hooks/index.d.ts.map +1 -0
- package/react/src/hooks/useContent.d.ts +35 -0
- package/react/src/hooks/useContent.d.ts.map +1 -0
- package/react/src/hooks/useData.d.ts +19 -0
- package/react/src/hooks/useData.d.ts.map +1 -0
- package/react/src/hooks/useNavigate.d.ts +15 -0
- package/react/src/hooks/useNavigate.d.ts.map +1 -0
- package/react/src/hooks/useParams.d.ts +15 -0
- package/react/src/hooks/useParams.d.ts.map +1 -0
- package/react/src/hooks/useRouter.d.ts +16 -0
- package/react/src/hooks/useRouter.d.ts.map +1 -0
- package/react/src/hooks/useSearchParams.d.ts +15 -0
- package/react/src/hooks/useSearchParams.d.ts.map +1 -0
- package/react/src/index.d.ts +15 -0
- package/react/src/index.d.ts.map +1 -0
- package/react/src/providers/ContentProvider.d.ts +44 -0
- package/react/src/providers/ContentProvider.d.ts.map +1 -0
- package/react/src/providers/RerouteProvider.d.ts +34 -0
- package/react/src/providers/RerouteProvider.d.ts.map +1 -0
- package/react/src/providers/RouterProvider.d.ts +32 -0
- package/react/src/providers/RouterProvider.d.ts.map +1 -0
- package/react/src/providers/index.d.ts +13 -0
- package/react/src/providers/index.d.ts.map +1 -0
- package/react/src/types/any.d.ts +12 -0
- package/react/src/types/any.d.ts.map +1 -0
- package/react/src/types/index.d.ts +12 -0
- package/react/src/types/index.d.ts.map +1 -0
- package/react/src/types/router.d.ts +41 -0
- package/react/src/types/router.d.ts.map +1 -0
- package/react/src/utils/content.d.ts +17 -0
- package/react/src/utils/content.d.ts.map +1 -0
- package/react/src/utils/head.d.ts +15 -0
- package/react/src/utils/head.d.ts.map +1 -0
- package/react/src/utils/index.d.ts +12 -0
- package/react/src/utils/index.d.ts.map +1 -0
- package/CHANGELOG.md +0 -29
- package/packages/cli/README.md +0 -264
- package/packages/cli/bin.ts +0 -3
- package/packages/core/README.md +0 -90
- package/packages/elysia/README.md +0 -250
- package/packages/react/README.md +0 -3
package/README.md
CHANGED
|
@@ -44,6 +44,20 @@ Reroute is a dead-simple file-based routing framework for building full-stack Re
|
|
|
44
44
|
- `useData()` - Read route-level SSR data without loaders
|
|
45
45
|
- `export const ssr = { data() {} }` - Route data function executed on server
|
|
46
46
|
|
|
47
|
+
### 🖼️ Image Optimization
|
|
48
|
+
- 🎨 **Format Control** - Support for auto, AVIF, WebP, JPEG, and PNG formats
|
|
49
|
+
- 📐 **Responsive Images** - Automatic srcset generation for multiple device sizes (640-3840px)
|
|
50
|
+
- ⚡ **On-Demand Processing** - Server-side image transformation using Sharp
|
|
51
|
+
- 💾 **Smart Caching** - In-memory and disk cache for optimized images (1-year cache headers)
|
|
52
|
+
- 🔍 **Lazy Loading** - Native lazy loading with IntersectionObserver fallback for older browsers
|
|
53
|
+
- ⏫ **Priority Loading** - Opt-in eager loading for above-the-fold images
|
|
54
|
+
- 🌫️ **Blur Placeholder** - Optional blur-up effect with custom blur data URL support
|
|
55
|
+
- 🎯 **Quality Control** - Configurable quality (1-100, default: 75)
|
|
56
|
+
- 🔄 **Loading States** - Built-in spinner with customization (size, color, background, custom component)
|
|
57
|
+
- 🎨 **Custom Loader** - Override default image URL generation
|
|
58
|
+
- 📏 **Callbacks** - onLoad and onError event handlers
|
|
59
|
+
- 📱 **Sizes Attribute** - Control responsive image selection with custom sizes
|
|
60
|
+
|
|
47
61
|
### 🚀 Performance Optimizations
|
|
48
62
|
- 💾 **Smart Caching** - LRU cache for files and bundles
|
|
49
63
|
- 🔗 **Link Prefetching** - Automatic content prefetching on hover/focus
|
package/_/README.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Reroute CLI Templates
|
|
2
|
+
|
|
3
|
+
This directory contains the scaffolding templates used by the `reroute init` command.
|
|
4
|
+
|
|
5
|
+
## Structure
|
|
6
|
+
|
|
7
|
+
Each subdirectory represents a template that users can choose from:
|
|
8
|
+
|
|
9
|
+
- `basic/` - Minimal Reroute application with basic routing
|
|
10
|
+
- `blog/` - Full-featured blog with content collections and layouts
|
|
11
|
+
|
|
12
|
+
## How It Works
|
|
13
|
+
|
|
14
|
+
When a user runs `reroute init my-app --template blog`, the CLI:
|
|
15
|
+
|
|
16
|
+
1. Copies all files from the `blog/` directory to the new project directory
|
|
17
|
+
2. Replaces template variables (e.g., `{{PROJECT_NAME}}`) with actual values
|
|
18
|
+
3. Runs `bun install` to install dependencies
|
|
19
|
+
|
|
20
|
+
## Template Variables
|
|
21
|
+
|
|
22
|
+
Templates can use the following variables that will be replaced during scaffolding:
|
|
23
|
+
|
|
24
|
+
- `{{PROJECT_NAME}}` - The name of the project being created
|
|
25
|
+
|
|
26
|
+
## Adding a New Template
|
|
27
|
+
|
|
28
|
+
To add a new template:
|
|
29
|
+
|
|
30
|
+
1. Create a new directory (e.g., `docs/`)
|
|
31
|
+
2. Add all necessary files with the complete project structure
|
|
32
|
+
3. Use `{{PROJECT_NAME}}` where dynamic replacement is needed
|
|
33
|
+
4. Update `init.ts` to include the new template in the template type union
|
|
34
|
+
5. Update the CLI README to document the new template
|
|
35
|
+
|
|
36
|
+
## File Organization
|
|
37
|
+
|
|
38
|
+
Templates should follow the standard Reroute project structure:
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
template-name/
|
|
42
|
+
├── package.json # Use {{PROJECT_NAME}} for the name field
|
|
43
|
+
├── .gitignore
|
|
44
|
+
└── src/
|
|
45
|
+
├── index.ts # Server entry point
|
|
46
|
+
└── client/
|
|
47
|
+
├── App.tsx
|
|
48
|
+
├── index.tsx
|
|
49
|
+
├── index.html # Use {{PROJECT_NAME}} in the title
|
|
50
|
+
├── routes/
|
|
51
|
+
└── components/
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Notes
|
|
55
|
+
|
|
56
|
+
- TypeScript errors in template files are expected (e.g., missing imports) since they're isolated
|
|
57
|
+
- These errors will resolve once the template is copied to an actual project
|
|
58
|
+
- Keep templates minimal but functional - users can customize from there
|
|
59
|
+
- Ensure templates follow the project's code style (Biome)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{PROJECT_NAME}}",
|
|
3
|
+
"description": "A Reroute application",
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"start": "reroute gen && bun src/index.ts",
|
|
7
|
+
"dev": "reroute gen --watch & bun --watch src/index.ts",
|
|
8
|
+
"build": "reroute gen && bun build src/index.ts --target bun --compile --outfile ./dist/app"
|
|
9
|
+
},
|
|
10
|
+
"private": true,
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"reroute-js": "latest",
|
|
13
|
+
"elysia": "^1.4.13",
|
|
14
|
+
"react": "^19.2.0",
|
|
15
|
+
"react-dom": "^19.2.0",
|
|
16
|
+
"sharp": "^0.34.4"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@types/bun": "latest",
|
|
20
|
+
"@types/react": "^19.2.2",
|
|
21
|
+
"@types/react-dom": "^19.2.2",
|
|
22
|
+
"typescript": "^5"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { RerouteProvider } from 'reroute-js/react';
|
|
2
|
+
import { artifacts } from '../../.reroute';
|
|
3
|
+
|
|
4
|
+
interface AppProps {
|
|
5
|
+
pathname?: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export default function App({ pathname }: AppProps = {}) {
|
|
9
|
+
return <RerouteProvider from={{ pathname, ...artifacts }} />;
|
|
10
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
|
|
3
|
+
export default function Counter() {
|
|
4
|
+
const [count, setCount] = useState(0);
|
|
5
|
+
const increase = () => setCount((c) => c + 1);
|
|
6
|
+
|
|
7
|
+
return (
|
|
8
|
+
<section>
|
|
9
|
+
<h2>Current count: {count}</h2>
|
|
10
|
+
<button type='button' onClick={increase}>
|
|
11
|
+
Increase
|
|
12
|
+
</button>
|
|
13
|
+
</section>
|
|
14
|
+
);
|
|
15
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<title>{{PROJECT_NAME}}</title>
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<div id="root"></div>
|
|
10
|
+
<script type="module" src="./index.tsx"></script>
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export default function NotFound() {
|
|
2
|
+
return (
|
|
3
|
+
<div
|
|
4
|
+
style={{
|
|
5
|
+
padding: '2rem',
|
|
6
|
+
maxWidth: '800px',
|
|
7
|
+
margin: '0 auto',
|
|
8
|
+
textAlign: 'center',
|
|
9
|
+
}}
|
|
10
|
+
>
|
|
11
|
+
<h1>404 - Page Not Found</h1>
|
|
12
|
+
<p>The page you're looking for doesn't exist.</p>
|
|
13
|
+
<nav style={{ marginTop: '2rem' }}>
|
|
14
|
+
<a href='/'>← Back to Home</a>
|
|
15
|
+
</nav>
|
|
16
|
+
</div>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const meta = {
|
|
2
|
+
title: 'About',
|
|
3
|
+
description: 'Learn more about our application',
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
function About() {
|
|
7
|
+
return (
|
|
8
|
+
<div style={{ padding: '2rem', maxWidth: '800px', margin: '0 auto' }}>
|
|
9
|
+
<h1>About</h1>
|
|
10
|
+
<p>Welcome to your Reroute application!</p>
|
|
11
|
+
<p>
|
|
12
|
+
This page demonstrates a simple static route that maps from{' '}
|
|
13
|
+
<code>routes/about.tsx</code> to <code>/about</code>.
|
|
14
|
+
</p>
|
|
15
|
+
<nav style={{ marginTop: '2rem' }}>
|
|
16
|
+
<a href='/' style={{ marginRight: '1rem' }}>
|
|
17
|
+
← Back to Home
|
|
18
|
+
</a>
|
|
19
|
+
</nav>
|
|
20
|
+
</div>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export default About;
|
|
25
|
+
export { meta };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Link } from 'reroute-js/react';
|
|
2
|
+
import Counter from '../components/Counter';
|
|
3
|
+
|
|
4
|
+
export default function HomePage() {
|
|
5
|
+
return (
|
|
6
|
+
<main style={{ padding: '2rem', maxWidth: '1200px', margin: '0 auto' }}>
|
|
7
|
+
<h1>🏠 Welcome to Reroute!</h1>
|
|
8
|
+
<p>This is your new Reroute application.</p>
|
|
9
|
+
|
|
10
|
+
<section style={{ marginTop: '2rem' }}>
|
|
11
|
+
<h2>Navigation</h2>
|
|
12
|
+
<nav
|
|
13
|
+
style={{
|
|
14
|
+
display: 'flex',
|
|
15
|
+
gap: '1rem',
|
|
16
|
+
flexDirection: 'column',
|
|
17
|
+
maxWidth: '300px',
|
|
18
|
+
}}
|
|
19
|
+
>
|
|
20
|
+
<Link
|
|
21
|
+
to='/about'
|
|
22
|
+
style={{
|
|
23
|
+
padding: '0.5rem 1rem',
|
|
24
|
+
background: '#eee',
|
|
25
|
+
textDecoration: 'none',
|
|
26
|
+
borderRadius: '4px',
|
|
27
|
+
}}
|
|
28
|
+
>
|
|
29
|
+
About
|
|
30
|
+
</Link>
|
|
31
|
+
</nav>
|
|
32
|
+
</section>
|
|
33
|
+
|
|
34
|
+
<section
|
|
35
|
+
style={{
|
|
36
|
+
marginTop: '2rem',
|
|
37
|
+
padding: '1rem',
|
|
38
|
+
background: '#f5f5f5',
|
|
39
|
+
borderRadius: '8px',
|
|
40
|
+
}}
|
|
41
|
+
>
|
|
42
|
+
<h3>✨ Features</h3>
|
|
43
|
+
<ul>
|
|
44
|
+
<li>File-based routing</li>
|
|
45
|
+
<li>Client-side navigation (SPA)</li>
|
|
46
|
+
<li>Server-side rendering (SSR)</li>
|
|
47
|
+
<li>Type-safe route params</li>
|
|
48
|
+
<li>Automatic route generation</li>
|
|
49
|
+
</ul>
|
|
50
|
+
</section>
|
|
51
|
+
|
|
52
|
+
<section>
|
|
53
|
+
<Counter />
|
|
54
|
+
</section>
|
|
55
|
+
</main>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Elysia } from 'elysia';
|
|
2
|
+
import { createElement } from 'react';
|
|
3
|
+
import { reroute } from 'reroute-js/elysia';
|
|
4
|
+
import App from './client/App';
|
|
5
|
+
|
|
6
|
+
const IS_PRODUCTION = Bun.env.NODE_ENV === 'production';
|
|
7
|
+
|
|
8
|
+
const app = new Elysia()
|
|
9
|
+
.use(
|
|
10
|
+
reroute({
|
|
11
|
+
app: createElement(App),
|
|
12
|
+
minify: IS_PRODUCTION,
|
|
13
|
+
}),
|
|
14
|
+
)
|
|
15
|
+
.get('/api/message', () => ({ message: 'Hello from server' }))
|
|
16
|
+
.listen(Number(Bun.env.PORT || '3000'));
|
|
17
|
+
|
|
18
|
+
console.log(
|
|
19
|
+
`🦊 Reroute is running at ${app.server?.hostname}:${app.server?.port}`,
|
|
20
|
+
);
|
|
@@ -0,0 +1,26 @@
|
|
|
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
|
+
"paths": {}
|
|
23
|
+
},
|
|
24
|
+
"include": ["packages/**/*.ts", "packages/**/*.tsx", "test/**/*.d.ts"],
|
|
25
|
+
"exclude": ["node_modules", "dist", "test"]
|
|
26
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{PROJECT_NAME}}",
|
|
3
|
+
"description": "A Reroute application",
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"start": "reroute gen && bun src/index.ts",
|
|
7
|
+
"dev": "reroute gen --watch & bun --watch src/index.ts",
|
|
8
|
+
"build": "reroute gen && bun build src/index.ts --target bun --compile --outfile ./dist/app"
|
|
9
|
+
},
|
|
10
|
+
"private": true,
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"reroute-js": "latest",
|
|
13
|
+
"elysia": "^1.4.12",
|
|
14
|
+
"react": "^19.2.0",
|
|
15
|
+
"react-dom": "^19.2.0",
|
|
16
|
+
"sharp": "^0.34.4"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@types/bun": "latest",
|
|
20
|
+
"@types/react": "^19.2.2",
|
|
21
|
+
"@types/react-dom": "^19.2.2",
|
|
22
|
+
"typescript": "^5"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { RerouteProvider } from 'reroute-js/react';
|
|
2
|
+
import { artifacts } from '../../.reroute';
|
|
3
|
+
|
|
4
|
+
interface AppProps {
|
|
5
|
+
pathname?: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export default function App({ pathname }: AppProps = {}) {
|
|
9
|
+
return <RerouteProvider from={{ pathname, ...artifacts }} />;
|
|
10
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
|
|
3
|
+
export default function Counter() {
|
|
4
|
+
const [count, setCount] = useState(0);
|
|
5
|
+
const increase = () => setCount((c) => c + 1);
|
|
6
|
+
|
|
7
|
+
return (
|
|
8
|
+
<section>
|
|
9
|
+
<h2>Current count: {count}</h2>
|
|
10
|
+
{/* biome-ignore lint/a11y/useButtonType: shut up */}
|
|
11
|
+
<button onClick={increase}>Increase</button>
|
|
12
|
+
</section>
|
|
13
|
+
);
|
|
14
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { Link, useContent } from 'reroute-js/react';
|
|
2
|
+
|
|
3
|
+
interface RecentPostsProps {
|
|
4
|
+
limit?: number;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function RecentPosts({ limit = 3 }: RecentPostsProps) {
|
|
8
|
+
const { items } = useContent({
|
|
9
|
+
collection: 'blog',
|
|
10
|
+
limit,
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const recentPosts = items;
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<div style={{ marginTop: '2rem' }}>
|
|
17
|
+
<h2>Recent Blog Posts</h2>
|
|
18
|
+
<div
|
|
19
|
+
style={{
|
|
20
|
+
marginTop: '1rem',
|
|
21
|
+
display: 'flex',
|
|
22
|
+
flexDirection: 'column',
|
|
23
|
+
gap: '1rem',
|
|
24
|
+
}}
|
|
25
|
+
>
|
|
26
|
+
{recentPosts.map((post) => (
|
|
27
|
+
<article
|
|
28
|
+
key={post.slug}
|
|
29
|
+
style={{
|
|
30
|
+
padding: '1rem',
|
|
31
|
+
border: '1px solid #e0e0e0',
|
|
32
|
+
borderRadius: '8px',
|
|
33
|
+
background: '#fff',
|
|
34
|
+
}}
|
|
35
|
+
>
|
|
36
|
+
<h3 style={{ margin: '0 0 0.5rem 0', fontSize: '1.25rem' }}>
|
|
37
|
+
<Link
|
|
38
|
+
to={post.href}
|
|
39
|
+
style={{ textDecoration: 'none', color: '#0066cc' }}
|
|
40
|
+
>
|
|
41
|
+
{String(post.meta?.title || post.name)}
|
|
42
|
+
</Link>
|
|
43
|
+
</h3>
|
|
44
|
+
{post.meta?.date && (
|
|
45
|
+
<time style={{ fontSize: '0.875rem', color: '#666' }}>
|
|
46
|
+
{String(post.meta.date)}
|
|
47
|
+
</time>
|
|
48
|
+
)}
|
|
49
|
+
{post.meta?.excerpt && (
|
|
50
|
+
<p
|
|
51
|
+
style={{
|
|
52
|
+
marginTop: '0.5rem',
|
|
53
|
+
color: '#333',
|
|
54
|
+
fontSize: '0.9rem',
|
|
55
|
+
}}
|
|
56
|
+
>
|
|
57
|
+
{String(post.meta.excerpt)}
|
|
58
|
+
</p>
|
|
59
|
+
)}
|
|
60
|
+
<Link
|
|
61
|
+
to={post.href}
|
|
62
|
+
style={{
|
|
63
|
+
display: 'inline-block',
|
|
64
|
+
marginTop: '0.5rem',
|
|
65
|
+
color: '#0066cc',
|
|
66
|
+
textDecoration: 'none',
|
|
67
|
+
fontSize: '0.9rem',
|
|
68
|
+
}}
|
|
69
|
+
>
|
|
70
|
+
Read more →
|
|
71
|
+
</Link>
|
|
72
|
+
</article>
|
|
73
|
+
))}
|
|
74
|
+
</div>
|
|
75
|
+
<div style={{ marginTop: '1rem' }}>
|
|
76
|
+
<Link
|
|
77
|
+
to='/blog'
|
|
78
|
+
style={{
|
|
79
|
+
color: '#0066cc',
|
|
80
|
+
textDecoration: 'none',
|
|
81
|
+
}}
|
|
82
|
+
>
|
|
83
|
+
View all posts →
|
|
84
|
+
</Link>
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export default RecentPosts;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<title>{{PROJECT_NAME}}</title>
|
|
6
|
+
|
|
7
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<div id="root"></div>
|
|
11
|
+
<script type="module" src="./index.tsx"></script>
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const meta = {
|
|
2
|
+
title: '404',
|
|
3
|
+
description: 'Page not found',
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
function NotFound() {
|
|
7
|
+
return (
|
|
8
|
+
<div style={{ padding: '2rem', maxWidth: '800px', margin: '0 auto' }}>
|
|
9
|
+
<h1>404</h1>
|
|
10
|
+
<p>The page you are looking for does not exist.</p>
|
|
11
|
+
<nav style={{ marginTop: '2rem' }}>
|
|
12
|
+
<a href='/' style={{ marginRight: '1rem' }}>
|
|
13
|
+
← Back to Home
|
|
14
|
+
</a>
|
|
15
|
+
</nav>
|
|
16
|
+
</div>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default NotFound;
|
|
21
|
+
export { meta };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import RecentPosts from '../components/RecentPosts';
|
|
2
|
+
|
|
3
|
+
const meta = {
|
|
4
|
+
title: 'About Us',
|
|
5
|
+
description:
|
|
6
|
+
'Learn more about our application built with custom file-based routing!',
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
function About() {
|
|
10
|
+
return (
|
|
11
|
+
<div style={{ padding: '2rem', maxWidth: '800px', margin: '0 auto' }}>
|
|
12
|
+
<h1>About Us</h1>
|
|
13
|
+
<p>Welcome to our application built with custom file-based routing!</p>
|
|
14
|
+
<p>
|
|
15
|
+
This page demonstrates a simple static route that maps from{' '}
|
|
16
|
+
<code>routes/about.tsx</code> to <code>/about</code>.
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
<RecentPosts limit={1} />
|
|
20
|
+
|
|
21
|
+
<nav style={{ marginTop: '2rem' }}>
|
|
22
|
+
<a href='/' style={{ marginRight: '1rem' }}>
|
|
23
|
+
← Back to Home
|
|
24
|
+
</a>
|
|
25
|
+
</nav>
|
|
26
|
+
</div>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export default About;
|
|
31
|
+
export { meta };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const meta = {
|
|
2
|
+
title: '404',
|
|
3
|
+
description: 'Page not found',
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
function NotFound() {
|
|
7
|
+
return (
|
|
8
|
+
<div style={{ padding: '2rem', maxWidth: '800px', margin: '0 auto' }}>
|
|
9
|
+
<h1>404</h1>
|
|
10
|
+
<p>The blog content you are looking for does not exist.</p>
|
|
11
|
+
<nav style={{ marginTop: '2rem' }}>
|
|
12
|
+
<a href='/' style={{ marginRight: '1rem' }}>
|
|
13
|
+
← Back to Home
|
|
14
|
+
</a>
|
|
15
|
+
</nav>
|
|
16
|
+
</div>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default NotFound;
|
|
21
|
+
export { meta };
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { Link, Outlet } from 'reroute-js/react';
|
|
2
|
+
|
|
3
|
+
export default function BlogLayout() {
|
|
4
|
+
return (
|
|
5
|
+
<div style={{ minHeight: '100vh', background: '#f9f9f9' }}>
|
|
6
|
+
{/* Blog Header */}
|
|
7
|
+
<header
|
|
8
|
+
style={{
|
|
9
|
+
background: '#fff',
|
|
10
|
+
borderBottom: '1px solid #e0e0e0',
|
|
11
|
+
padding: '1rem 2rem',
|
|
12
|
+
}}
|
|
13
|
+
>
|
|
14
|
+
<div style={{ maxWidth: '800px', margin: '0 auto' }}>
|
|
15
|
+
<nav
|
|
16
|
+
style={{
|
|
17
|
+
display: 'flex',
|
|
18
|
+
alignItems: 'center',
|
|
19
|
+
justifyContent: 'space-between',
|
|
20
|
+
}}
|
|
21
|
+
>
|
|
22
|
+
<Link
|
|
23
|
+
to='/blog'
|
|
24
|
+
style={{
|
|
25
|
+
fontSize: '1.5rem',
|
|
26
|
+
fontWeight: 'bold',
|
|
27
|
+
textDecoration: 'none',
|
|
28
|
+
color: '#333',
|
|
29
|
+
}}
|
|
30
|
+
>
|
|
31
|
+
📝 Blog
|
|
32
|
+
</Link>
|
|
33
|
+
<div
|
|
34
|
+
style={{ display: 'flex', gap: '1.5rem', alignItems: 'center' }}
|
|
35
|
+
>
|
|
36
|
+
<Link
|
|
37
|
+
to='/'
|
|
38
|
+
style={{
|
|
39
|
+
textDecoration: 'none',
|
|
40
|
+
color: '#666',
|
|
41
|
+
fontSize: '0.875rem',
|
|
42
|
+
}}
|
|
43
|
+
>
|
|
44
|
+
Home
|
|
45
|
+
</Link>
|
|
46
|
+
<Link
|
|
47
|
+
to='/about'
|
|
48
|
+
style={{
|
|
49
|
+
textDecoration: 'none',
|
|
50
|
+
color: '#666',
|
|
51
|
+
fontSize: '0.875rem',
|
|
52
|
+
}}
|
|
53
|
+
>
|
|
54
|
+
About
|
|
55
|
+
</Link>
|
|
56
|
+
</div>
|
|
57
|
+
</nav>
|
|
58
|
+
</div>
|
|
59
|
+
</header>
|
|
60
|
+
|
|
61
|
+
{/* Blog Content */}
|
|
62
|
+
<main>
|
|
63
|
+
<div style={{ maxWidth: '800px', margin: '0 auto' }}>
|
|
64
|
+
<Outlet />
|
|
65
|
+
</div>
|
|
66
|
+
</main>
|
|
67
|
+
|
|
68
|
+
{/* Blog Footer */}
|
|
69
|
+
<footer
|
|
70
|
+
style={{
|
|
71
|
+
marginTop: '4rem',
|
|
72
|
+
padding: '2rem',
|
|
73
|
+
textAlign: 'center',
|
|
74
|
+
color: '#666',
|
|
75
|
+
fontSize: '0.875rem',
|
|
76
|
+
borderTop: '1px solid #e0e0e0',
|
|
77
|
+
background: '#fff',
|
|
78
|
+
}}
|
|
79
|
+
>
|
|
80
|
+
<p>© 2024 Reroute Blog. Built with Bun, Elysia, and React.</p>
|
|
81
|
+
</footer>
|
|
82
|
+
</div>
|
|
83
|
+
);
|
|
84
|
+
}
|
|
@@ -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: 'Hello World',
|
|
5
|
+
description: 'This is the first post using Reroute 🎉',
|
|
6
|
+
excerpt: 'This is a great 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>Hello World</h1>
|
|
21
|
+
<p>Welcome to my blog!!</p>
|
|
22
|
+
</div>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export { meta, ssr };
|
|
27
|
+
export default BlogPost;
|