setup frontend #5

Merged
GW_MC merged 6 commits from feature/frontend-setup into master 2025-12-02 20:50:08 +08:00
13 changed files with 4927 additions and 0 deletions
Showing only changes of commit 27173c01da - Show all commits

View File

@@ -0,0 +1,4 @@
.react-router
build
node_modules
README.md

7
apps/frontend/.gitignore vendored Normal file
View File

@@ -0,0 +1,7 @@
.DS_Store
.env
/node_modules/
# React Router
/.react-router/
/build/

15
apps/frontend/app/app.css Normal file
View File

@@ -0,0 +1,15 @@
@import "tailwindcss";
@theme {
--font-sans: "Inter", ui-sans-serif, system-ui, sans-serif,
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
}
html,
body {
@apply bg-white dark:bg-gray-950;
@media (prefers-color-scheme: dark) {
color-scheme: dark;
}
}

View File

@@ -0,0 +1,59 @@
import { isRouteErrorResponse, Links, Meta, Outlet, Scripts, ScrollRestoration } from 'react-router';
import type { Route } from './+types/root';
import './app.css';
import { Theme } from '@radix-ui/themes';
export const links: Route.LinksFunction = () => [];
export function Layout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<Meta />
<Links />
</head>
<body>
{children}
<ScrollRestoration />
<Scripts />
</body>
</html>
);
}
export default function App() {
return (
<Theme>
<Outlet />
</Theme>
);
}
export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
let message = 'Oops!';
let details = 'An unexpected error occurred.';
let stack: string | undefined;
if (isRouteErrorResponse(error)) {
message = error.status === 404 ? '404' : 'Error';
details = error.status === 404 ? 'The requested page could not be found.' : error.statusText || details;
} else if (import.meta.env.DEV && error && error instanceof Error) {
details = error.message;
stack = error.stack;
}
return (
<main className="pt-16 p-4 container mx-auto">
<h1>{message}</h1>
<p>{details}</p>
{stack && (
<pre className="w-full p-4 overflow-x-auto">
<code>{stack}</code>
</pre>
)}
</main>
);
}

View File

@@ -0,0 +1,3 @@
import { type RouteConfig, index } from "@react-router/dev/routes";
export default [index("routes/home.tsx")] satisfies RouteConfig;

View File

@@ -0,0 +1,10 @@
import { Text } from '@radix-ui/themes';
import type { Route } from './+types/home';
export function meta({}: Route.MetaArgs) {
return [{ title: 'YANPM' }, { name: 'description', content: 'Welcome to Yet Another Nginx Proxy Manager!' }];
}
export default function Home() {
return <Text>Welcome to Yet Another Nginx Proxy Manager!</Text>;
}

View File

@@ -0,0 +1,33 @@
{
"name": "frontend",
"private": true,
"type": "module",
"scripts": {
"build": "react-router build",
"dev": "react-router dev",
"start": "react-router-serve ./build/server/index.js",
"typecheck": "react-router typegen && tsc"
},
"dependencies": {
"@radix-ui/themes": "^3.2.1",
"@react-router/node": "^7.9.2",
"@react-router/serve": "^7.9.2",
"isbot": "^5.1.31",
"radix-ui": "^1.4.3",
"react": "^19.1.1",
"react-dom": "^19.1.1",
"react-router": "^7.9.2"
},
"devDependencies": {
"@react-router/dev": "^7.9.2",
"@tailwindcss/vite": "^4.1.13",
"@types/node": "^22",
"@types/react": "^19.1.13",
"@types/react-dom": "^19.1.9",
"dotenv": "^17.2.3",
"tailwindcss": "^4.1.13",
"typescript": "^5.9.2",
"vite": "^7.1.7",
"vite-tsconfig-paths": "^5.1.4"
}
}

4748
apps/frontend/pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,5 @@
import type { Config } from '@react-router/dev/config';
export default {
ssr: false,
} satisfies Config;

View File

@@ -0,0 +1,22 @@
{
"include": ["**/*", "**/.server/**/*", "**/.client/**/*", ".react-router/types/**/*"],
"compilerOptions": {
"lib": ["DOM", "DOM.Iterable", "ES2022"],
"types": ["node", "vite/client"],
"target": "ES2022",
"module": "ES2022",
"moduleResolution": "bundler",
"jsx": "react-jsx",
"rootDirs": [".", "./.react-router/types"],
"baseUrl": ".",
"paths": {
"~/*": ["./app/*"]
},
"esModuleInterop": true,
"verbatimModuleSyntax": true,
"noEmit": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"strict": true
}
}

View File

@@ -0,0 +1,9 @@
import { reactRouter } from '@react-router/dev/vite';
import tailwindcss from '@tailwindcss/vite';
import { defineConfig } from 'vite';
import tsconfigPaths from 'vite-tsconfig-paths';
export default defineConfig({
plugins: [tailwindcss(), reactRouter(), tsconfigPaths()],
appType: 'spa',
});

View File

@@ -40,3 +40,15 @@ migrate *args:
generate-entity:
# delegate to cli
just cli db:migrate_and_generate --output-path ../../public/database/src/generated/entities
build-frontend:
# build frontend assets
cd apps/frontend && \
pnpm build
build-backend:
# build backend server
cd apps/api && \
cargo build --release
build: build-frontend build-backend