chore(routes): LAC-121 - All routes are navagable

This commit is contained in:
icld 2025-03-04 16:52:32 -08:00
parent 7809fa765e
commit dc439c0076
63 changed files with 1917 additions and 120 deletions

View File

@ -1,65 +0,0 @@
{
"name": "Laconic Core Development",
"image": "mcr.microsoft.com/devcontainers/javascript-node:0-18",
// Add environment variables
"containerEnv": {
"NODE_ENV": "development"
},
// Mount your SSH keys for git authentication
"mounts": [
"source=${localEnv:HOME}/.ssh,target=/home/node/.ssh,type=bind,readonly"
],
"customizations": {
"vscode": {
"extensions": [
"biomejs.biome",
"ms-vscode.vscode-typescript-next",
"ms-azuretools.vscode-docker",
"dbaeumer.vscode-eslint",
"christian-kohler.path-intellisense",
"github.vscode-pull-request-github",
"streetsidesoftware.code-spell-checker",
"eamodio.gitlens"
],
"settings": {
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": "explicit",
"source.fixAll": "explicit",
"source.addMissingImports.ts": "explicit",
"source.fixAll.ts": "explicit",
"source.removeUnusedImports": "explicit"
},
// Additional helpful settings
"editor.bracketPairColorization.enabled": true,
"editor.guides.bracketPairs": true,
"terminal.integrated.defaultProfile.linux": "bash",
"javascript.updateImportsOnFileMove.enabled": "always",
"typescript.updateImportsOnFileMove.enabled": "always",
"files.exclude": {
"**/.git": true,
"**/node_modules": true,
"**/dist": true
}
}
}
},
// Forward common development ports
"forwardPorts": [3000, 4000, 5000, 8000],
// Set up git configuration
"postCreateCommand": "pnpm install && git config --global pull.rebase true",
"remoteUser": "node",
// Features to install in the container
"features": {
"ghcr.io/devcontainers/features/github-cli:1": {},
"ghcr.io/devcontainers/features/git:1": {}
}
}

View File

@ -1,13 +0,0 @@
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'],
rules: {
// Add rules that can be auto-fixed
'@typescript-eslint/no-unused-vars': 'error',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/no-non-null-assertion': 'warn'
}
}

View File

@ -4,12 +4,12 @@
"typescript.enablePromptUseWorkspaceTsdk": true,
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll": true,
"source.organizeImports": true
"source.fixAll": "explicit",
"source.organizeImports": "explicit"
},
"editor.defaultFormatter": "biomejs.biome",
"[typescript]": {
"editor.defaultFormatter": "biomejs.biome"
"editor.defaultFormatter": "vscode.typescript-language-features"
},
"[typescriptreact]": {
"editor.defaultFormatter": "biomejs.biome"

7
apps/deploy-fe/.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
node_modules
.next/
.turbo/
.env
.env.local
.env.development.local
.env.test.local

View File

@ -0,0 +1,20 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "tailwind.config.ts",
"css": "../../../services/ui/src/styles/globals.css",
"baseColor": "zinc",
"cssVariables": true
},
"iconLibrary": "lucide",
"aliases": {
"components": "@/components",
"hooks": "@/hooks",
"lib": "@/lib",
"utils": "@workspace/ui/lib/utils",
"ui": "@workspace/ui/components"
}
}

View File

@ -0,0 +1,6 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
transpilePackages: ['@workspace/ui']
}
export default nextConfig

View File

@ -0,0 +1,75 @@
{
"name": "deploy-fe",
"version": "0.0.1",
"type": "module",
"private": true,
"scripts": {
"dev": "next dev --turbopack",
"build": "next build",
"start": "next start",
"lint": "biome check .",
"lint:fix": "biome check --write .",
"format": "biome format .",
"format:fix": "biome format --write .",
"check-types": "tsc --noEmit",
"fix-types": "tsc --noEmit --pretty --incremental"
},
"dependencies": {
"@biomejs/biome": "^1.9.4",
"@biomejs/monorepo": "github:biomejs/biome",
"@hookform/resolvers": "^4.1.2",
"@radix-ui/react-accordion": "^1.2.3",
"@radix-ui/react-alert-dialog": "^1.1.6",
"@radix-ui/react-aspect-ratio": "^1.1.2",
"@radix-ui/react-avatar": "^1.1.3",
"@radix-ui/react-checkbox": "^1.1.4",
"@radix-ui/react-collapsible": "^1.1.3",
"@radix-ui/react-context-menu": "^2.2.6",
"@radix-ui/react-dialog": "^1.1.6",
"@radix-ui/react-dropdown-menu": "^2.1.6",
"@radix-ui/react-hover-card": "^1.1.6",
"@radix-ui/react-label": "^2.1.2",
"@radix-ui/react-menubar": "^1.1.6",
"@radix-ui/react-navigation-menu": "^1.2.5",
"@radix-ui/react-popover": "^1.1.6",
"@radix-ui/react-progress": "^1.1.2",
"@radix-ui/react-radio-group": "^1.2.3",
"@radix-ui/react-scroll-area": "^1.2.3",
"@radix-ui/react-select": "^2.1.6",
"@radix-ui/react-separator": "^1.1.2",
"@radix-ui/react-slider": "^1.2.3",
"@radix-ui/react-slot": "^1.1.1",
"@radix-ui/react-switch": "^1.1.3",
"@radix-ui/react-tabs": "^1.1.3",
"@radix-ui/react-toggle": "^1.1.2",
"@radix-ui/react-toggle-group": "^1.1.2",
"@radix-ui/react-tooltip": "^1.1.8",
"@workspace/ui": "workspace:*",
"class-variance-authority": "^0.7.0",
"cmdk": "1.0.0",
"date-fns": "^4.1.0",
"embla-carousel-react": "^8.5.2",
"input-otp": "^1.4.2",
"lucide-react": "0.456.0",
"next": "^15.1.0",
"next-themes": "^0.4.4",
"react": "^19.0.0",
"react-day-picker": "8.10.1",
"react-dom": "^19.0.0",
"react-hook-form": "^7.54.2",
"react-resizable-panels": "^2.1.7",
"recharts": "^2.15.1",
"sonner": "^2.0.1",
"vaul": "^1.1.2",
"zod": "^3.23.8"
},
"devDependencies": {
"@types/node": "^20",
"@types/react": "18.3.0",
"@types/react-dom": "18.3.1",
"@workspace/typescript-config": "workspace:*",
"postcss": "^8",
"tailwindcss": "^4.0.9",
"typescript": "^5"
}
}

View File

@ -0,0 +1,6 @@
export default {
plugins: {
'@tailwindcss/postcss': {},
autoprefixer: {}
}
}

View File

@ -0,0 +1,18 @@
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: 'Buy Prepaid Service',
description: 'Buy prepaid service page description'
}
const Page = () => {
return (
<div>
<h1>
Hello from (web3-authenticated)/(dashboard)/(buy-prepaid-service)/bp
</h1>
</div>
)
}
export default Page

View File

@ -0,0 +1,12 @@
const Page = () => {
return (
<div>
<h1>
Hello from
(web3-authenticated)/(dashboard)/(projects)/pr/[provider]/[orgSlug]/(projects)/ps/(create)/cr/(configure)/cf
</h1>
</div>
)
}
export default Page

View File

@ -0,0 +1,12 @@
const Page = () => {
return (
<div>
<h1>
Hello from
(web3-authenticated)/(dashboard)/(projects)/pr/[provider]/[orgSlug]/(projects)/ps/(create)/cr/(deploy)/dp
</h1>
</div>
)
}
export default Page

View File

@ -0,0 +1,12 @@
const Page = () => {
return (
<div>
<h1>
Hello from
(web3-authenticated)/(dashboard)/(projects)/pr/[provider]/[orgSlug]/(projects)/ps/(create)/cr/(success)/sc/[id]
</h1>
</div>
)
}
export default Page

View File

@ -0,0 +1,12 @@
const Page = () => {
return (
<div>
<h1>
Hello from
(web3-authenticated)/(dashboard)/(projects)/pr/[provider]/[orgSlug]/(projects)/ps/(create)/cr/(template)/tm/(configure)/cf
</h1>
</div>
)
}
export default Page

View File

@ -0,0 +1,12 @@
const Page = () => {
return (
<div>
<h1>
Hello from
(web3-authenticated)/(dashboard)/(projects)/pr/[provider]/[orgSlug]/(projects)/ps/(create)/cr/(template)/tm/(deploy)/dp
</h1>
</div>
)
}
export default Page

View File

@ -0,0 +1,12 @@
const Page = () => {
return (
<div>
<h1>
Hello from
(web3-authenticated)/(dashboard)/(projects)/pr/[provider]/[orgSlug]/(projects)/ps/[id]/(deployments)/dep
</h1>
</div>
)
}
export default Page

View File

@ -0,0 +1,12 @@
const Page = () => {
return (
<div>
<h1>
Hello from
(web3-authenticated)/(dashboard)/(projects)/pr/[provider]/[orgSlug]/(projects)/ps/[id]/(integrations)/int
</h1>
</div>
)
}
export default Page

View File

@ -0,0 +1,12 @@
const Page = () => {
return (
<div>
<h1>
Hello from
(web3-authenticated)/(dashboard)/(projects)/pr/[provider]/[orgSlug]/(projects)/ps/[id]/(settings)/set/(collaborators)/col
</h1>
</div>
)
}
export default Page

View File

@ -0,0 +1,12 @@
const Page = () => {
return (
<div>
<h1>
Hello from
(web3-authenticated)/(dashboard)/(projects)/pr/[provider]/[orgSlug]/(projects)/ps/[id]/(settings)/set/(domains)/dom/(add)/cf
</h1>
</div>
)
}
export default Page

View File

@ -0,0 +1,12 @@
const Page = () => {
return (
<div>
<h1>
Hello from
(web3-authenticated)/(dashboard)/(projects)/pr/[provider]/[orgSlug]/(projects)/ps/[id]/(settings)/set/(domains)/dom/(add)/config/cf
</h1>
</div>
)
}
export default Page

View File

@ -0,0 +1,12 @@
const Page = () => {
return (
<div>
<h1>
Hello from
(web3-authenticated)/(dashboard)/(projects)/pr/[provider]/[orgSlug]/(projects)/ps/[id]/(settings)/set/(environment-variables)/env
</h1>
</div>
)
}
export default Page

View File

@ -0,0 +1,12 @@
const Page = () => {
return (
<div>
<h1>
Hello from
(web3-authenticated)/(dashboard)/(projects)/pr/[provider]/[orgSlug]/(projects)/ps/[id]/(settings)/set/(git)
</h1>
</div>
)
}
export default Page

View File

@ -0,0 +1,39 @@
// // Define your own params interface to avoid using Next.js internals
// interface PageParams {
// id: string
// provider: string
// orgSlug: string
// }
// // Generate dynamic metadata based on project ID
// export async function generateMetadata({
// params
// }: {
// params: PageParams
// }): Promise<Metadata> {
// const { id } = params
// try {
// const project = { name: 'Project Name' }
// // const project = await getProject(id)
// return {
// title: `Project: ${project.name}`,
// description: `Details for project ${project.name}`
// }
// } catch (error) {
// return {
// title: 'Project Details',
// description: 'Project information page'
// }
// }
// }
export default async function ProjectPage() {
const id = 'A fake project ID'
return (
<div>
<h1>Project ID: {id}</h1>
{/* Project content */}
</div>
)
}

View File

@ -0,0 +1,12 @@
const Page = () => {
return (
<div>
<h1>
Hello from
(web3-authenticated)/(dashboard)/(projects)/pr/[provider]/[orgSlug]/(settings)/set
</h1>
</div>
)
}
export default Page

View File

@ -0,0 +1,30 @@
'use client'
import { Button } from '@workspace/ui/components/button'
import { useEffect } from 'react'
export default function ClientError({
error,
reset
}: {
error: Error & { digest?: string }
reset: () => void
}) {
useEffect(() => {
// Log the error to an error reporting service
console.error(error)
}, [error])
return (
<div className="p-8 text-center">
<h2 className="text-xl font-bold mb-4">Something went wrong!</h2>
<p className="mb-4 text-gray-600">{error.message}</p>
<Button
onClick={reset}
className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
>
Try again
</Button>
</div>
)
}

View File

@ -0,0 +1,10 @@
export default function Loading() {
return (
<div className="flex items-center justify-center p-12">
<div className="animate-pulse text-center">
<div className="h-6 w-24 bg-gray-200 rounded mb-4 mx-auto" />
<div className="h-32 w-full max-w-md bg-gray-200 rounded" />
</div>
</div>
)
}

View File

@ -0,0 +1,16 @@
import type React from 'react'
interface LayoutProps {
children: React.ReactNode
}
const Layout: React.FC<LayoutProps> = ({ children }) => {
return (
<div>
<h2>Layout for (web3-authenticated)/(dashboard)</h2>
{children}
</div>
)
}
export default Layout

View File

@ -0,0 +1,16 @@
import type React from 'react'
interface LayoutProps {
children: React.ReactNode
}
const Layout: React.FC<LayoutProps> = ({ children }) => {
return (
<div>
<h2>Layout for (web3-authenticated)</h2>
{children}
</div>
)
}
export default Layout

View File

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -0,0 +1,43 @@
import { Providers } from '@/components/providers'
import '@workspace/ui/globals.css'
import type { Metadata } from 'next'
import { Geist, Geist_Mono } from 'next/font/google'
const fontSans = Geist({
subsets: ['latin'],
variable: '--font-sans'
})
const fontMono = Geist_Mono({
subsets: ['latin'],
variable: '--font-mono'
})
// Add root metadata with template pattern
export const metadata: Metadata = {
title: {
template: '%s | Qwrk Deploy',
default: 'Qwrk Deploy - Cloud Deployment Platform'
},
description: 'Deploy your applications with Qwrk',
metadataBase: new URL('https://deploy.qwrk.app'),
icons: {
icon: '/favicon.ico'
}
}
export default function RootLayout({
children
}: Readonly<{
children: React.ReactNode
}>) {
return (
<html lang="en" suppressHydrationWarning>
<body
className={`${fontSans.variable} ${fontMono.variable} font-sans antialiased `}
>
<Providers>{children}</Providers>
</body>
</html>
)
}

View File

@ -0,0 +1,16 @@
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: 'Login Page',
description: 'Login page description'
}
const Page = () => {
return (
<div>
<h1>Hello from login</h1>
</div>
)
}
export default Page

View File

@ -0,0 +1,22 @@
import type { Metadata } from 'next'
import Link from 'next/link'
export const metadata: Metadata = {
title: 'Page Not Found',
description: 'The requested page could not be found'
}
export default function NotFound() {
return (
<div className="flex flex-col items-center justify-center min-h-screen p-4">
<h2 className="text-2xl font-bold mb-4">404 - Page Not Found</h2>
<p className="mb-8">The page you are looking for does not exist.</p>
<Link
href="/"
className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
>
Return Home
</Link>
</div>
)
}

View File

@ -0,0 +1,18 @@
import { Button } from '@workspace/ui/components/button'
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: 'Home Page',
description: 'Home page description'
}
export default function Page() {
return (
<div className="flex items-center justify-center min-h-svh">
<div className="flex flex-col items-center justify-center gap-4">
<h1 className="text-2xl font-bold">Hello World</h1>
<Button size="sm">Button</Button>
</div>
</div>
)
}

View File

@ -0,0 +1,16 @@
import type React from 'react'
interface LayoutProps {
children: React.ReactNode
}
const Layout: React.FC<LayoutProps> = ({ children }) => {
return (
<div>
<h2>Layout for store</h2>
{children}
</div>
)
}
export default Layout

View File

@ -0,0 +1,16 @@
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: 'Store Page',
description: 'Store page description'
}
const Page = () => {
return (
<div>
<h1>Hello from store</h1>
</div>
)
}
export default Page

View File

@ -0,0 +1,16 @@
import type React from 'react'
interface LayoutProps {
children: React.ReactNode
}
const Layout: React.FC<LayoutProps> = ({ children }) => {
return (
<div>
<h2>Layout for wallet</h2>
{children}
</div>
)
}
export default Layout

View File

@ -0,0 +1,16 @@
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: 'Wallet Page',
description: 'Wallet page description'
}
const Page = () => {
return (
<div>
<h1>Hello from wallet</h1>
</div>
)
}
export default Page

View File

@ -0,0 +1 @@
export * from '@workspace/ui/tailwind.config'

View File

@ -0,0 +1,23 @@
{
"extends": "@workspace/typescript-config/nextjs.json",
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"],
"@workspace/ui/*": ["../../packages/ui/src/*"]
},
"plugins": [
{
"name": "next"
}
]
},
"include": [
"next-env.d.ts",
"next.config.mjs",
"./src/**/*.ts",
"./src/**/*.tsx",
".next/types/**/*.ts"
],
"exclude": ["node_modules"]
}

View File

@ -8,7 +8,7 @@
"build": "next build",
"start": "next start",
"lint": "biome check .",
"lint:fix": "biome check --apply .",
"lint:fix": "biome check --write .",
"format": "biome format .",
"format:fix": "biome format --write .",
"check-types": "tsc --noEmit",
@ -44,6 +44,7 @@
"@radix-ui/react-toggle": "^1.1.2",
"@radix-ui/react-toggle-group": "^1.1.2",
"@radix-ui/react-tooltip": "^1.1.8",
"@tailwindcss/upgrade": "^4.0.6",
"@workspace/ui": "workspace:*",
"class-variance-authority": "^0.7.0",
"cmdk": "1.0.0",

View File

@ -1 +1,6 @@
export { default } from '@workspace/ui/postcss.config'
export default {
plugins: {
'@tailwindcss/postcss': {},
autoprefixer: {}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -1,6 +1,6 @@
import { Providers } from '@/components/providers'
import '@workspace/ui/globals.css'
import { Providers } from '@/components/providers'
import { Geist, Geist_Mono } from 'next/font/google'
const fontSans = Geist({

View File

View File

@ -0,0 +1,18 @@
'use client'
import { ThemeProvider as NextThemesProvider } from 'next-themes'
import type * as React from 'react'
export function Providers({ children }: { children: React.ReactNode }) {
return (
<NextThemesProvider
attribute="class"
defaultTheme="system"
enableSystem
disableTransitionOnChange
enableColorScheme
>
{children}
</NextThemesProvider>
)
}

View File

View File

@ -0,0 +1,19 @@
import * as React from 'react'
const MOBILE_BREAKPOINT = 768
export function useIsMobile() {
const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
React.useEffect(() => {
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
const onChange = () => {
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
}
mql.addEventListener('change', onChange)
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
return () => mql.removeEventListener('change', onChange)
}, [])
return !!isMobile
}

View File

View File

@ -3,7 +3,7 @@
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./*"],
"@/*": ["./src/*"],
"@workspace/ui/*": ["../../packages/ui/src/*"]
},
"plugins": [

View File

@ -7,7 +7,7 @@
},
"files": {
"ignoreUnknown": false,
"ignore": ["node_modules", "dist", "build"]
"ignore": ["node_modules", "dist", "build", ".next"]
},
"formatter": {
"enabled": true,

656
pnpm-lock.yaml generated
View File

@ -27,14 +27,14 @@ importers:
specifier: ^5.7.3
version: 5.7.3
apps/web:
apps/deploy-fe:
dependencies:
'@biomejs/biome':
specifier: ^1.9.4
version: 1.9.4
'@biomejs/monorepo':
specifier: github:biomejs/biome
version: https://codeload.github.com/biomejs/biome/tar.gz/d95df40a86c8debb369fdc9070c91642325bfe1f
version: https://codeload.github.com/biomejs/biome/tar.gz/21dd358be5dade01d672916a0ab76bc825ef85cb
'@hookform/resolvers':
specifier: ^4.1.2
version: 4.1.2(react-hook-form@7.54.2(react@19.0.0))
@ -193,6 +193,175 @@ importers:
specifier: ^5
version: 5.7.3
apps/web:
dependencies:
'@biomejs/biome':
specifier: ^1.9.4
version: 1.9.4
'@biomejs/monorepo':
specifier: github:biomejs/biome
version: https://codeload.github.com/biomejs/biome/tar.gz/21dd358be5dade01d672916a0ab76bc825ef85cb
'@hookform/resolvers':
specifier: ^4.1.2
version: 4.1.2(react-hook-form@7.54.2(react@19.0.0))
'@radix-ui/react-accordion':
specifier: ^1.2.3
version: 1.2.3(@types/react-dom@18.3.1)(@types/react@18.3.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-alert-dialog':
specifier: ^1.1.6
version: 1.1.6(@types/react-dom@18.3.1)(@types/react@18.3.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-aspect-ratio':
specifier: ^1.1.2
version: 1.1.2(@types/react-dom@18.3.1)(@types/react@18.3.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-avatar':
specifier: ^1.1.3
version: 1.1.3(@types/react-dom@18.3.1)(@types/react@18.3.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-checkbox':
specifier: ^1.1.4
version: 1.1.4(@types/react-dom@18.3.1)(@types/react@18.3.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-collapsible':
specifier: ^1.1.3
version: 1.1.3(@types/react-dom@18.3.1)(@types/react@18.3.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-context-menu':
specifier: ^2.2.6
version: 2.2.6(@types/react-dom@18.3.1)(@types/react@18.3.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-dialog':
specifier: ^1.1.6
version: 1.1.6(@types/react-dom@18.3.1)(@types/react@18.3.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-dropdown-menu':
specifier: ^2.1.6
version: 2.1.6(@types/react-dom@18.3.1)(@types/react@18.3.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-hover-card':
specifier: ^1.1.6
version: 1.1.6(@types/react-dom@18.3.1)(@types/react@18.3.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-label':
specifier: ^2.1.2
version: 2.1.2(@types/react-dom@18.3.1)(@types/react@18.3.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-menubar':
specifier: ^1.1.6
version: 1.1.6(@types/react-dom@18.3.1)(@types/react@18.3.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-navigation-menu':
specifier: ^1.2.5
version: 1.2.5(@types/react-dom@18.3.1)(@types/react@18.3.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-popover':
specifier: ^1.1.6
version: 1.1.6(@types/react-dom@18.3.1)(@types/react@18.3.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-progress':
specifier: ^1.1.2
version: 1.1.2(@types/react-dom@18.3.1)(@types/react@18.3.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-radio-group':
specifier: ^1.2.3
version: 1.2.3(@types/react-dom@18.3.1)(@types/react@18.3.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-scroll-area':
specifier: ^1.2.3
version: 1.2.3(@types/react-dom@18.3.1)(@types/react@18.3.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-select':
specifier: ^2.1.6
version: 2.1.6(@types/react-dom@18.3.1)(@types/react@18.3.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-separator':
specifier: ^1.1.2
version: 1.1.2(@types/react-dom@18.3.1)(@types/react@18.3.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-slider':
specifier: ^1.2.3
version: 1.2.3(@types/react-dom@18.3.1)(@types/react@18.3.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-slot':
specifier: ^1.1.1
version: 1.1.2(@types/react@18.3.0)(react@19.0.0)
'@radix-ui/react-switch':
specifier: ^1.1.3
version: 1.1.3(@types/react-dom@18.3.1)(@types/react@18.3.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-tabs':
specifier: ^1.1.3
version: 1.1.3(@types/react-dom@18.3.1)(@types/react@18.3.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-toggle':
specifier: ^1.1.2
version: 1.1.2(@types/react-dom@18.3.1)(@types/react@18.3.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-toggle-group':
specifier: ^1.1.2
version: 1.1.2(@types/react-dom@18.3.1)(@types/react@18.3.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-tooltip':
specifier: ^1.1.8
version: 1.1.8(@types/react-dom@18.3.1)(@types/react@18.3.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@tailwindcss/upgrade':
specifier: ^4.0.6
version: 4.0.6
'@workspace/ui':
specifier: workspace:*
version: link:../../services/ui
class-variance-authority:
specifier: ^0.7.0
version: 0.7.1
cmdk:
specifier: 1.0.0
version: 1.0.0(@types/react-dom@18.3.1)(@types/react@18.3.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
date-fns:
specifier: ^4.1.0
version: 4.1.0
embla-carousel-react:
specifier: ^8.5.2
version: 8.5.2(react@19.0.0)
input-otp:
specifier: ^1.4.2
version: 1.4.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
lucide-react:
specifier: 0.456.0
version: 0.456.0(react@19.0.0)
next:
specifier: ^15.1.0
version: 15.2.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
next-themes:
specifier: ^0.4.4
version: 0.4.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react:
specifier: ^19.0.0
version: 19.0.0
react-day-picker:
specifier: 8.10.1
version: 8.10.1(date-fns@4.1.0)(react@19.0.0)
react-dom:
specifier: ^19.0.0
version: 19.0.0(react@19.0.0)
react-hook-form:
specifier: ^7.54.2
version: 7.54.2(react@19.0.0)
react-resizable-panels:
specifier: ^2.1.7
version: 2.1.7(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
recharts:
specifier: ^2.15.1
version: 2.15.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
sonner:
specifier: ^2.0.1
version: 2.0.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
vaul:
specifier: ^1.1.2
version: 1.1.2(@types/react-dom@18.3.1)(@types/react@18.3.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
zod:
specifier: ^3.23.8
version: 3.24.2
devDependencies:
'@types/node':
specifier: ^20
version: 20.17.19
'@types/react':
specifier: 18.3.0
version: 18.3.0
'@types/react-dom':
specifier: 18.3.1
version: 18.3.1
'@workspace/typescript-config':
specifier: workspace:*
version: link:../../services/typescript-config
postcss:
specifier: ^8
version: 8.5.3
tailwindcss:
specifier: ^4.0.9
version: 4.0.9
typescript:
specifier: ^5
version: 5.7.3
services/typescript-config: {}
services/ui:
@ -202,7 +371,7 @@ importers:
version: 1.9.4
'@biomejs/monorepo':
specifier: github:biomejs/biome
version: https://codeload.github.com/biomejs/biome/tar.gz/d95df40a86c8debb369fdc9070c91642325bfe1f
version: https://codeload.github.com/biomejs/biome/tar.gz/21dd358be5dade01d672916a0ab76bc825ef85cb
'@radix-ui/react-slot':
specifier: ^1.1.1
version: 1.1.2(@types/react@18.3.0)(react@19.0.0)
@ -234,6 +403,9 @@ importers:
specifier: ^3.23.8
version: 3.24.2
devDependencies:
'@tailwindcss/postcss':
specifier: ^4.0.9
version: 4.0.9
'@turbo/gen':
specifier: ^2.2.3
version: 2.4.4(@types/node@22.13.5)(typescript@5.7.3)
@ -253,7 +425,7 @@ importers:
specifier: ^10.4.20
version: 10.4.20(postcss@8.5.3)
postcss:
specifier: ^8.4.47
specifier: ^8.5.3
version: 8.5.3
tailwindcss:
specifier: ^4.0.9
@ -264,6 +436,10 @@ importers:
packages:
'@alloc/quick-lru@5.2.0':
resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
engines: {node: '>=10'}
'@babel/runtime-corejs3@7.26.9':
resolution: {integrity: sha512-5EVjbTegqN7RSJle6hMWYxO4voo4rI+9krITk+DWR+diJgGrjZjrIBnJhjrHYYQsFgI7j1w1QnrvV7YSKBfYGg==}
engines: {node: '>=6.9.0'}
@ -325,8 +501,8 @@ packages:
cpu: [x64]
os: [win32]
'@biomejs/monorepo@https://codeload.github.com/biomejs/biome/tar.gz/d95df40a86c8debb369fdc9070c91642325bfe1f':
resolution: {tarball: https://codeload.github.com/biomejs/biome/tar.gz/d95df40a86c8debb369fdc9070c91642325bfe1f}
'@biomejs/monorepo@https://codeload.github.com/biomejs/biome/tar.gz/21dd358be5dade01d672916a0ab76bc825ef85cb':
resolution: {tarball: https://codeload.github.com/biomejs/biome/tar.gz/21dd358be5dade01d672916a0ab76bc825ef85cb}
version: 0.0.0
'@cspotcode/source-map-support@0.8.1':
@ -1290,6 +1466,10 @@ packages:
'@radix-ui/rect@1.1.0':
resolution: {integrity: sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==}
'@sindresorhus/merge-streams@2.3.0':
resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==}
engines: {node: '>=18'}
'@standard-schema/utils@0.3.0':
resolution: {integrity: sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==}
@ -1299,6 +1479,86 @@ packages:
'@swc/helpers@0.5.15':
resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==}
'@tailwindcss/node@4.0.9':
resolution: {integrity: sha512-tOJvdI7XfJbARYhxX+0RArAhmuDcczTC46DGCEziqxzzbIaPnfYaIyRT31n4u8lROrsO7Q6u/K9bmQHL2uL1bQ==}
'@tailwindcss/oxide-android-arm64@4.0.9':
resolution: {integrity: sha512-YBgy6+2flE/8dbtrdotVInhMVIxnHJPbAwa7U1gX4l2ThUIaPUp18LjB9wEH8wAGMBZUb//SzLtdXXNBHPUl6Q==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [android]
'@tailwindcss/oxide-darwin-arm64@4.0.9':
resolution: {integrity: sha512-pWdl4J2dIHXALgy2jVkwKBmtEb73kqIfMpYmcgESr7oPQ+lbcQ4+tlPeVXaSAmang+vglAfFpXQCOvs/aGSqlw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
'@tailwindcss/oxide-darwin-x64@4.0.9':
resolution: {integrity: sha512-4Dq3lKp0/C7vrRSkNPtBGVebEyWt9QPPlQctxJ0H3MDyiQYvzVYf8jKow7h5QkWNe8hbatEqljMj/Y0M+ERYJg==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
'@tailwindcss/oxide-freebsd-x64@4.0.9':
resolution: {integrity: sha512-k7U1RwRODta8x0uealtVt3RoWAWqA+D5FAOsvVGpYoI6ObgmnzqWW6pnVwz70tL8UZ/QXjeMyiICXyjzB6OGtQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [freebsd]
'@tailwindcss/oxide-linux-arm-gnueabihf@4.0.9':
resolution: {integrity: sha512-NDDjVweHz2zo4j+oS8y3KwKL5wGCZoXGA9ruJM982uVJLdsF8/1AeKvUwKRlMBpxHt1EdWJSAh8a0Mfhl28GlQ==}
engines: {node: '>= 10'}
cpu: [arm]
os: [linux]
'@tailwindcss/oxide-linux-arm64-gnu@4.0.9':
resolution: {integrity: sha512-jk90UZ0jzJl3Dy1BhuFfRZ2KP9wVKMXPjmCtY4U6fF2LvrjP5gWFJj5VHzfzHonJexjrGe1lMzgtjriuZkxagg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
'@tailwindcss/oxide-linux-arm64-musl@4.0.9':
resolution: {integrity: sha512-3eMjyTC6HBxh9nRgOHzrc96PYh1/jWOwHZ3Kk0JN0Kl25BJ80Lj9HEvvwVDNTgPg154LdICwuFLuhfgH9DULmg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
'@tailwindcss/oxide-linux-x64-gnu@4.0.9':
resolution: {integrity: sha512-v0D8WqI/c3WpWH1kq/HP0J899ATLdGZmENa2/emmNjubT0sWtEke9W9+wXeEoACuGAhF9i3PO5MeyditpDCiWQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
'@tailwindcss/oxide-linux-x64-musl@4.0.9':
resolution: {integrity: sha512-Kvp0TCkfeXyeehqLJr7otsc4hd/BUPfcIGrQiwsTVCfaMfjQZCG7DjI+9/QqPZha8YapLA9UoIcUILRYO7NE1Q==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
'@tailwindcss/oxide-win32-arm64-msvc@4.0.9':
resolution: {integrity: sha512-m3+60T/7YvWekajNq/eexjhV8z10rswcz4BC9bioJ7YaN+7K8W2AmLmG0B79H14m6UHE571qB0XsPus4n0QVgQ==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [win32]
'@tailwindcss/oxide-win32-x64-msvc@4.0.9':
resolution: {integrity: sha512-dpc05mSlqkwVNOUjGu/ZXd5U1XNch1kHFJ4/cHkZFvaW1RzbHmRt24gvM8/HC6IirMxNarzVw4IXVtvrOoZtxA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
'@tailwindcss/oxide@4.0.9':
resolution: {integrity: sha512-eLizHmXFqHswJONwfqi/WZjtmWZpIalpvMlNhTM99/bkHtUs6IqgI1XQ0/W5eO2HiRQcIlXUogI2ycvKhVLNcA==}
engines: {node: '>= 10'}
'@tailwindcss/postcss@4.0.9':
resolution: {integrity: sha512-BT/E+pdMqulavEAVM5NCpxmGEwHiLDPpkmg/c/X25ZBW+izTe+aZ+v1gf/HXTrihRoCxrUp5U4YyHsBTzspQKQ==}
'@tailwindcss/upgrade@4.0.6':
resolution: {integrity: sha512-vq6wVJ+jdHuiHfIPO7/1EQFZbTW7OhFmTc40OJdnI0mvC0J/7QC1hOtIIV+JCySxp+ozOerYTu6cZxhDdl4xCQ==}
hasBin: true
'@tootallnate/quickjs-emscripten@0.23.0':
resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==}
@ -1576,6 +1836,11 @@ packages:
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
engines: {node: '>= 8'}
cssesc@3.0.0:
resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
engines: {node: '>=4'}
hasBin: true
csstype@3.1.3:
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
@ -1642,6 +1907,14 @@ packages:
decimal.js-light@2.5.1:
resolution: {integrity: sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==}
dedent@1.5.3:
resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==}
peerDependencies:
babel-plugin-macros: ^3.1.0
peerDependenciesMeta:
babel-plugin-macros:
optional: true
deep-extend@0.6.0:
resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==}
engines: {node: '>=4.0.0'}
@ -1657,6 +1930,11 @@ packages:
resolution: {integrity: sha512-wH9xOVHnczo9jN2IW68BabcecVPxacIA3g/7z6vhSU/4stOKQzeCRK0yD0A24WiAAUJmmVpWqrERcTxnLo3AnA==}
engines: {node: '>=8'}
detect-libc@1.0.3:
resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==}
engines: {node: '>=0.10'}
hasBin: true
detect-libc@2.0.3:
resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==}
engines: {node: '>=8'}
@ -1697,6 +1975,10 @@ packages:
emoji-regex@8.0.0:
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
enhanced-resolve@5.18.1:
resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==}
engines: {node: '>=10.13.0'}
escalade@3.2.0:
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
engines: {node: '>=6'}
@ -1790,6 +2072,10 @@ packages:
resolution: {integrity: sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==}
engines: {node: '>=8'}
globby@14.1.0:
resolution: {integrity: sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==}
engines: {node: '>=18'}
graceful-fs@4.2.11:
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
@ -1840,6 +2126,10 @@ packages:
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
engines: {node: '>= 4'}
ignore@7.0.3:
resolution: {integrity: sha512-bAH5jbK/F3T3Jls4I0SO1hmPR0dKU0a7+SY6n1yzRtG54FLO8d6w/nxLFX2Nb7dBu6cCWXPaAME6cYqFUMmuCA==}
engines: {node: '>= 4'}
indent-string@4.0.0:
resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==}
engines: {node: '>=8'}
@ -1932,6 +2222,10 @@ packages:
isexe@2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
jiti@2.4.2:
resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==}
hasBin: true
js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
@ -1999,6 +2293,70 @@ packages:
resolution: {integrity: sha512-/5royc/WbL2KTfFJ54wEdvxUZOBXwc54v/fW2Bz4LMOkAA3LWIxnoUiybSiauu+nhdTG98qERxH1YHwF2wZlAA==}
hasBin: true
lightningcss-darwin-arm64@1.29.1:
resolution: {integrity: sha512-HtR5XJ5A0lvCqYAoSv2QdZZyoHNttBpa5EP9aNuzBQeKGfbyH5+UipLWvVzpP4Uml5ej4BYs5I9Lco9u1fECqw==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [darwin]
lightningcss-darwin-x64@1.29.1:
resolution: {integrity: sha512-k33G9IzKUpHy/J/3+9MCO4e+PzaFblsgBjSGlpAaFikeBFm8B/CkO3cKU9oI4g+fjS2KlkLM/Bza9K/aw8wsNA==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [darwin]
lightningcss-freebsd-x64@1.29.1:
resolution: {integrity: sha512-0SUW22fv/8kln2LnIdOCmSuXnxgxVC276W5KLTwoehiO0hxkacBxjHOL5EtHD8BAXg2BvuhsJPmVMasvby3LiQ==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [freebsd]
lightningcss-linux-arm-gnueabihf@1.29.1:
resolution: {integrity: sha512-sD32pFvlR0kDlqsOZmYqH/68SqUMPNj+0pucGxToXZi4XZgZmqeX/NkxNKCPsswAXU3UeYgDSpGhu05eAufjDg==}
engines: {node: '>= 12.0.0'}
cpu: [arm]
os: [linux]
lightningcss-linux-arm64-gnu@1.29.1:
resolution: {integrity: sha512-0+vClRIZ6mmJl/dxGuRsE197o1HDEeeRk6nzycSy2GofC2JsY4ifCRnvUWf/CUBQmlrvMzt6SMQNMSEu22csWQ==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
lightningcss-linux-arm64-musl@1.29.1:
resolution: {integrity: sha512-UKMFrG4rL/uHNgelBsDwJcBqVpzNJbzsKkbI3Ja5fg00sgQnHw/VrzUTEc4jhZ+AN2BvQYz/tkHu4vt1kLuJyw==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
lightningcss-linux-x64-gnu@1.29.1:
resolution: {integrity: sha512-u1S+xdODy/eEtjADqirA774y3jLcm8RPtYztwReEXoZKdzgsHYPl0s5V52Tst+GKzqjebkULT86XMSxejzfISw==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
lightningcss-linux-x64-musl@1.29.1:
resolution: {integrity: sha512-L0Tx0DtaNUTzXv0lbGCLB/c/qEADanHbu4QdcNOXLIe1i8i22rZRpbT3gpWYsCh9aSL9zFujY/WmEXIatWvXbw==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
lightningcss-win32-arm64-msvc@1.29.1:
resolution: {integrity: sha512-QoOVnkIEFfbW4xPi+dpdft/zAKmgLgsRHfJalEPYuJDOWf7cLQzYg0DEh8/sn737FaeMJxHZRc1oBreiwZCjog==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [win32]
lightningcss-win32-x64-msvc@1.29.1:
resolution: {integrity: sha512-NygcbThNBe4JElP+olyTI/doBNGJvLs3bFCRPdvuCcxZCcCZ71B858IHpdm7L1btZex0FvCmM17FK98Y9MRy1Q==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [win32]
lightningcss@1.29.1:
resolution: {integrity: sha512-FmGoeD4S05ewj+AkhTY+D+myDvXI6eL27FjHIjoyUkO/uw7WZD1fBVs0QxeYWa7E17CUHJaYX/RUGISCtcrG4Q==}
engines: {node: '>= 12.0.0'}
lodash.get@4.4.2:
resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==}
deprecated: This package is deprecated. Use the optional chaining (?.) operator instead.
@ -2065,6 +2423,10 @@ packages:
resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
hasBin: true
mri@1.2.0:
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
engines: {node: '>=4'}
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
@ -2113,6 +2475,14 @@ packages:
no-case@2.3.2:
resolution: {integrity: sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==}
node-addon-api@8.3.1:
resolution: {integrity: sha512-lytcDEdxKjGJPTLEfW4mYMigRezMlyJY8W4wxJK8zE533Jlb8L8dRuObJFWg2P+AuOIxoCgKF+2Oq4d4Zd0OUA==}
engines: {node: ^18 || ^20 || >= 21}
node-gyp-build@4.8.4:
resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==}
hasBin: true
node-plop@0.26.3:
resolution: {integrity: sha512-Cov028YhBZ5aB7MdMWJEmwyBig43aGL5WT4vdoB28Oitau1zZAcHUn8Sgfk9HM33TqhtLJ9PlM/O0Mv+QpV/4Q==}
engines: {node: '>=8.9.4'}
@ -2187,6 +2557,10 @@ packages:
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
engines: {node: '>=8'}
path-type@6.0.0:
resolution: {integrity: sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==}
engines: {node: '>=18'}
picocolors@1.0.1:
resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==}
@ -2197,6 +2571,20 @@ packages:
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
engines: {node: '>=8.6'}
pify@2.3.0:
resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
engines: {node: '>=0.10.0'}
postcss-import@16.1.0:
resolution: {integrity: sha512-7hsAZ4xGXl4MW+OKEWCnF6T5jqBw80/EE9aXg1r2yyn1RsVEU8EtKXbijEODa+rg7iih4bKf7vlvTGYR4CnPNg==}
engines: {node: '>=18.0.0'}
peerDependencies:
postcss: ^8.0.0
postcss-selector-parser@7.1.0:
resolution: {integrity: sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==}
engines: {node: '>=4'}
postcss-value-parser@4.2.0:
resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
@ -2208,6 +2596,11 @@ packages:
resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==}
engines: {node: ^10 || ^12 || >=14}
prettier@3.5.0:
resolution: {integrity: sha512-quyMrVt6svPS7CjQ9gKb3GLEX/rl3BCL2oa/QkNcXv4YNVBC9olt3s+H7ukto06q7B1Qz46PbrKLO34PR6vXcA==}
engines: {node: '>=14'}
hasBin: true
prop-types@15.8.1:
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
@ -2310,6 +2703,9 @@ packages:
resolution: {integrity: sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==}
engines: {node: '>=0.10.0'}
read-cache@1.0.0:
resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==}
readable-stream@3.6.2:
resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
engines: {node: '>= 6'}
@ -2410,6 +2806,10 @@ packages:
resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
engines: {node: '>=8'}
slash@5.1.0:
resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==}
engines: {node: '>=14.16'}
smart-buffer@4.2.0:
resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==}
engines: {node: '>= 6.0.0', npm: '>= 3.0.0'}
@ -2501,9 +2901,16 @@ packages:
peerDependencies:
tailwindcss: '>=3.0.0 || insiders'
tailwindcss@4.0.6:
resolution: {integrity: sha512-mysewHYJKaXgNOW6pp5xon/emCsfAMnO8WMaGKZZ35fomnR/T5gYnRg2/yRTTrtXiEl1tiVkeRt0eMO6HxEZqw==}
tailwindcss@4.0.9:
resolution: {integrity: sha512-12laZu+fv1ONDRoNR9ipTOpUD7RN9essRVkX36sjxuRUInpN7hIiHN4lBd/SIFjbISvnXzp8h/hXzmU8SQQYhw==}
tapable@2.2.1:
resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==}
engines: {node: '>=6'}
through@2.3.8:
resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==}
@ -2527,6 +2934,25 @@ packages:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
engines: {node: '>=8.0'}
tree-sitter-javascript@0.23.1:
resolution: {integrity: sha512-/bnhbrTD9frUYHQTiYnPcxyHORIw157ERBa6dqzaKxvR/x3PC4Yzd+D1pZIMS6zNg2v3a8BZ0oK7jHqsQo9fWA==}
peerDependencies:
tree-sitter: ^0.21.1
peerDependenciesMeta:
tree-sitter:
optional: true
tree-sitter-typescript@0.23.2:
resolution: {integrity: sha512-e04JUUKxTT53/x3Uq1zIL45DoYKVfHH4CZqwgZhPg5qYROl5nQjV+85ruFzFGZxu+QeFVbRTPDRnqL9UbU4VeA==}
peerDependencies:
tree-sitter: ^0.21.0
peerDependenciesMeta:
tree-sitter:
optional: true
tree-sitter@0.22.4:
resolution: {integrity: sha512-usbHZP9/oxNsUY65MQUsduGRqDHQOou1cagUSwjhoSYAmSahjQDAVsh9s+SlZkn8X8+O1FULRGwHu7AFP3kjzg==}
ts-node@10.9.2:
resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==}
hasBin: true
@ -2601,6 +3027,10 @@ packages:
undici-types@6.20.0:
resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==}
unicorn-magic@0.3.0:
resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==}
engines: {node: '>=18'}
universalify@2.0.1:
resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
engines: {node: '>= 10.0.0'}
@ -2686,6 +3116,8 @@ packages:
snapshots:
'@alloc/quick-lru@5.2.0': {}
'@babel/runtime-corejs3@7.26.9':
dependencies:
core-js-pure: 3.40.0
@ -2730,7 +3162,7 @@ snapshots:
'@biomejs/cli-win32-x64@1.9.4':
optional: true
'@biomejs/monorepo@https://codeload.github.com/biomejs/biome/tar.gz/d95df40a86c8debb369fdc9070c91642325bfe1f': {}
'@biomejs/monorepo@https://codeload.github.com/biomejs/biome/tar.gz/21dd358be5dade01d672916a0ab76bc825ef85cb': {}
'@cspotcode/source-map-support@0.8.1':
dependencies:
@ -3673,6 +4105,8 @@ snapshots:
'@radix-ui/rect@1.1.0': {}
'@sindresorhus/merge-streams@2.3.0': {}
'@standard-schema/utils@0.3.0': {}
'@swc/counter@0.1.3': {}
@ -3681,6 +4115,89 @@ snapshots:
dependencies:
tslib: 2.8.1
'@tailwindcss/node@4.0.9':
dependencies:
enhanced-resolve: 5.18.1
jiti: 2.4.2
tailwindcss: 4.0.9
'@tailwindcss/oxide-android-arm64@4.0.9':
optional: true
'@tailwindcss/oxide-darwin-arm64@4.0.9':
optional: true
'@tailwindcss/oxide-darwin-x64@4.0.9':
optional: true
'@tailwindcss/oxide-freebsd-x64@4.0.9':
optional: true
'@tailwindcss/oxide-linux-arm-gnueabihf@4.0.9':
optional: true
'@tailwindcss/oxide-linux-arm64-gnu@4.0.9':
optional: true
'@tailwindcss/oxide-linux-arm64-musl@4.0.9':
optional: true
'@tailwindcss/oxide-linux-x64-gnu@4.0.9':
optional: true
'@tailwindcss/oxide-linux-x64-musl@4.0.9':
optional: true
'@tailwindcss/oxide-win32-arm64-msvc@4.0.9':
optional: true
'@tailwindcss/oxide-win32-x64-msvc@4.0.9':
optional: true
'@tailwindcss/oxide@4.0.9':
optionalDependencies:
'@tailwindcss/oxide-android-arm64': 4.0.9
'@tailwindcss/oxide-darwin-arm64': 4.0.9
'@tailwindcss/oxide-darwin-x64': 4.0.9
'@tailwindcss/oxide-freebsd-x64': 4.0.9
'@tailwindcss/oxide-linux-arm-gnueabihf': 4.0.9
'@tailwindcss/oxide-linux-arm64-gnu': 4.0.9
'@tailwindcss/oxide-linux-arm64-musl': 4.0.9
'@tailwindcss/oxide-linux-x64-gnu': 4.0.9
'@tailwindcss/oxide-linux-x64-musl': 4.0.9
'@tailwindcss/oxide-win32-arm64-msvc': 4.0.9
'@tailwindcss/oxide-win32-x64-msvc': 4.0.9
'@tailwindcss/postcss@4.0.9':
dependencies:
'@alloc/quick-lru': 5.2.0
'@tailwindcss/node': 4.0.9
'@tailwindcss/oxide': 4.0.9
lightningcss: 1.29.1
postcss: 8.5.3
tailwindcss: 4.0.9
'@tailwindcss/upgrade@4.0.6':
dependencies:
'@tailwindcss/node': 4.0.9
'@tailwindcss/oxide': 4.0.9
braces: 3.0.3
dedent: 1.5.3
enhanced-resolve: 5.18.1
globby: 14.1.0
jiti: 2.4.2
mri: 1.2.0
picocolors: 1.1.1
postcss: 8.5.3
postcss-import: 16.1.0(postcss@8.5.3)
postcss-selector-parser: 7.1.0
prettier: 3.5.0
tailwindcss: 4.0.6
tree-sitter: 0.22.4
tree-sitter-typescript: 0.23.2(tree-sitter@0.22.4)
transitivePeerDependencies:
- babel-plugin-macros
'@tootallnate/quickjs-emscripten@0.23.0': {}
'@tsconfig/node10@1.0.11': {}
@ -3999,6 +4516,8 @@ snapshots:
shebang-command: 2.0.0
which: 2.0.2
cssesc@3.0.0: {}
csstype@3.1.3: {}
d3-array@3.2.4:
@ -4049,6 +4568,8 @@ snapshots:
decimal.js-light@2.5.1: {}
dedent@1.5.3: {}
deep-extend@0.6.0: {}
defaults@1.0.4:
@ -4072,6 +4593,8 @@ snapshots:
rimraf: 3.0.2
slash: 3.0.0
detect-libc@1.0.3: {}
detect-libc@2.0.3:
optional: true
@ -4108,6 +4631,11 @@ snapshots:
emoji-regex@8.0.0: {}
enhanced-resolve@5.18.1:
dependencies:
graceful-fs: 4.2.11
tapable: 2.2.1
escalade@3.2.0: {}
escape-string-regexp@1.0.5: {}
@ -4216,6 +4744,15 @@ snapshots:
merge2: 1.4.1
slash: 3.0.0
globby@14.1.0:
dependencies:
'@sindresorhus/merge-streams': 2.3.0
fast-glob: 3.3.3
ignore: 7.0.3
path-type: 6.0.0
slash: 5.1.0
unicorn-magic: 0.3.0
graceful-fs@4.2.11: {}
gradient-string@2.0.2:
@ -4269,6 +4806,8 @@ snapshots:
ignore@5.3.2: {}
ignore@7.0.3: {}
indent-string@4.0.0: {}
inflight@1.0.6:
@ -4365,6 +4904,8 @@ snapshots:
isexe@2.0.0: {}
jiti@2.4.2: {}
js-tokens@4.0.0: {}
js-yaml@4.1.0:
@ -4422,6 +4963,51 @@ snapshots:
lefthook-windows-arm64: 1.11.2
lefthook-windows-x64: 1.11.2
lightningcss-darwin-arm64@1.29.1:
optional: true
lightningcss-darwin-x64@1.29.1:
optional: true
lightningcss-freebsd-x64@1.29.1:
optional: true
lightningcss-linux-arm-gnueabihf@1.29.1:
optional: true
lightningcss-linux-arm64-gnu@1.29.1:
optional: true
lightningcss-linux-arm64-musl@1.29.1:
optional: true
lightningcss-linux-x64-gnu@1.29.1:
optional: true
lightningcss-linux-x64-musl@1.29.1:
optional: true
lightningcss-win32-arm64-msvc@1.29.1:
optional: true
lightningcss-win32-x64-msvc@1.29.1:
optional: true
lightningcss@1.29.1:
dependencies:
detect-libc: 1.0.3
optionalDependencies:
lightningcss-darwin-arm64: 1.29.1
lightningcss-darwin-x64: 1.29.1
lightningcss-freebsd-x64: 1.29.1
lightningcss-linux-arm-gnueabihf: 1.29.1
lightningcss-linux-arm64-gnu: 1.29.1
lightningcss-linux-arm64-musl: 1.29.1
lightningcss-linux-x64-gnu: 1.29.1
lightningcss-linux-x64-musl: 1.29.1
lightningcss-win32-arm64-msvc: 1.29.1
lightningcss-win32-x64-msvc: 1.29.1
lodash.get@4.4.2: {}
lodash@4.17.21: {}
@ -4478,6 +5064,8 @@ snapshots:
dependencies:
minimist: 1.2.8
mri@1.2.0: {}
ms@2.1.3: {}
mute-stream@0.0.8: {}
@ -4522,6 +5110,10 @@ snapshots:
dependencies:
lower-case: 1.1.4
node-addon-api@8.3.1: {}
node-gyp-build@4.8.4: {}
node-plop@0.26.3:
dependencies:
'@babel/runtime-corejs3': 7.26.9
@ -4622,12 +5214,28 @@ snapshots:
path-type@4.0.0: {}
path-type@6.0.0: {}
picocolors@1.0.1: {}
picocolors@1.1.1: {}
picomatch@2.3.1: {}
pify@2.3.0: {}
postcss-import@16.1.0(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
read-cache: 1.0.0
resolve: 1.22.10
postcss-selector-parser@7.1.0:
dependencies:
cssesc: 3.0.0
util-deprecate: 1.0.2
postcss-value-parser@4.2.0: {}
postcss@8.4.31:
@ -4642,6 +5250,8 @@ snapshots:
picocolors: 1.1.1
source-map-js: 1.2.1
prettier@3.5.0: {}
prop-types@15.8.1:
dependencies:
loose-envify: 1.4.0
@ -4752,6 +5362,10 @@ snapshots:
react@19.0.0: {}
read-cache@1.0.0:
dependencies:
pify: 2.3.0
readable-stream@3.6.2:
dependencies:
inherits: 2.0.4
@ -4875,6 +5489,8 @@ snapshots:
slash@3.0.0: {}
slash@5.1.0: {}
smart-buffer@4.2.0: {}
snake-case@2.1.0:
@ -4951,8 +5567,12 @@ snapshots:
dependencies:
tailwindcss: 4.0.9
tailwindcss@4.0.6: {}
tailwindcss@4.0.9: {}
tapable@2.2.1: {}
through@2.3.8: {}
tiny-invariant@1.3.3: {}
@ -4977,6 +5597,26 @@ snapshots:
dependencies:
is-number: 7.0.0
tree-sitter-javascript@0.23.1(tree-sitter@0.22.4):
dependencies:
node-addon-api: 8.3.1
node-gyp-build: 4.8.4
optionalDependencies:
tree-sitter: 0.22.4
tree-sitter-typescript@0.23.2(tree-sitter@0.22.4):
dependencies:
node-addon-api: 8.3.1
node-gyp-build: 4.8.4
tree-sitter-javascript: 0.23.1(tree-sitter@0.22.4)
optionalDependencies:
tree-sitter: 0.22.4
tree-sitter@0.22.4:
dependencies:
node-addon-api: 8.3.1
node-gyp-build: 4.8.4
ts-node@10.9.2(@types/node@22.13.5)(typescript@5.7.3):
dependencies:
'@cspotcode/source-map-support': 0.8.1
@ -5037,6 +5677,8 @@ snapshots:
undici-types@6.20.0: {}
unicorn-magic@0.3.0: {}
universalify@2.0.1: {}
update-browserslist-db@1.1.3(browserslist@4.24.4):

View File

@ -1,9 +1,15 @@
packages:
- apps/*
- services/*
ignoredBuiltDependencies:
- '@biomejs/biome'
- core-js-pure
- sharp
onlyBuiltDependencies:
- '@biomejs/biome'
- '@biomejs/cli-darwin-arm64'
- chalk
- lefthook
- lefthook-darwin-arm64
- tree-sitter
- tree-sitter-javascript
- tree-sitter-typescript
- turbo
- turbo-darwin-arm64
- typescript

View File

@ -21,13 +21,14 @@
"zod": "^3.23.8"
},
"devDependencies": {
"@tailwindcss/postcss": "^4.0.9",
"@turbo/gen": "^2.2.3",
"@types/node": "^22.9.0",
"@types/react": "18.3.0",
"@types/react-dom": "18.3.1",
"@workspace/typescript-config": "workspace:*",
"autoprefixer": "^10.4.20",
"postcss": "^8.4.47",
"postcss": "^8.5.3",
"react": "^18.3.1",
"tailwindcss": "^4.0.9",
"typescript": "^5.6.3"

View File

@ -1,9 +1,5 @@
/** @type {import('postcss-load-config').Config} */
const config = {
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {}
'@tailwindcss/postcss': {}
}
}
export default config

View File

@ -1,6 +1,4 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@import "tailwindcss";
@layer base {
:root {
@ -72,22 +70,13 @@
--sidebar-border: 240 3.7% 15.9%;
--sidebar-ring: 217.2 91.2% 59.8%;
}
}
/* } */
@layer base {
/* @theme base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}
@layer base {
* {
@apply border-border outline-ring/50;
}
body {
@apply bg-background text-foreground;
}
} */
}

View File

@ -1,6 +1,6 @@
import type { Config } from 'tailwindcss'
import defaultTheme from 'tailwindcss'
import tailwindcssAnimate from 'tailwindcss-animate'
import defaultTheme from 'tailwindcss/defaultTheme'
const config = {
// darkMode: ["class"],
content: [

View File

@ -0,0 +1,171 @@
# Next.js App Router Structure with Abbreviated URLs
```
app/
page.tsx # URL: /
layout.tsx
not-found.tsx
global-error.tsx
login/
page.tsx # URL: /login
wallet/
page.tsx # URL: /wallet
layout.tsx
store/
page.tsx # URL: /store
layout.tsx
(web3-authenticated)/ # Auth wrapper (not in URL)
layout.tsx
(dashboard)/ # Dashboard wrapper (not in URL)
layout.tsx
page.tsx # URL: /
(buy-prepaid-service)/
bp/ # Abbreviated
page.tsx # URL: /bp
(projects)/
pr/ # Abbreviated
page.tsx # URL: /pr
[provider]/
page.tsx # URL: /pr/[provider]
[orgSlug]/
page.tsx # URL: /pr/[provider]/[orgSlug]
layout.tsx
error.tsx
not-found.tsx
loading.tsx
(settings)/
set/ # Abbreviated
page.tsx # URL: /pr/[provider]/[orgSlug]/set
(projects)/
ps/ # Abbreviated
page.tsx # URL: /pr/[provider]/[orgSlug]/ps
layout.tsx
loading.tsx
error.tsx
(create)/
cr/ # Abbreviated
page.tsx # URL: /pr/[provider]/[orgSlug]/ps/cr
layout.tsx
(configure)/
cf/ # Abbreviated
page.tsx # URL: /pr/[provider]/[orgSlug]/ps/cr/cf
(deploy)/
dp/ # Abbreviated
page.tsx # URL: /pr/[provider]/[orgSlug]/ps/cr/dp
loading.tsx
(success)/
sc/ # Abbreviated
[id]/
page.tsx # URL: /pr/[provider]/[orgSlug]/ps/cr/sc/[id]
(template)/
tm/ # Abbreviated
page.tsx # URL: /pr/[provider]/[orgSlug]/ps/cr/tm
(configure)/
cf/ # Abbreviated
page.tsx # URL: /pr/[provider]/[orgSlug]/ps/cr/tm/cf
(deploy)/
dp/ # Abbreviated
page.tsx # URL: /pr/[provider]/[orgSlug]/ps/cr/tm/dp
loading.tsx
[id]/
page.tsx # URL: /pr/[provider]/[orgSlug]/ps/[id]
layout.tsx
loading.tsx
error.tsx
not-found.tsx
(deployments)/
dep/ # Abbreviated
page.tsx # URL: /pr/[provider]/[orgSlug]/ps/[id]/dep
loading.tsx
(integrations)/
int/ # Abbreviated
page.tsx # URL: /pr/[provider]/[orgSlug]/ps/[id]/int
(settings)/
set/ # Abbreviated
page.tsx # URL: /pr/[provider]/[orgSlug]/ps/[id]/set
layout.tsx
(domains)/
dom/ # Abbreviated
page.tsx # URL: /pr/[provider]/[orgSlug]/ps/[id]/set/dom
(add)/
add/ # Kept as-is (short enough)
page.tsx # URL: /pr/[provider]/[orgSlug]/ps/[id]/set/dom/add
(config)/
cf/ # Abbreviated
page.tsx # URL: /pr/[provider]/[orgSlug]/ps/[id]/set/dom/add/cf
(git)/
git/ # Kept as-is (short enough)
page.tsx # URL: /pr/[provider]/[orgSlug]/ps/[id]/set/git
(environment-variables)/
env/ # Abbreviated
page.tsx # URL: /pr/[provider]/[orgSlug]/ps/[id]/set/env
(collaborators)/
col/ # Abbreviated
page.tsx # URL: /pr/[provider]/[orgSlug]/ps/[id]/set/col
```
## Abbreviation Legend
- bp = buy-prepaid-service
- pr = projects
- ps = projects (within organization)
- cr = create
- cf = configure
- dp = deploy
- sc = success
- tm = template
- dep = deployments
- int = integrations
- set = settings
- dom = domains
- env = environment-variables
- col = collaborators
## API Routes
```
app/
api/
route.ts
organizations/
[slug]/
route.ts
projects/
route.ts
[id]/
route.ts
deployments/
route.ts
```

View File

@ -0,0 +1,441 @@
# Next.js App Router File Templates
This document provides basic templates for the common file types used in a Next.js application with the App Router. These templates follow the current best practices for Next.js 15.
## Page Templates
### Basic Page (`page.tsx`)
```tsx
import { Metadata } from 'next'
export const metadata: Metadata = {
title: 'Page Title',
description: 'Page description',
}
export default function Page() {
return (
<div>
<h1>Page Content</h1>
{/* Page content goes here */}
</div>
)
}
```
### Dynamic Route Page (`[slug]/page.tsx`)
```tsx
export async function generateMetadata({ params }) {
return {
title: `Page for ${params.slug}`,
description: `Description for ${params.slug}`,
}
}
export default function DynamicPage({ params }) {
const { slug } = params
return (
<div>
<h1>Dynamic Page: {slug}</h1>
{/* Dynamic page content goes here */}
</div>
)
}
```
## Layout Templates
### Root Layout (`layout.tsx`)
```tsx
import { Metadata } from 'next'
import './globals.css'
export const metadata: Metadata = {
title: {
template: '%s | Site Name',
default: 'Site Name',
},
description: 'Site description',
}
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
<header>
{/* Header content */}
</header>
<main>{children}</main>
<footer>
{/* Footer content */}
</footer>
</body>
</html>
)
}
```
### Nested Layout (`(dashboard)/layout.tsx`)
```tsx
export default function DashboardLayout({ children }) {
return (
<div className="dashboard-layout">
<nav className="dashboard-nav">
{/* Dashboard navigation */}
</nav>
<div className="dashboard-content">
{children}
</div>
</div>
)
}
```
### Auth Layout with Session Check (`(authenticated)/layout.tsx`)
```tsx
import { redirect } from 'next/navigation'
// This is a Server Component
export default async function AuthLayout({ children }) {
const session = await getSession() // Replace with your auth solution
if (!session) {
redirect('/login')
}
return <>{children}</>
}
```
## Error Handling Templates
### Not Found (`not-found.tsx`)
```tsx
import Link from 'next/link'
export const metadata = {
title: 'Not Found',
description: 'Page not found',
}
export default function NotFound() {
return (
<div className="error-container">
<h1>404 - Page Not Found</h1>
<p>The page you are looking for does not exist.</p>
<Link href="/">
Return to Home
</Link>
</div>
)
}
```
### Error Page (`error.tsx`)
```tsx
'use client' // Error components must be Client Components
import { useEffect } from 'react'
export default function Error({ error, reset }) {
useEffect(() => {
// Log the error to an error reporting service
console.error(error)
}, [error])
return (
<div className="error-container">
<h2>Something went wrong!</h2>
<button
onClick={
// Attempt to recover by trying to re-render the segment
() => reset()
}
>
Try again
</button>
</div>
)
}
```
### Global Error (`global-error.tsx`)
```tsx
'use client'
export default function GlobalError({ error, reset }) {
return (
<html>
<body>
<div className="global-error">
<h2>Something went wrong!</h2>
<button onClick={() => reset()}>Try again</button>
</div>
</body>
</html>
)
}
```
## Loading States
### Loading Component (`loading.tsx`)
```tsx
export default function Loading() {
return (
<div className="loading-container">
<div className="loading-spinner"></div>
<p>Loading...</p>
</div>
)
}
```
## Route Handlers
### API Route (`api/route.ts`)
```ts
import { NextResponse } from 'next/server'
export async function GET(request) {
// Handle GET request
return NextResponse.json({ message: 'Hello World' })
}
export async function POST(request) {
// Handle POST request
const body = await request.json()
return NextResponse.json({ received: body })
}
```
### Dynamic API Route (`api/[slug]/route.ts`)
```ts
import { NextResponse } from 'next/server'
export async function GET(request, { params }) {
const { slug } = params
return NextResponse.json({ slug })
}
```
## Middleware
### Middleware (`middleware.ts`)
Place this file in the root of your project:
```ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
// This function runs before requests are completed
export function middleware(request: NextRequest) {
const currentUrl = request.nextUrl.clone()
// Example: check if user is authenticated
const isAuthenticated = checkAuth(request)
if (!isAuthenticated && currentUrl.pathname.startsWith('/protected')) {
return NextResponse.redirect(new URL('/login', request.url))
}
return NextResponse.next()
}
// Configure matcher for paths that should trigger middleware
export const config = {
matcher: ['/protected/:path*', '/api/:path*'],
}
// Example auth check function
function checkAuth(request) {
// Implement your auth check logic here
return !!request.cookies.get('auth-token')
}
```
## Utilities - Server Actions
### Form Actions (`actions.ts`)
```ts
'use server'
export async function submitForm(formData: FormData) {
// Validate data
const name = formData.get('name')
const email = formData.get('email')
// Process data
try {
// Save to database or send to API
await saveToDatabase({ name, email })
return { success: true }
} catch (error) {
return { success: false, error: error.message }
}
}
async function saveToDatabase(data) {
// Implementation for database interaction
}
```
## Server Component with Data Fetching
### Data Fetching in Server Component (`dashboard/page.tsx`)
```tsx
// This is a Server Component
export default async function DashboardPage() {
// This data fetching happens on the server
const data = await fetchDashboardData()
return (
<div>
<h1>Dashboard</h1>
<div className="dashboard-stats">
{data.map(item => (
<div key={item.id} className="stat-card">
<h3>{item.title}</h3>
<p>{item.value}</p>
</div>
))}
</div>
</div>
)
}
async function fetchDashboardData() {
// API or database call
const res = await fetch('https://api.example.com/dashboard-data', {
cache: 'no-store' // Don't cache this data
})
if (!res.ok) {
throw new Error('Failed to fetch dashboard data')
}
return res.json()
}
```
## Client Component with Hooks
### Interactive Client Component (`components/Counter.tsx`)
```tsx
'use client' // Mark as Client Component
import { useState } from 'react'
export default function Counter() {
const [count, setCount] = useState(0)
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
)
}
```
## Parallel Routes
### Parallel Route Layout (`@dashboard/page.tsx` and `@profile/page.tsx`)
In your directory structure:
```
app/
layout.tsx
[user]/
layout.tsx
page.tsx
@dashboard/
page.tsx
@profile/
page.tsx
```
In `[user]/layout.tsx`:
```tsx
export default function UserLayout({ children, dashboard, profile }) {
return (
<div className="user-page">
<div className="sidebar">
{/* Sidebar navigation */}
</div>
<div className="main-content">
{children}
</div>
<div className="dashboard-slot">
{dashboard}
</div>
<div className="profile-slot">
{profile}
</div>
</div>
)
}
```
## Route Interception
### Photo Modal Example (`./(.)photos/[id]/page.tsx`)
The directory structure might look like:
```
app/
photos/
page.tsx
[id]/
page.tsx
(.)photos/
[id]/
page.tsx // This intercepts /photos/[id]
```
In `./(.)photos/[id]/page.tsx`:
```tsx
export default function PhotoModal({ params }) {
const { id } = params
// Fetch photo data based on id
return (
<div className="modal">
<div className="modal-content">
<h2>Photo {id}</h2>
<img src={`/api/photos/${id}`} alt={`Photo ${id}`} />
</div>
</div>
)
}
```
## References
- [Official Next.js Documentation](https://nextjs.org/docs/app)
- [Pages and Layouts](https://nextjs.org/docs/app/building-your-application/routing/pages-and-layouts)
- [Route Handlers](https://nextjs.org/docs/app/building-your-application/routing/route-handlers)
- [Error Handling](https://nextjs.org/docs/app/building-your-application/routing/error-handling)
- [Loading UI and Streaming](https://nextjs.org/docs/app/building-your-application/routing/loading-ui-and-streaming)
- [Metadata API](https://nextjs.org/docs/app/building-your-application/optimizing/metadata)
- [Server Actions](https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions)
- [Middleware](https://nextjs.org/docs/app/building-your-application/routing/middleware)