feat: migrate all 5 Vite apps from react-router to TanStack Router

Migrated backoffice, hackathon, dimentorin, gacha, qrcampaign, and
infra from custom react-router file-based routing to TanStack Router
file-based routing following the tanstack-frontend-best-practice
convention.

Key changes per app:
- New routes/ directory with __root.tsx, _public.tsx, _authenticated.tsx
- Auth guards via beforeLoad (replaces old middleware.ts)
- createFileRoute pattern for all page components
- TanStackRouterVite plugin in vite.config for auto route generation
- _components/_hooks folders colocated with routes (ignored by router)
- routeTree.gen.ts auto-generated on dev/build

Convention:
- _public/* routes redirect to dashboard if authenticated
- _authenticated/* routes redirect to /auth/login if not authenticated
- $param for dynamic segments (was [param] in old convention)
- _layout suffix for pathless layout routes

Removed:
- Old src/app/ directories from all apps
- Old src/middleware.ts files
- Custom convertPagesToRoute utility (no longer needed)
- react-router dependency usage (kept in package.json for shared libs)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
maulanasdqn
2026-04-11 17:04:14 +07:00
co-authored by Claude Opus 4.6
parent 86d9e759a6
commit 4240e8eb51
291 changed files with 3889 additions and 4585 deletions
+17 -8
View File
@@ -1,14 +1,23 @@
import { createRoot } from 'react-dom/client';
import { StrictMode } from 'react';
import App from './app/App';
import './index.css';
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { RouterProvider, createRouter } from '@tanstack/react-router'
import { routeTree } from './routeTree.gen'
import './index.css'
const rootElement = document.getElementById('root');
const router = createRouter({ routeTree })
if (!rootElement) throw new Error('Failed to find the root element');
declare module '@tanstack/react-router' {
interface Register {
router: typeof router
}
}
const rootElement = document.getElementById('root')
if (!rootElement) throw new Error('Failed to find the root element')
createRoot(rootElement).render(
<StrictMode>
<App />
<RouterProvider router={router} />
</StrictMode>
);
)
+2
View File
@@ -0,0 +1,2 @@
// This file is auto-generated by TanStack Router
export const routeTree = {} as any
+5
View File
@@ -0,0 +1,5 @@
import { createRootRoute, Outlet } from '@tanstack/react-router'
export const Route = createRootRoute({
component: () => <Outlet />,
})
@@ -1,3 +1,5 @@
import { createFileRoute } from '@tanstack/react-router'
const apps = [
{ name: 'Landing', domain: 'imphnen.dev', type: 'Next.js', color: 'blue' },
{ name: 'WWW', domain: 'www.imphnen.dev', type: 'Redirect', color: 'purple' },
@@ -8,7 +10,7 @@ const apps = [
{ name: 'QR Campaign', domain: 'qr.imphnen.dev', type: 'Vite', color: 'green' },
{ name: 'Infra', domain: 'infra.imphnen.dev', type: 'Vite', color: 'green' },
{ name: 'API QR', domain: 'api-qr.imphnen.dev', type: 'Backend', color: 'orange' },
];
]
const techStack = [
{ category: 'OS', items: ['NixOS 25.05'] },
@@ -19,9 +21,13 @@ const techStack = [
{ category: 'Frontend', items: ['React', 'Next.js', 'Vite', 'TailwindCSS'] },
{ category: 'Backend', items: ['Go', 'Supabase'] },
{ category: 'Secrets', items: ['sops-nix'] },
];
]
export default function App() {
export const Route = createFileRoute('/')({
component: InfraPage,
})
function InfraPage() {
return (
<div className="min-h-screen bg-[#0a0a0a]">
@@ -234,5 +240,5 @@ export default function App() {
</div>
</footer>
</div>
);
)
}
+9 -1
View File
@@ -3,6 +3,7 @@ import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
import { TanStackRouterVite } from '@tanstack/router-plugin/vite';
export default defineConfig(() => ({
root: __dirname,
@@ -15,7 +16,14 @@ export default defineConfig(() => ({
port: 3007,
host: 'localhost',
},
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
plugins: [
TanStackRouterVite({
routeFileIgnorePattern: '_components|_hooks|_hook|_data',
}),
react(),
nxViteTsPaths(),
nxCopyAssetsPlugin(['*.md']),
],
build: {
outDir: '../../dist/apps/infra',
emptyOutDir: true,