diff --git a/crates/tuono/src/lib.rs b/crates/tuono/src/lib.rs
index 7f6756a9..09dc0622 100644
--- a/crates/tuono/src/lib.rs
+++ b/crates/tuono/src/lib.rs
@@ -1,6 +1,8 @@
use clap::{Parser, Subcommand};
use std::process::Command;
-mod axum_source_builder;
+
+mod source_builder;
+use source_builder::{bundle_axum_source, create_client_entry_files};
mod watch;
#[derive(Subcommand, Debug)]
@@ -24,11 +26,14 @@ pub fn cli() {
let args = Args::parse();
match args.action.unwrap() {
- Actions::Dev => watch::watch().unwrap(),
+ Actions::Dev => {
+ bundle_axum_source();
+ create_client_entry_files().unwrap();
+ watch::watch().unwrap();
+ }
Actions::Build => {
- axum_source_builder::bundle_axum_source();
-
- println!("Build JS source");
+ bundle_axum_source();
+ create_client_entry_files().unwrap();
let mut vite_build = Command::new("./node_modules/.bin/tuono-build-prod");
let _ = &vite_build.output().unwrap();
}
diff --git a/crates/tuono/src/axum_source_builder.rs b/crates/tuono/src/source_builder.rs
similarity index 82%
rename from crates/tuono/src/axum_source_builder.rs
rename to crates/tuono/src/source_builder.rs
index e2821ba3..c13d50ca 100644
--- a/crates/tuono/src/axum_source_builder.rs
+++ b/crates/tuono/src/source_builder.rs
@@ -1,11 +1,30 @@
use glob::glob;
use std::collections::HashMap;
use std::fs;
+use std::io;
use std::io::prelude::*;
use std::path::Path;
use std::path::PathBuf;
const ROOT_FOLDER: &'static str = "src/routes";
+const DEV_FOLDER: &'static str = ".tuono";
+const SERVER_ENTRY_DATA: &'static str = "// File automatically generated by tuono
+
+import { routeTree } from './routeTree.gen'
+import { serverSideRendering } from 'tuono/ssr'
+
+export const renderFn = serverSideRendering(routeTree)
+";
+
+const CLIENT_ENTRY_DATA: &'static str = "// File automatically generated by tuono
+
+import { hydrate } from 'tuono/hydration'
+
+// Import the generated route tree
+import { routeTree } from './routeTree.gen'
+
+hydrate(routeTree)
+";
enum Mode {
Prod,
@@ -159,3 +178,14 @@ pub fn bundle_axum_source() {
create_main_file(&base_path, &bundled_file);
}
+
+pub fn create_client_entry_files() -> io::Result<()> {
+ let dev_folder = Path::new(DEV_FOLDER);
+ let mut server_entry = fs::File::create(&dev_folder.join("server-main.tsx"))?;
+ let mut client_entry = fs::File::create(&dev_folder.join("client-main.tsx"))?;
+
+ server_entry.write(SERVER_ENTRY_DATA.as_bytes())?;
+ client_entry.write(CLIENT_ENTRY_DATA.as_bytes())?;
+
+ Ok(())
+}
diff --git a/crates/tuono/src/watch.rs b/crates/tuono/src/watch.rs
index 100f32f2..7206ca72 100644
--- a/crates/tuono/src/watch.rs
+++ b/crates/tuono/src/watch.rs
@@ -6,7 +6,7 @@ use watchexec::Watchexec;
use watchexec_signals::Signal;
use watchexec_supervisor::job::start_job;
-use crate::axum_source_builder::bundle_axum_source;
+use crate::source_builder::bundle_axum_source;
// What is the development pipeline?
//
@@ -22,7 +22,6 @@ use crate::axum_source_builder::bundle_axum_source;
#[tokio::main]
pub async fn watch() -> Result<()> {
- bundle_axum_source();
let (watch_client, _) = start_job(Arc::new(Command {
program: Program::Exec {
prog: "node_modules/.bin/tuono-dev-watch".into(),
diff --git a/packages/tuono/package.json b/packages/tuono/package.json
index 4a077563..33ceb81a 100644
--- a/packages/tuono/package.json
+++ b/packages/tuono/package.json
@@ -25,6 +25,26 @@
"default": "./dist/cjs/build/index.js"
}
},
+ "./ssr": {
+ "import": {
+ "types": "./dist/esm/ssr/index.d.ts",
+ "default": "./dist/esm/ssr/index.js"
+ },
+ "require": {
+ "types": "./dist/cjs/ssr/index.d.ts",
+ "default": "./dist/cjs/ssr/index.js"
+ }
+ },
+ "./hydration": {
+ "import": {
+ "types": "./dist/esm/hydration/index.d.ts",
+ "default": "./dist/esm/hydration/index.js"
+ },
+ "require": {
+ "types": "./dist/cjs/ssr/index.d.ts",
+ "default": "./dist/cjs/ssr/index.js"
+ }
+ },
".": {
"import": {
"types": "./dist/esm/index.d.ts",
@@ -65,6 +85,7 @@
"@types/babel__core": "^7.20.5",
"@types/node": "^20.12.7",
"@vitejs/plugin-react-swc": "^3.7.0",
+ "fast-text-encoding": "^1.0.6",
"prettier": "^3.2.4",
"vite": "^5.2.11",
"zustand": "4.4.7"
diff --git a/packages/tuono/src/hydration/index.tsx b/packages/tuono/src/hydration/index.tsx
new file mode 100644
index 00000000..d6737fcd
--- /dev/null
+++ b/packages/tuono/src/hydration/index.tsx
@@ -0,0 +1,19 @@
+import 'vite/modulepreload-polyfill'
+import React from 'react'
+import ReactDOM from 'react-dom/client'
+import { RouterProvider, createRouter } from '../router'
+
+export function hydrate(routeTree: any) {
+ // Create a new router instance
+ const router = createRouter({ routeTree })
+
+ // Render the app
+ const rootElement = document.getElementById('__tuono')!
+
+ ReactDOM.hydrateRoot(
+ rootElement,
+