File Structure
After running npm run build, Vite emits a production-ready static bundle to the dist/ folder. The core entry points of the source are shown below.
index.html (root entry – replaces app/layout.tsx)
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/assets/imgs/template/logo/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Orisa - Multi-purpose React Template</title>
<!-- Google Fonts: DM Sans -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,100..1000;1,9..40,100..1000&display=swap" rel="stylesheet" />
<!-- Template CSS -->
<link rel="stylesheet" href="/assets/css/vendors/bootstrap.min.css" />
<link rel="stylesheet" href="/assets/css/vendors/swiper-bundle.min.css" />
<link rel="stylesheet" href="/assets/css/vendors/nice-select.css" />
<link rel="stylesheet" href="/assets/css/vendors/magnific-popup.css" />
<link rel="stylesheet" href="/assets/css/vendors/odometer.css" />
<link rel="stylesheet" href="/assets/css/vendors/spacing.css" />
<link rel="stylesheet" href="/assets/css/vendors/font-awesome-pro.css" />
<link rel="stylesheet" href="/assets/css/main.css" />
<style>
:root { --at-ff-body: "DM Sans", sans-serif; }
body { font-family: var(--at-ff-body); }
</style>
<!-- Theme init: set data-theme before first paint -->
<script src="/scripts/theme-init.js"></script>
</head>
<body>
<div class="px-blur-bottom"></div>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
src/main.tsx (app bootstrap)
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { RouterProvider } from "react-router-dom";
import { router } from "@/router";
import PageLoader from "@/pages/PageLoader";
function App() {
return (
<>
<PageLoader />
<RouterProvider router={router} />
</>
);
}
createRoot(document.getElementById("root")!).render(
<StrictMode>
<App />
</StrictMode>
);
src/router.tsx (route table – replaces App Router)
import { createBrowserRouter } from "react-router-dom";
import NotFound from "@/pages/NotFound";
import Home from "@/pages/Home";
import About1 from "@/pages/About1";
import Index2 from "@/pages/Index2";
// ...one import per route
export const router = createBrowserRouter([
{ path: "/", element: <Home /> },
{ path: "/about-1", element: <About1 /> },
{ path: "/index-2", element: <Index2 /> },
// ...35+ routes total
{ path: "*", element: <NotFound /> },
]);
src/components/layout/Layout.tsx
import { MobileMenuCloneProvider } from "@/components/layout/MobileMenuCloneContext";
import BackToTop from "@/components/elements/BackToTopServer";
import ParallaxSceneEffect from "@/components/effects/ParallaxSceneEffect";
import Footer1 from "@/components/layout/footer/Footer1";
import Footer2 from "@/components/layout/footer/Footer2";
import Footer3 from "@/components/layout/footer/Footer3";
import Footer4 from "@/components/layout/footer/Footer4";
import Footer5 from "@/components/layout/footer/Footer5";
import Header1 from "@/components/layout/header/Header1";
import Header2 from "@/components/layout/header/Header2";
import Header3 from "@/components/layout/header/Header3";
import Header4 from "@/components/layout/header/Header4";
import Header5 from "@/components/layout/header/Header5";
import ServerEffects from "@/components/layout/ServerEffects";
const HEADER_COMPONENTS = { 1: Header1, 2: Header2, 3: Header3, 4: Header4, 5: Header5 } as const;
const FOOTER_COMPONENTS = { 1: Footer1, 2: Footer2, 3: Footer3, 4: Footer4, 5: Footer5 } as const;
function Header({ style }: { style?: number }) {
if (!style) return <Header1 />;
const C = HEADER_COMPONENTS[style as keyof typeof HEADER_COMPONENTS];
return C ? <C /> : <Header1 />;
}
function Footer({ style }: { style?: number }) {
if (!style) return <Footer1 />;
const C = FOOTER_COMPONENTS[style as keyof typeof FOOTER_COMPONENTS];
return C ? <C /> : <Footer1 />;
}
interface LayoutProps {
children?: React.ReactNode;
headerStyle?: number;
footerStyle?: number;
}
export default function Layout({ children, headerStyle, footerStyle }: LayoutProps) {
return (
<MobileMenuCloneProvider>
<ServerEffects />
<div id="top" />
<Header style={headerStyle} />
<div id="smooth-wrapper">
<div id="smooth-content" className="z-index-3">
<main className="bg-neutral-0">{children}</main>
{footerStyle !== 2 && <Footer style={footerStyle} />}
</div>
{footerStyle === 2 && <Footer style={footerStyle} />}
</div>
<ParallaxSceneEffect />
<BackToTop />
</MobileMenuCloneProvider>
);
}
Next.js → React compatibility shims
Three tiny wrappers let every page/section from the Next.js source keep the same JSX without a single attribute change. Only the import paths are rewritten.
src/components/common/Image.tsx— drop-in replacement fornext/image, renders a plain<img>.src/components/common/Link.tsx— drop-in replacement fornext/link, wraps React Router'sLinkand falls back to<a>for external /mailto:/#hrefs.src/util/dynamic.tsx— drop-in replacement fornext/dynamic, powered byReact.lazy+Suspense.
Dependencies
{
"name": "orisa-react",
"private": true,
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"preview": "vite preview",
"lint": "eslint ."
},
"dependencies": {
"bootstrap": "^5.3.3",
"gsap": "^3.12.7",
"isotope-layout": "^3.0.6",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-fast-marquee": "^1.6.5",
"react-router-dom": "^7.0.0",
"split-text": "^1.0.0",
"swiper": "^11.2.5",
"wowjs": "^1.1.3"
},
"devDependencies": {
"@types/bootstrap": "^5.2.10",
"@types/isotope-layout": "^3.0.14",
"@types/node": "^22.10.0",
"@types/react": "^19.0.0",
"@types/react-dom": "^19.0.0",
"@vitejs/plugin-react": "^4.3.4",
"typescript": "^5.7.0",
"vite": "^6.0.0"
}
}