To establish a robust foundation, Solid generator produces a suite of core files.
This infrastructure handles critical tasks like mapping your file structure to application routes, enabling type-safe navigation, and ensuring efficient code-splitting through lazy loading.
π¨ The App Component β
The generator creates a minimal App.tsx as your root application component.
import type { ParentComponent } from "solid-js";
const App: ParentComponent = (props) => {
return props.children;
};
export default App;This simple component serves as your application shell.
You can customize this component to add global layouts, error boundaries, or other application-wide concerns.
π£οΈ Router Configuration β
Your router.tsx file integrates SolidJS Router with routes generated by KosmoJS through the routerFactory function.
The routerFactory accepts a callback receiving:
App- Your application's root componentroutes- Auto-generated route definitions
Your callback returns two router configurations:
clientRouter()- Browser-based routing for client-side navigationserverRouter({ url })- Server-side routing for SSR with URL context
import { Router } from "@solidjs/router";
import { routerFactory } from "_/front/router";
import { baseurl } from "@/front/config";
export default routerFactory((App, routes) => {
return {
clientRouter() {
return (
<Router root={App} base={baseurl}>
{routes}
</Router>
);
},
serverRouter({ url }) {
return (
<Router root={App} base={baseurl} url={url.pathname}>
{routes}
</Router>
);
},
}
});Key differences:
clientRouter()renders a<Router>without theurlprop - SolidJS Router reads the browser's current location automaticallyserverRouter({ url })includes theurlprop set tourl.pathname- this tells SolidJS Router which route to render during server-side rendering
Both configurations share the same baseurl from your source folder settings, ensuring consistent path handling
The routes are injected as children, wrapped by your App component via the root prop, establishing the component hierarchy.
π― The Entry Point β
Your application begins at entry/client.tsx, where the renderFactory handles DOM mounting and SSR hydration.
The renderFactory orchestrates two rendering modes through a callback that provides:
clientRender()- Mounts your application to the DOM from scratchserverRender()- Hydrates pre-rendered server HTML for interactivity
import { hydrate, render } from "solid-js/web";
import { renderFactory, createRoutes } from "_/front/entry/client";
import App from "@/front/App";
import createRouter from "@/front/router";
const root = document.getElementById("app");
if (root) {
const routes = createRoutes({ withPreload: true });
renderFactory(async () => {
const router = await createRouter(App, routes);
return {
clientRender() {
render(() => router, root);
},
serverRender() {
hydrate(() => router, root)
},
}
});
} else {
console.error("Root element not found!");
}Automatic mode detection:
When building for SSR, the generator sets an ssrMode flag that gets bundled into your client code. This flag enables precise runtime detection - the client bundle knows exactly whether it's running in SSR mode. When your page loads, renderFactory uses this flag to determine the rendering mode:
- If
ssrModeis true (SSR build),serverRender()activates to hydrate the server-rendered markup - If
ssrModeis false (client-only build),clientRender()executes a fresh mount
You provide both functions; renderFactory selects the appropriate one based on the build-time flag.
Your index.html references this entry during source folder initialization:
<script type="module" src="./entry/client.tsx"></script>Vite uses index.html as its starting point, following the module import to entry/client.tsx and constructing the complete application dependency graph from that reference.