diff --git a/components.json b/components.json
new file mode 100644
index 0000000..ffe928f
--- /dev/null
+++ b/components.json
@@ -0,0 +1,21 @@
+{
+ "$schema": "https://ui.shadcn.com/schema.json",
+ "style": "new-york",
+ "rsc": true,
+ "tsx": true,
+ "tailwind": {
+ "config": "",
+ "css": "src/app/globals.css",
+ "baseColor": "neutral",
+ "cssVariables": true,
+ "prefix": ""
+ },
+ "aliases": {
+ "components": "@/components",
+ "utils": "@/lib/utils",
+ "ui": "@/components/ui",
+ "lib": "@/lib",
+ "hooks": "@/hooks"
+ },
+ "iconLibrary": "lucide"
+}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 87c8584..7b1fefa 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,9 +8,23 @@
"name": "codenuk-frontend",
"version": "0.1.0",
"dependencies": {
+ "@next/font": "^14.2.15",
+ "@radix-ui/react-avatar": "^1.1.10",
+ "@radix-ui/react-checkbox": "^1.3.2",
+ "@radix-ui/react-dropdown-menu": "^2.1.15",
+ "@radix-ui/react-label": "^2.1.7",
+ "@radix-ui/react-progress": "^1.1.7",
+ "@radix-ui/react-radio-group": "^1.3.7",
+ "@radix-ui/react-select": "^2.2.5",
+ "@radix-ui/react-slot": "^1.2.3",
+ "@radix-ui/react-tabs": "^1.1.12",
+ "class-variance-authority": "^0.7.1",
+ "clsx": "^2.1.1",
+ "lucide-react": "^0.539.0",
"next": "15.4.6",
"react": "19.1.0",
- "react-dom": "19.1.0"
+ "react-dom": "19.1.0",
+ "tailwind-merge": "^3.3.1"
},
"devDependencies": {
"@eslint/eslintrc": "^3",
@@ -21,6 +35,7 @@
"eslint": "^9",
"eslint-config-next": "15.4.6",
"tailwindcss": "^4",
+ "tw-animate-css": "^1.3.6",
"typescript": "^5"
}
},
@@ -225,6 +240,44 @@
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
+ "node_modules/@floating-ui/core": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz",
+ "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/utils": "^0.2.10"
+ }
+ },
+ "node_modules/@floating-ui/dom": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.3.tgz",
+ "integrity": "sha512-uZA413QEpNuhtb3/iIKoYMSK07keHPYeXF02Zhd6e213j+d1NamLix/mCLxBUDW/Gx52sPH2m+chlUsyaBs/Ag==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/core": "^1.7.3",
+ "@floating-ui/utils": "^0.2.10"
+ }
+ },
+ "node_modules/@floating-ui/react-dom": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.5.tgz",
+ "integrity": "sha512-HDO/1/1oH9fjj4eLgegrlH3dklZpHtUYYFiVwMUwfGvk9jWDRWqkklA2/NFScknrcNSspbV868WjXORvreDX+Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/dom": "^1.7.3"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
+ "node_modules/@floating-ui/utils": {
+ "version": "0.2.10",
+ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz",
+ "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==",
+ "license": "MIT"
+ },
"node_modules/@humanfs/core": {
"version": "0.19.1",
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
@@ -790,6 +843,15 @@
"fast-glob": "3.3.1"
}
},
+ "node_modules/@next/font": {
+ "version": "14.2.15",
+ "resolved": "https://registry.npmjs.org/@next/font/-/font-14.2.15.tgz",
+ "integrity": "sha512-QopYhBmCDDrNDynbi+ZD1hDZXmQXVFo7TmAFp4DQgO/kogz1OLbQ92hPigJbj572eZ3GaaVxNIyYVn3/eAsehg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "next": "*"
+ }
+ },
"node_modules/@next/swc-darwin-arm64": {
"version": "15.4.6",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.4.6.tgz",
@@ -966,6 +1028,810 @@
"node": ">=12.4.0"
}
},
+ "node_modules/@radix-ui/number": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz",
+ "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==",
+ "license": "MIT"
+ },
+ "node_modules/@radix-ui/primitive": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.2.tgz",
+ "integrity": "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==",
+ "license": "MIT"
+ },
+ "node_modules/@radix-ui/react-arrow": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz",
+ "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.1.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-avatar": {
+ "version": "1.1.10",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.10.tgz",
+ "integrity": "sha512-V8piFfWapM5OmNCXTzVQY+E1rDa53zY+MQ4Y7356v4fFz6vqCyUtIz2rUD44ZEdwg78/jKmMJHj07+C/Z/rcog==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-is-hydrated": "0.1.0",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-checkbox": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.3.2.tgz",
+ "integrity": "sha512-yd+dI56KZqawxKZrJ31eENUwqc1QSqg4OZ15rybGjF2ZNwMO+wCyHzAVLRp9qoYJf7kYy0YpZ2b0JCzJ42HZpA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.2",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-presence": "1.1.4",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "@radix-ui/react-use-previous": "1.1.1",
+ "@radix-ui/react-use-size": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-collection": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz",
+ "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-slot": "1.2.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-compose-refs": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz",
+ "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-context": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
+ "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-direction": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz",
+ "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-dismissable-layer": {
+ "version": "1.1.10",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.10.tgz",
+ "integrity": "sha512-IM1zzRV4W3HtVgftdQiiOmA0AdJlCtMLe00FXaHwgt3rAnNsIyDqshvkIW3hj/iu5hu8ERP7KIYki6NkqDxAwQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.2",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-escape-keydown": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-dropdown-menu": {
+ "version": "2.1.15",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.15.tgz",
+ "integrity": "sha512-mIBnOjgwo9AH3FyKaSWoSu/dYj6VdhJ7frEPiGTeXCdUFHjl9h3mFh2wwhEtINOmYXWhdpf1rY2minFsmaNgVQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.2",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-menu": "2.1.15",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-focus-guards": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.2.tgz",
+ "integrity": "sha512-fyjAACV62oPV925xFCrH8DR5xWhg9KYtJT4s3u54jxp+L/hbpTY2kIeEFFbFe+a/HCE94zGQMZLIpVTPVZDhaA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-focus-scope": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz",
+ "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-id": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz",
+ "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-label": {
+ "version": "2.1.7",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.7.tgz",
+ "integrity": "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.1.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu": {
+ "version": "2.1.15",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.15.tgz",
+ "integrity": "sha512-tVlmA3Vb9n8SZSd+YSbuFR66l87Wiy4du+YE+0hzKQEANA+7cWKH1WgqcEX4pXqxUFQKrWQGHdvEfw00TjFiew==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.2",
+ "@radix-ui/react-collection": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-dismissable-layer": "1.1.10",
+ "@radix-ui/react-focus-guards": "1.1.2",
+ "@radix-ui/react-focus-scope": "1.1.7",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-popper": "1.2.7",
+ "@radix-ui/react-portal": "1.1.9",
+ "@radix-ui/react-presence": "1.1.4",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-roving-focus": "1.1.10",
+ "@radix-ui/react-slot": "1.2.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "aria-hidden": "^1.2.4",
+ "react-remove-scroll": "^2.6.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-popper": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.7.tgz",
+ "integrity": "sha512-IUFAccz1JyKcf/RjB552PlWwxjeCJB8/4KxT7EhBHOJM+mN7LdW+B3kacJXILm32xawcMMjb2i0cIZpo+f9kiQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/react-dom": "^2.0.0",
+ "@radix-ui/react-arrow": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-layout-effect": "1.1.1",
+ "@radix-ui/react-use-rect": "1.1.1",
+ "@radix-ui/react-use-size": "1.1.1",
+ "@radix-ui/rect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-portal": {
+ "version": "1.1.9",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz",
+ "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-presence": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.4.tgz",
+ "integrity": "sha512-ueDqRbdc4/bkaQT3GIpLQssRlFgWaL/U2z/S31qRwwLWoxHLgry3SIfCwhxeQNbirEUXFa+lq3RL3oBYXtcmIA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-primitive": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
+ "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-slot": "1.2.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-progress": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.7.tgz",
+ "integrity": "sha512-vPdg/tF6YC/ynuBIJlk1mm7Le0VgW6ub6J2UWnTQ7/D23KXcPI1qy+0vBkgKgd38RCMJavBXpB83HPNFMTb0Fg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-radio-group": {
+ "version": "1.3.7",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.3.7.tgz",
+ "integrity": "sha512-9w5XhD0KPOrm92OTTE0SysH3sYzHsSTHNvZgUBo/VZ80VdYyB5RneDbc0dKpURS24IxkoFRu/hI0i4XyfFwY6g==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.2",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-presence": "1.1.4",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-roving-focus": "1.1.10",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "@radix-ui/react-use-previous": "1.1.1",
+ "@radix-ui/react-use-size": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-roving-focus": {
+ "version": "1.1.10",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.10.tgz",
+ "integrity": "sha512-dT9aOXUen9JSsxnMPv/0VqySQf5eDQ6LCk5Sw28kamz8wSOW2bJdlX2Bg5VUIIcV+6XlHpWTIuTPCf/UNIyq8Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.2",
+ "@radix-ui/react-collection": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-select": {
+ "version": "2.2.5",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.5.tgz",
+ "integrity": "sha512-HnMTdXEVuuyzx63ME0ut4+sEMYW6oouHWNGUZc7ddvUWIcfCva/AMoqEW/3wnEllriMWBa0RHspCYnfCWJQYmA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/number": "1.1.1",
+ "@radix-ui/primitive": "1.1.2",
+ "@radix-ui/react-collection": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-dismissable-layer": "1.1.10",
+ "@radix-ui/react-focus-guards": "1.1.2",
+ "@radix-ui/react-focus-scope": "1.1.7",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-popper": "1.2.7",
+ "@radix-ui/react-portal": "1.1.9",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-slot": "1.2.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1",
+ "@radix-ui/react-use-previous": "1.1.1",
+ "@radix-ui/react-visually-hidden": "1.2.3",
+ "aria-hidden": "^1.2.4",
+ "react-remove-scroll": "^2.6.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-slot": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-tabs": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.12.tgz",
+ "integrity": "sha512-GTVAlRVrQrSw3cEARM0nAx73ixrWDPNZAruETn3oHCNP6SbZ/hNxdxp+u7VkIEv3/sFoLq1PfcHrl7Pnp0CDpw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-presence": "1.1.4",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-roving-focus": "1.1.10",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-callback-ref": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
+ "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-controllable-state": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz",
+ "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-effect-event": "0.0.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-effect-event": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz",
+ "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-escape-keydown": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz",
+ "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-callback-ref": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-is-hydrated": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-is-hydrated/-/react-use-is-hydrated-0.1.0.tgz",
+ "integrity": "sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA==",
+ "license": "MIT",
+ "dependencies": {
+ "use-sync-external-store": "^1.5.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-layout-effect": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
+ "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-previous": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz",
+ "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-rect": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz",
+ "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/rect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-size": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz",
+ "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-visually-hidden": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz",
+ "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.1.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/rect": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz",
+ "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==",
+ "license": "MIT"
+ },
"node_modules/@rtsao/scc": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz",
@@ -1311,7 +2177,7 @@
"version": "19.1.10",
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.10.tgz",
"integrity": "sha512-EhBeSYX0Y6ye8pNebpKrwFJq7BoQ8J5SO6NlvNwwHjSj6adXJViPQrKlsyPw7hLBLvckEMO1yxeGdR82YBBlDg==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"dependencies": {
"csstype": "^3.0.2"
@@ -1321,7 +2187,7 @@
"version": "19.1.7",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.7.tgz",
"integrity": "sha512-i5ZzwYpqjmrKenzkoLM2Ibzt6mAsM7pxB6BCIouEVVmgiqaMj1TjaK7hnA36hbW5aZv20kx7Lw6hWzPWg0Rurw==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"peerDependencies": {
"@types/react": "^19.0.0"
@@ -1947,6 +2813,18 @@
"dev": true,
"license": "Python-2.0"
},
+ "node_modules/aria-hidden": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz",
+ "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/aria-query": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz",
@@ -2308,12 +3186,33 @@
"node": ">=18"
}
},
+ "node_modules/class-variance-authority": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz",
+ "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "clsx": "^2.1.1"
+ },
+ "funding": {
+ "url": "https://polar.sh/cva"
+ }
+ },
"node_modules/client-only": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
"license": "MIT"
},
+ "node_modules/clsx": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/color": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
@@ -2385,7 +3284,7 @@
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
- "dev": true,
+ "devOptional": true,
"license": "MIT"
},
"node_modules/damerau-levenshtein": {
@@ -2520,6 +3419,12 @@
"node": ">=8"
}
},
+ "node_modules/detect-node-es": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
+ "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==",
+ "license": "MIT"
+ },
"node_modules/doctrine": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
@@ -3392,6 +4297,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/get-nonce": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz",
+ "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/get-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
@@ -4492,6 +5406,15 @@
"loose-envify": "cli.js"
}
},
+ "node_modules/lucide-react": {
+ "version": "0.539.0",
+ "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.539.0.tgz",
+ "integrity": "sha512-VVISr+VF2krO91FeuCrm1rSOLACQUYVy7NQkzrOty52Y8TlTPcXcMdQFj9bYzBgXbWCiywlwSZ3Z8u6a+6bMlg==",
+ "license": "ISC",
+ "peerDependencies": {
+ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
"node_modules/magic-string": {
"version": "0.30.17",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
@@ -5096,6 +6019,75 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/react-remove-scroll": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.1.tgz",
+ "integrity": "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==",
+ "license": "MIT",
+ "dependencies": {
+ "react-remove-scroll-bar": "^2.3.7",
+ "react-style-singleton": "^2.2.3",
+ "tslib": "^2.1.0",
+ "use-callback-ref": "^1.3.3",
+ "use-sidecar": "^1.1.3"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-remove-scroll-bar": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz",
+ "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==",
+ "license": "MIT",
+ "dependencies": {
+ "react-style-singleton": "^2.2.2",
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-style-singleton": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz",
+ "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==",
+ "license": "MIT",
+ "dependencies": {
+ "get-nonce": "^1.0.0",
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
"node_modules/reflect.getprototypeof": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
@@ -5706,6 +6698,16 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/tailwind-merge": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.3.1.tgz",
+ "integrity": "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/dcastil"
+ }
+ },
"node_modules/tailwindcss": {
"version": "4.1.11",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.11.tgz",
@@ -5831,6 +6833,16 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"license": "0BSD"
},
+ "node_modules/tw-animate-css": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.3.6.tgz",
+ "integrity": "sha512-9dy0R9UsYEGmgf26L8UcHiLmSFTHa9+D7+dAt/G/sF5dCnPePZbfgDYinc7/UzAM7g/baVrmS6m9yEpU46d+LA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/Wombosvideo"
+ }
+ },
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@@ -6007,6 +7019,58 @@
"punycode": "^2.1.0"
}
},
+ "node_modules/use-callback-ref": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz",
+ "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/use-sidecar": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz",
+ "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==",
+ "license": "MIT",
+ "dependencies": {
+ "detect-node-es": "^1.1.0",
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/use-sync-external-store": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz",
+ "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
diff --git a/package.json b/package.json
index a6eaa4c..365a91b 100644
--- a/package.json
+++ b/package.json
@@ -9,19 +9,34 @@
"lint": "next lint"
},
"dependencies": {
+ "@next/font": "^14.2.15",
+ "@radix-ui/react-avatar": "^1.1.10",
+ "@radix-ui/react-checkbox": "^1.3.2",
+ "@radix-ui/react-dropdown-menu": "^2.1.15",
+ "@radix-ui/react-label": "^2.1.7",
+ "@radix-ui/react-progress": "^1.1.7",
+ "@radix-ui/react-radio-group": "^1.3.7",
+ "@radix-ui/react-select": "^2.2.5",
+ "@radix-ui/react-slot": "^1.2.3",
+ "@radix-ui/react-tabs": "^1.1.12",
+ "class-variance-authority": "^0.7.1",
+ "clsx": "^2.1.1",
+ "lucide-react": "^0.539.0",
+ "next": "15.4.6",
"react": "19.1.0",
"react-dom": "19.1.0",
- "next": "15.4.6"
+ "tailwind-merge": "^3.3.1"
},
"devDependencies": {
- "typescript": "^5",
+ "@eslint/eslintrc": "^3",
+ "@tailwindcss/postcss": "^4",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
- "@tailwindcss/postcss": "^4",
- "tailwindcss": "^4",
"eslint": "^9",
"eslint-config-next": "15.4.6",
- "@eslint/eslintrc": "^3"
+ "tailwindcss": "^4",
+ "tw-animate-css": "^1.3.6",
+ "typescript": "^5"
}
}
diff --git a/public/analytics-dashboard-preview.png b/public/analytics-dashboard-preview.png
new file mode 100644
index 0000000..2849a39
Binary files /dev/null and b/public/analytics-dashboard-preview.png differ
diff --git a/public/blog-platform-preview.png b/public/blog-platform-preview.png
new file mode 100644
index 0000000..bff95e5
Binary files /dev/null and b/public/blog-platform-preview.png differ
diff --git a/public/landing-page-preview.png b/public/landing-page-preview.png
new file mode 100644
index 0000000..42819a0
Binary files /dev/null and b/public/landing-page-preview.png differ
diff --git a/public/marketing-website-preview.png b/public/marketing-website-preview.png
new file mode 100644
index 0000000..6a1e9fd
Binary files /dev/null and b/public/marketing-website-preview.png differ
diff --git a/public/saas-platform-preview.png b/public/saas-platform-preview.png
new file mode 100644
index 0000000..9024388
Binary files /dev/null and b/public/saas-platform-preview.png differ
diff --git a/public/seo-blog-preview.png b/public/seo-blog-preview.png
new file mode 100644
index 0000000..201b123
Binary files /dev/null and b/public/seo-blog-preview.png differ
diff --git a/src/app/architecture/page.tsx b/src/app/architecture/page.tsx
new file mode 100644
index 0000000..a52d257
--- /dev/null
+++ b/src/app/architecture/page.tsx
@@ -0,0 +1,5 @@
+import ArchitectureGenerator from "@/components/architecture/architecture-generator"
+
+export default function ArchitecturePage() {
+ return
+}
\ No newline at end of file
diff --git a/src/app/auth/page.tsx b/src/app/auth/page.tsx
new file mode 100644
index 0000000..a1d510f
--- /dev/null
+++ b/src/app/auth/page.tsx
@@ -0,0 +1,5 @@
+import { AuthPage } from "@/components/auth/auth-page"
+
+export default function AuthPageRoute() {
+ return
+}
diff --git a/src/app/business-context/page.tsx b/src/app/business-context/page.tsx
new file mode 100644
index 0000000..7119ad6
--- /dev/null
+++ b/src/app/business-context/page.tsx
@@ -0,0 +1,5 @@
+import BusinessContextGenerator from "@/components/business-context/business-context-generator"
+
+export default function BusinessContextPage() {
+ return
+}
diff --git a/src/app/features/page.tsx b/src/app/features/page.tsx
new file mode 100644
index 0000000..7ea41e0
--- /dev/null
+++ b/src/app/features/page.tsx
@@ -0,0 +1,5 @@
+import { FeaturesPage } from "@/components/features/features-page"
+
+export default function FeaturesPageRoute() {
+ return
+}
diff --git a/src/app/globals.css b/src/app/globals.css
index a2dc41e..dc98be7 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -1,26 +1,122 @@
@import "tailwindcss";
+@import "tw-animate-css";
-:root {
- --background: #ffffff;
- --foreground: #171717;
-}
+@custom-variant dark (&:is(.dark *));
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
+ --color-sidebar-ring: var(--sidebar-ring);
+ --color-sidebar-border: var(--sidebar-border);
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
+ --color-sidebar-accent: var(--sidebar-accent);
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
+ --color-sidebar-primary: var(--sidebar-primary);
+ --color-sidebar-foreground: var(--sidebar-foreground);
+ --color-sidebar: var(--sidebar);
+ --color-chart-5: var(--chart-5);
+ --color-chart-4: var(--chart-4);
+ --color-chart-3: var(--chart-3);
+ --color-chart-2: var(--chart-2);
+ --color-chart-1: var(--chart-1);
+ --color-ring: var(--ring);
+ --color-input: var(--input);
+ --color-border: var(--border);
+ --color-destructive: var(--destructive);
+ --color-accent-foreground: var(--accent-foreground);
+ --color-accent: var(--accent);
+ --color-muted-foreground: var(--muted-foreground);
+ --color-muted: var(--muted);
+ --color-secondary-foreground: var(--secondary-foreground);
+ --color-secondary: var(--secondary);
+ --color-primary-foreground: var(--primary-foreground);
+ --color-primary: var(--primary);
+ --color-popover-foreground: var(--popover-foreground);
+ --color-popover: var(--popover);
+ --color-card-foreground: var(--card-foreground);
+ --color-card: var(--card);
+ --radius-sm: calc(var(--radius) - 4px);
+ --radius-md: calc(var(--radius) - 2px);
+ --radius-lg: var(--radius);
+ --radius-xl: calc(var(--radius) + 4px);
}
-@media (prefers-color-scheme: dark) {
- :root {
- --background: #0a0a0a;
- --foreground: #ededed;
+:root {
+ --radius: 0.625rem;
+ --background: oklch(1 0 0);
+ --foreground: oklch(0.145 0 0);
+ --card: oklch(1 0 0);
+ --card-foreground: oklch(0.145 0 0);
+ --popover: oklch(1 0 0);
+ --popover-foreground: oklch(0.145 0 0);
+ --primary: oklch(0.205 0 0);
+ --primary-foreground: oklch(0.985 0 0);
+ --secondary: oklch(0.97 0 0);
+ --secondary-foreground: oklch(0.205 0 0);
+ --muted: oklch(0.97 0 0);
+ --muted-foreground: oklch(0.556 0 0);
+ --accent: oklch(0.97 0 0);
+ --accent-foreground: oklch(0.205 0 0);
+ --destructive: oklch(0.577 0.245 27.325);
+ --border: oklch(0.922 0 0);
+ --input: oklch(0.922 0 0);
+ --ring: oklch(0.708 0 0);
+ --chart-1: oklch(0.646 0.222 41.116);
+ --chart-2: oklch(0.6 0.118 184.704);
+ --chart-3: oklch(0.398 0.07 227.392);
+ --chart-4: oklch(0.828 0.189 84.429);
+ --chart-5: oklch(0.769 0.188 70.08);
+ --sidebar: oklch(0.985 0 0);
+ --sidebar-foreground: oklch(0.145 0 0);
+ --sidebar-primary: oklch(0.205 0 0);
+ --sidebar-primary-foreground: oklch(0.985 0 0);
+ --sidebar-accent: oklch(0.97 0 0);
+ --sidebar-accent-foreground: oklch(0.205 0 0);
+ --sidebar-border: oklch(0.922 0 0);
+ --sidebar-ring: oklch(0.708 0 0);
+}
+
+.dark {
+ --background: oklch(0.145 0 0);
+ --foreground: oklch(0.985 0 0);
+ --card: oklch(0.205 0 0);
+ --card-foreground: oklch(0.985 0 0);
+ --popover: oklch(0.205 0 0);
+ --popover-foreground: oklch(0.985 0 0);
+ --primary: oklch(0.922 0 0);
+ --primary-foreground: oklch(0.205 0 0);
+ --secondary: oklch(0.269 0 0);
+ --secondary-foreground: oklch(0.985 0 0);
+ --muted: oklch(0.269 0 0);
+ --muted-foreground: oklch(0.708 0 0);
+ --accent: oklch(0.269 0 0);
+ --accent-foreground: oklch(0.985 0 0);
+ --destructive: oklch(0.704 0.191 22.216);
+ --border: oklch(1 0 0 / 10%);
+ --input: oklch(1 0 0 / 15%);
+ --ring: oklch(0.556 0 0);
+ --chart-1: oklch(0.488 0.243 264.376);
+ --chart-2: oklch(0.696 0.17 162.48);
+ --chart-3: oklch(0.769 0.188 70.08);
+ --chart-4: oklch(0.627 0.265 303.9);
+ --chart-5: oklch(0.645 0.246 16.439);
+ --sidebar: oklch(0.205 0 0);
+ --sidebar-foreground: oklch(0.985 0 0);
+ --sidebar-primary: oklch(0.488 0.243 264.376);
+ --sidebar-primary-foreground: oklch(0.985 0 0);
+ --sidebar-accent: oklch(0.269 0 0);
+ --sidebar-accent-foreground: oklch(0.985 0 0);
+ --sidebar-border: oklch(1 0 0 / 10%);
+ --sidebar-ring: oklch(0.556 0 0);
+}
+
+@layer base {
+ * {
+ @apply border-border outline-ring/50;
+ }
+ body {
+ @apply bg-background text-foreground;
}
}
-
-body {
- background: var(--background);
- color: var(--foreground);
- font-family: Arial, Helvetica, sans-serif;
-}
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index f7fa87e..49d20d1 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -1,34 +1,44 @@
-import type { Metadata } from "next";
-import { Geist, Geist_Mono } from "next/font/google";
-import "./globals.css";
+import type React from "react"
+import type { Metadata } from "next"
+import { Poppins } from "next/font/google"
+import { AuthProvider } from "@/contexts/auth-context"
+import { AppLayout } from "@/components/layout/app-layout"
+import "./globals.css"
-const geistSans = Geist({
- variable: "--font-geist-sans",
+const poppins = Poppins({
subsets: ["latin"],
-});
-
-const geistMono = Geist_Mono({
- variable: "--font-geist-mono",
- subsets: ["latin"],
-});
+ weight: ["300", "400", "500", "600", "700"],
+ variable: "--font-poppins",
+})
export const metadata: Metadata = {
- title: "Create Next App",
- description: "Generated by create next app",
-};
+ title: "Codenuk - AI-Powered Project Builder",
+ description: "Build scalable applications with AI-generated architecture and code",
+ generator: "v0.dev",
+}
export default function RootLayout({
children,
}: Readonly<{
- children: React.ReactNode;
+ children: React.ReactNode
}>) {
return (
-
- {children}
+
+
+
+
+
+
+ {children}
+
+
- );
+ )
}
diff --git a/src/app/page.tsx b/src/app/page.tsx
index a932894..ba374ff 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -1,103 +1,5 @@
-import Image from "next/image";
+import { redirect } from "next/navigation"
-export default function Home() {
- return (
-
-
-
-
- -
- Get started by editing{" "}
-
- src/app/page.tsx
-
- .
-
- -
- Save and see your changes instantly.
-
-
-
-
-
-
-
- );
+export default function HomePage() {
+ redirect("/project-builder")
}
diff --git a/src/app/project-builder/page.tsx b/src/app/project-builder/page.tsx
new file mode 100644
index 0000000..46beb18
--- /dev/null
+++ b/src/app/project-builder/page.tsx
@@ -0,0 +1,10 @@
+import { Suspense } from "react"
+import { MainDashboard } from "@/components/main-dashboard"
+
+export default function ProjectBuilderPage() {
+ return (
+ Loading...}>
+
+
+ )
+}
diff --git a/src/app/templates/page.tsx b/src/app/templates/page.tsx
new file mode 100644
index 0000000..48910c9
--- /dev/null
+++ b/src/app/templates/page.tsx
@@ -0,0 +1,5 @@
+import { TemplatesPage } from "@/components/templates/template-page"
+
+export default function TemplatesPageRoute() {
+ return
+}
diff --git a/src/components/architecture/architecture-generator.tsx b/src/components/architecture/architecture-generator.tsx
new file mode 100644
index 0000000..fbb15f1
--- /dev/null
+++ b/src/components/architecture/architecture-generator.tsx
@@ -0,0 +1,191 @@
+"use client"
+
+import { useState } from "react"
+import { Button } from "@/components/ui/button"
+import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
+import { Badge } from "@/components/ui/badge"
+import { Input } from "@/components/ui/input"
+import { Code, Database, Server, Shield, Zap, Layers, GitBranch } from "lucide-react"
+
+export default function ArchitectureGenerator() {
+ const [selectedArchitecture, setSelectedArchitecture] = useState("")
+ const [projectName, setProjectName] = useState("")
+
+ const architecturePatterns = [
+ {
+ id: "monolithic",
+ name: "Monolithic Architecture",
+ description: "Single application with all components tightly coupled",
+ icon: Layers,
+ complexity: "Low",
+ bestFor: "Small to medium projects",
+ pros: ["Simple to develop", "Easy to deploy", "Lower initial cost"],
+ cons: ["Harder to scale", "Technology lock-in", "Difficult to maintain"],
+ },
+ {
+ id: "microservices",
+ name: "Microservices Architecture",
+ description: "Loosely coupled services that can be developed and deployed independently",
+ icon: GitBranch,
+ complexity: "High",
+ bestFor: "Large, complex applications",
+ pros: ["Independent scaling", "Technology diversity", "Easier maintenance"],
+ cons: ["Distributed complexity", "Network overhead", "Data consistency challenges"],
+ },
+ {
+ id: "serverless",
+ name: "Serverless Architecture",
+ description: "Event-driven, auto-scaling functions without server management",
+ icon: Zap,
+ complexity: "Medium",
+ bestFor: "Event-driven applications",
+ pros: ["Auto-scaling", "Pay-per-use", "No server management"],
+ cons: ["Cold start latency", "Vendor lock-in", "Limited execution time"],
+ },
+ {
+ id: "layered",
+ name: "Layered Architecture",
+ description: "Separation of concerns with distinct layers for different responsibilities",
+ icon: Database,
+ complexity: "Medium",
+ bestFor: "Business applications",
+ pros: ["Clear separation", "Easy to test", "Maintainable"],
+ cons: ["Performance overhead", "Tight coupling between layers"],
+ },
+ ]
+
+ const generateArchitecture = () => {
+ if (!selectedArchitecture || !projectName) return
+
+ // Here you would typically call an API to generate the architecture
+ console.log(`Generating ${selectedArchitecture} architecture for ${projectName}`)
+ }
+
+ return (
+
+
+ {/* Header */}
+
+
Architecture Generator
+
+ Generate optimal architecture patterns for your project based on requirements and scale
+
+
+
+ {/* Project Name Input */}
+
+
+ setProjectName(e.target.value)}
+ className="text-center"
+ />
+
+
+ {/* Architecture Patterns */}
+
+ {architecturePatterns.map((pattern) => {
+ const Icon = pattern.icon
+ return (
+
setSelectedArchitecture(pattern.id)}
+ >
+
+
+
+
+ {pattern.name}
+
+ {pattern.complexity} Complexity
+
+
+
+ {pattern.description}
+
+
Best for:
+
{pattern.bestFor}
+
+
+
+ )
+ })}
+
+
+ {/* Generate Button */}
+
+
+
+
+ {/* Selected Architecture Details */}
+ {selectedArchitecture && (
+
+
+
+
+
+ Architecture Details
+
+
+
+ {(() => {
+ const pattern = architecturePatterns.find(p => p.id === selectedArchitecture)
+ if (!pattern) return null
+
+ return (
+
+
+
+
+ Advantages
+
+
+ {pattern.pros.map((pro, index) => (
+ -
+
+ {pro}
+
+ ))}
+
+
+
+
+
+ Considerations
+
+
+ {pattern.cons.map((con, index) => (
+ -
+
+ {con}
+
+ ))}
+
+
+
+ )
+ })()}
+
+
+
+ )}
+
+
+ )
+}
diff --git a/src/components/auth/auth-page.tsx b/src/components/auth/auth-page.tsx
new file mode 100644
index 0000000..5b23341
--- /dev/null
+++ b/src/components/auth/auth-page.tsx
@@ -0,0 +1,25 @@
+"use client"
+
+import { useState } from "react"
+import { SignInForm } from "./signin-form"
+import { SignUpForm } from "./signup-form"
+
+export function AuthPage() {
+ const [isSignIn, setIsSignIn] = useState(true)
+
+ return (
+
+
+
+
Codenuk
+
AI-Powered Project Builder
+
+ {isSignIn ? (
+
setIsSignIn(false)} />
+ ) : (
+ setIsSignIn(true)} />
+ )}
+
+
+ )
+}
diff --git a/src/components/auth/signin-form.tsx b/src/components/auth/signin-form.tsx
new file mode 100644
index 0000000..27314bd
--- /dev/null
+++ b/src/components/auth/signin-form.tsx
@@ -0,0 +1,117 @@
+"use client"
+
+import type React from "react"
+
+import { useState } from "react"
+import { useRouter } from "next/navigation"
+import { Button } from "@/components/ui/button"
+import { Input } from "@/components/ui/input"
+import { Label } from "@/components/ui/label"
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
+import { Eye, EyeOff, Loader2 } from "lucide-react"
+import { useAuth } from "@/contexts/auth-context"
+
+interface SignInFormProps {
+ onToggleMode: () => void
+}
+
+export function SignInForm({ onToggleMode }: SignInFormProps) {
+ const [showPassword, setShowPassword] = useState(false)
+ const [isLoading, setIsLoading] = useState(false)
+ const [error, setError] = useState("")
+ const [formData, setFormData] = useState({
+ email: "",
+ password: "",
+ })
+
+ const { login } = useAuth()
+ const router = useRouter()
+
+ const handleSubmit = async (e: React.FormEvent) => {
+ e.preventDefault()
+ setError("")
+ setIsLoading(true)
+
+ try {
+ const success = await login(formData.email, formData.password)
+ if (success) {
+ router.push("/")
+ } else {
+ setError("Invalid email or password")
+ }
+ } catch (err) {
+ setError("An error occurred. Please try again.")
+ } finally {
+ setIsLoading(false)
+ }
+ }
+
+ return (
+
+
+ Sign In
+ Enter your credentials to access your account
+
+
+
+
+
+ )
+}
diff --git a/src/components/auth/signup-form.tsx b/src/components/auth/signup-form.tsx
new file mode 100644
index 0000000..5f052fe
--- /dev/null
+++ b/src/components/auth/signup-form.tsx
@@ -0,0 +1,159 @@
+"use client"
+
+import type React from "react"
+
+import { useState } from "react"
+import { useRouter } from "next/navigation"
+import { Button } from "@/components/ui/button"
+import { Input } from "@/components/ui/input"
+import { Label } from "@/components/ui/label"
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
+import { Eye, EyeOff, Loader2 } from "lucide-react"
+import { useAuth } from "@/contexts/auth-context"
+
+interface SignUpFormProps {
+ onToggleMode: () => void
+}
+
+export function SignUpForm({ onToggleMode }: SignUpFormProps) {
+ const [showPassword, setShowPassword] = useState(false)
+ const [showConfirmPassword, setShowConfirmPassword] = useState(false)
+ const [isLoading, setIsLoading] = useState(false)
+ const [error, setError] = useState("")
+ const [formData, setFormData] = useState({
+ name: "",
+ email: "",
+ password: "",
+ confirmPassword: "",
+ })
+
+ const { signup } = useAuth()
+ const router = useRouter()
+
+ const handleSubmit = async (e: React.FormEvent) => {
+ e.preventDefault()
+ setError("")
+
+ if (formData.password !== formData.confirmPassword) {
+ setError("Passwords don't match")
+ return
+ }
+
+ setIsLoading(true)
+
+ try {
+ const success = await signup(formData.name, formData.email, formData.password)
+ if (success) {
+ router.push("/")
+ } else {
+ setError("Failed to create account. Please try again.")
+ }
+ } catch (err) {
+ setError("An error occurred. Please try again.")
+ } finally {
+ setIsLoading(false)
+ }
+ }
+
+ return (
+
+
+ Sign Up
+ Create your account to get started
+
+
+
+
+
+ )
+}
diff --git a/src/components/business-context/business-context-generator.tsx b/src/components/business-context/business-context-generator.tsx
new file mode 100644
index 0000000..7c616b6
--- /dev/null
+++ b/src/components/business-context/business-context-generator.tsx
@@ -0,0 +1,546 @@
+"use client"
+
+import React from "react"
+
+import { useState } from "react"
+import { Button } from "@/components/ui/button"
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
+import { Label } from "@/components/ui/label"
+import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
+import { Checkbox } from "@/components/ui/checkbox"
+import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
+import { Progress } from "@/components/ui/progress"
+import { Badge } from "@/components/ui/badge"
+import { Users, Server, DollarSign, Shield } from "lucide-react"
+
+interface BusinessContext {
+ userScale: {
+ expectedUsers: string
+ growthRate: string
+ peakTraffic: string
+ globalReach: boolean
+ }
+ technical: {
+ performance: string
+ availability: string
+ security: string[]
+ integrations: string[]
+ }
+ business: {
+ model: string
+ revenue: string
+ budget: string
+ timeline: string
+ }
+ operational: {
+ team: string
+ maintenance: string
+ monitoring: string[]
+ compliance: string[]
+ }
+}
+
+export default function BusinessContextGenerator() {
+ const [currentSection, setCurrentSection] = useState(0)
+ const [context, setContext] = useState({
+ userScale: {
+ expectedUsers: "",
+ growthRate: "",
+ peakTraffic: "",
+ globalReach: false,
+ },
+ technical: {
+ performance: "",
+ availability: "",
+ security: [],
+ integrations: [],
+ },
+ business: {
+ model: "",
+ revenue: "",
+ budget: "",
+ timeline: "",
+ },
+ operational: {
+ team: "",
+ maintenance: "",
+ monitoring: [],
+ compliance: [],
+ },
+ })
+
+ const sections = [
+ { title: "User Scale & Growth", icon: Users, color: "bg-blue-500" },
+ { title: "Technical Requirements", icon: Server, color: "bg-green-500" },
+ { title: "Business Model", icon: DollarSign, color: "bg-purple-500" },
+ { title: "Operational Context", icon: Shield, color: "bg-orange-500" },
+ ]
+
+ const progress = ((currentSection + 1) / sections.length) * 100
+
+ const updateContext = (section: keyof BusinessContext, field: string, value: any) => {
+ setContext((prev) => ({
+ ...prev,
+ [section]: {
+ ...prev[section],
+ [field]: value,
+ },
+ }))
+ }
+
+ const toggleArrayValue = (section: keyof BusinessContext, field: string, value: string) => {
+ setContext((prev) => {
+ const currentArray = (prev[section] as any)[field] || []
+ const newArray = currentArray.includes(value)
+ ? currentArray.filter((item: string) => item !== value)
+ : [...currentArray, value]
+
+ return {
+ ...prev,
+ [section]: {
+ ...prev[section],
+ [field]: newArray,
+ },
+ }
+ })
+ }
+
+ const renderUserScaleSection = () => (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ updateContext("userScale", "globalReach", checked)}
+ />
+
+
+
+ )
+
+ const renderTechnicalSection = () => (
+
+
+
+
updateContext("technical", "performance", value)}
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
updateContext("technical", "availability", value)}
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {[
+ "Authentication",
+ "Authorization",
+ "Data Encryption",
+ "GDPR Compliance",
+ "SOC2 Compliance",
+ "PCI Compliance",
+ ].map((security) => (
+
+ toggleArrayValue("technical", "security", security)}
+ />
+
+
+ ))}
+
+
+
+
+
+
+ {[
+ "Payment Processing",
+ "Email Service",
+ "SMS Service",
+ "Analytics",
+ "CRM",
+ "Social Media",
+ "File Storage",
+ "CDN",
+ ].map((integration) => (
+
+ toggleArrayValue("technical", "integrations", integration)}
+ />
+
+
+ ))}
+
+
+
+ )
+
+ const renderBusinessSection = () => (
+
+
+
+
updateContext("business", "model", value)}>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+
+ const renderOperationalSection = () => (
+
+
+
+
updateContext("operational", "team", value)}
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
updateContext("operational", "maintenance", value)}
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {[
+ "Error Tracking",
+ "Performance Monitoring",
+ "User Analytics",
+ "Security Monitoring",
+ "Uptime Monitoring",
+ "Log Management",
+ ].map((monitoring) => (
+
+ toggleArrayValue("operational", "monitoring", monitoring)}
+ />
+
+
+ ))}
+
+
+
+
+
+
+ {["GDPR", "CCPA", "HIPAA", "SOX", "PCI DSS", "ISO 27001"].map((compliance) => (
+
+ toggleArrayValue("operational", "compliance", compliance)}
+ />
+
+
+ ))}
+
+
+
+ )
+
+ const renderSection = () => {
+ switch (currentSection) {
+ case 0:
+ return renderUserScaleSection()
+ case 1:
+ return renderTechnicalSection()
+ case 2:
+ return renderBusinessSection()
+ case 3:
+ return renderOperationalSection()
+ default:
+ return null
+ }
+ }
+
+ return (
+
+
+
+
Business Context Generator
+
+ Help us understand your business requirements to generate the perfect architecture
+
+
+
+
+
+ Progress
+
+ {currentSection + 1} of {sections.length}
+
+
+
+
+
+
+ {sections.map((section, index) => {
+ const Icon = section.icon
+ return (
+
setCurrentSection(index)}
+ >
+
+
+
+
+ {section.title}
+ {index < currentSection && (
+
+ Completed
+
+ )}
+ {index === currentSection && Current}
+
+
+ )
+ })}
+
+
+
+
+
+ {React.createElement(sections[currentSection].icon, { className: "w-5 h-5" })}
+ {sections[currentSection].title}
+
+
+ {currentSection === 0 && "Define your expected user base and growth patterns"}
+ {currentSection === 1 && "Specify technical performance and security requirements"}
+ {currentSection === 2 && "Outline your business model and financial expectations"}
+ {currentSection === 3 && "Configure operational and compliance requirements"}
+
+
+ {renderSection()}
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/src/components/features/features-page.tsx b/src/components/features/features-page.tsx
new file mode 100644
index 0000000..039f5f5
--- /dev/null
+++ b/src/components/features/features-page.tsx
@@ -0,0 +1,684 @@
+"use client"
+
+import type React from "react"
+
+import { useState, useRef } from "react"
+import Link from "next/link"
+import { Button } from "@/components/ui/button"
+import { Input } from "@/components/ui/input"
+import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
+import { Badge } from "@/components/ui/badge"
+import {
+ Search,
+ Plus,
+ Trash2,
+ GripVertical,
+ Database,
+ Shield,
+ CreditCard,
+ BarChart3,
+ Bell,
+ Mail,
+ Globe,
+ Smartphone,
+ Zap,
+ Settings,
+ FileText,
+ ImageIcon,
+ Video,
+ MessageSquare,
+ Star,
+ Code,
+ Palette,
+ Layers,
+ Save,
+ Download,
+} from "lucide-react"
+import { ArrowRight } from "lucide-react" // Added import for ArrowRight
+
+interface Feature {
+ id: string
+ name: string
+ description: string
+ category: string
+ icon: any
+ complexity: number
+ timeImpact: string
+ dependencies: string[]
+ conflicts: string[]
+ techStack: string[]
+ businessQuestions: string[]
+ isCore?: boolean
+ isPopular?: boolean
+}
+
+interface SelectedFeature extends Feature {
+ order: number
+ customConfig?: any
+}
+
+export function FeaturesPage() {
+ const [activeTab, setActiveTab] = useState("browse")
+ const [selectedCategory, setSelectedCategory] = useState("all")
+ const [searchQuery, setSearchQuery] = useState("")
+ const [selectedFeatures, setSelectedFeatures] = useState([])
+ const [draggedFeature, setDraggedFeature] = useState(null)
+ const [dragOverIndex, setDragOverIndex] = useState(null)
+ const dropZoneRef = useRef(null)
+
+ const features: Feature[] = [
+ // Core Features
+ {
+ id: "user-auth",
+ name: "User Authentication",
+ description: "Secure user registration, login, and session management",
+ category: "core",
+ icon: Shield,
+ complexity: 3,
+ timeImpact: "2-3 days",
+ dependencies: [],
+ conflicts: [],
+ techStack: ["NextAuth.js", "JWT", "OAuth"],
+ businessQuestions: [
+ "How many users do you expect in the first year?",
+ "Do you need social login (Google, Facebook)?",
+ "Will you have different user roles?",
+ ],
+ isCore: true,
+ isPopular: true,
+ },
+ {
+ id: "database",
+ name: "Database Integration",
+ description: "Data storage and management system",
+ category: "core",
+ icon: Database,
+ complexity: 4,
+ timeImpact: "3-5 days",
+ dependencies: [],
+ conflicts: [],
+ techStack: ["PostgreSQL", "Prisma", "Redis"],
+ businessQuestions: [
+ "What's your expected data volume?",
+ "Do you need real-time data updates?",
+ "What's your data backup strategy?",
+ ],
+ isCore: true,
+ isPopular: true,
+ },
+ {
+ id: "api-management",
+ name: "API Management",
+ description: "RESTful API with rate limiting and documentation",
+ category: "core",
+ icon: Code,
+ complexity: 3,
+ timeImpact: "2-4 days",
+ dependencies: ["database"],
+ conflicts: [],
+ techStack: ["Next.js API Routes", "Swagger", "Rate Limiting"],
+ businessQuestions: [
+ "Will you have external API integrations?",
+ "Do you need API versioning?",
+ "What's your expected API call volume?",
+ ],
+ isCore: true,
+ },
+
+ // Business Features
+ {
+ id: "payment-processing",
+ name: "Payment Processing",
+ description: "Secure payment handling with multiple providers",
+ category: "business",
+ icon: CreditCard,
+ complexity: 5,
+ timeImpact: "1-2 weeks",
+ dependencies: ["user-auth", "database"],
+ conflicts: [],
+ techStack: ["Stripe", "PayPal", "Webhook Handling"],
+ businessQuestions: [
+ "What payment methods do you need?",
+ "What's your expected transaction volume?",
+ "Do you need subscription billing?",
+ ],
+ isPopular: true,
+ },
+ {
+ id: "analytics",
+ name: "Analytics & Tracking",
+ description: "User behavior tracking and business metrics",
+ category: "business",
+ icon: BarChart3,
+ complexity: 3,
+ timeImpact: "2-3 days",
+ dependencies: [],
+ conflicts: [],
+ techStack: ["Google Analytics", "Mixpanel", "Custom Events"],
+ businessQuestions: [
+ "What metrics are most important to track?",
+ "Do you need real-time analytics?",
+ "What's your privacy policy regarding data?",
+ ],
+ isPopular: true,
+ },
+ {
+ id: "notifications",
+ name: "Notification System",
+ description: "Email, SMS, and push notifications",
+ category: "business",
+ icon: Bell,
+ complexity: 4,
+ timeImpact: "3-5 days",
+ dependencies: ["user-auth"],
+ conflicts: [],
+ techStack: ["SendGrid", "Twilio", "Push API"],
+ businessQuestions: [
+ "What types of notifications do you need?",
+ "How frequently will you send notifications?",
+ "Do you need notification preferences?",
+ ],
+ },
+
+ // UI/UX Features
+ {
+ id: "responsive-design",
+ name: "Responsive Design",
+ description: "Mobile-first responsive layout",
+ category: "ui",
+ icon: Smartphone,
+ complexity: 2,
+ timeImpact: "1-2 days",
+ dependencies: [],
+ conflicts: [],
+ techStack: ["Tailwind CSS", "CSS Grid", "Flexbox"],
+ businessQuestions: ["What devices will your users primarily use?", "Do you need a mobile app later?"],
+ isCore: true,
+ },
+ {
+ id: "dark-mode",
+ name: "Dark Mode",
+ description: "Toggle between light and dark themes",
+ category: "ui",
+ icon: Palette,
+ complexity: 2,
+ timeImpact: "1 day",
+ dependencies: ["responsive-design"],
+ conflicts: [],
+ techStack: ["CSS Variables", "Theme Provider"],
+ businessQuestions: ["Is this important for your user base?"],
+ },
+ {
+ id: "animations",
+ name: "Animations & Transitions",
+ description: "Smooth animations and micro-interactions",
+ category: "ui",
+ icon: Zap,
+ complexity: 3,
+ timeImpact: "2-3 days",
+ dependencies: ["responsive-design"],
+ conflicts: [],
+ techStack: ["Framer Motion", "CSS Animations"],
+ businessQuestions: ["What's your performance priority?"],
+ },
+
+ // Content Features
+ {
+ id: "content-management",
+ name: "Content Management",
+ description: "CMS for managing dynamic content",
+ category: "content",
+ icon: FileText,
+ complexity: 4,
+ timeImpact: "1 week",
+ dependencies: ["database"],
+ conflicts: [],
+ techStack: ["Sanity", "Strapi", "MDX"],
+ businessQuestions: ["Who will manage content?", "How often will content change?"],
+ },
+ {
+ id: "media-upload",
+ name: "Media Upload",
+ description: "File and image upload with optimization",
+ category: "content",
+ icon: ImageIcon, // Updated from Image to ImageIcon
+ complexity: 3,
+ timeImpact: "2-3 days",
+ dependencies: ["database"],
+ conflicts: [],
+ techStack: ["Cloudinary", "AWS S3", "Image Optimization"],
+ businessQuestions: ["What file types do you need?", "What's your storage budget?"],
+ },
+ {
+ id: "video-streaming",
+ name: "Video Streaming",
+ description: "Video upload and streaming capabilities",
+ category: "content",
+ icon: Video,
+ complexity: 5,
+ timeImpact: "1-2 weeks",
+ dependencies: ["media-upload"],
+ conflicts: [],
+ techStack: ["Vimeo API", "YouTube API", "Video.js"],
+ businessQuestions: ["What video quality do you need?", "Expected video volume?"],
+ },
+
+ // Communication Features
+ {
+ id: "chat-system",
+ name: "Real-time Chat",
+ description: "Live messaging and communication",
+ category: "communication",
+ icon: MessageSquare,
+ complexity: 4,
+ timeImpact: "1 week",
+ dependencies: ["user-auth", "database"],
+ conflicts: [],
+ techStack: ["WebSockets", "Socket.io", "Real-time DB"],
+ businessQuestions: ["How many concurrent users?", "Do you need group chats?"],
+ },
+ {
+ id: "email-integration",
+ name: "Email Integration",
+ description: "Email sending and template management",
+ category: "communication",
+ icon: Mail,
+ complexity: 3,
+ timeImpact: "2-3 days",
+ dependencies: [],
+ conflicts: [],
+ techStack: ["SendGrid", "Mailgun", "Email Templates"],
+ businessQuestions: ["What types of emails will you send?", "Expected email volume?"],
+ },
+
+ // Advanced Features
+ {
+ id: "ai-integration",
+ name: "AI Integration",
+ description: "Machine learning and AI-powered features",
+ category: "advanced",
+ icon: Layers,
+ complexity: 5,
+ timeImpact: "1-3 weeks",
+ dependencies: ["api-management"],
+ conflicts: [],
+ techStack: ["OpenAI API", "TensorFlow", "Custom Models"],
+ businessQuestions: ["What AI capabilities do you need?", "What's your AI budget?", "Do you have training data?"],
+ },
+ {
+ id: "real-time",
+ name: "Real-time Features",
+ description: "Live updates and collaboration",
+ category: "advanced",
+ icon: Zap,
+ complexity: 4,
+ timeImpact: "1 week",
+ dependencies: ["database"],
+ conflicts: [],
+ techStack: ["WebSockets", "Socket.io", "Redis Pub/Sub"],
+ businessQuestions: ["How many concurrent users?", "What needs to be real-time?"],
+ },
+ ]
+
+ const categories = [
+ { id: "all", name: "All Features", icon: Globe, count: features.length },
+ { id: "core", name: "Core", icon: Settings, count: features.filter((f) => f.category === "core").length },
+ {
+ id: "business",
+ name: "Business",
+ icon: BarChart3,
+ count: features.filter((f) => f.category === "business").length,
+ },
+ { id: "ui", name: "UI/UX", icon: Palette, count: features.filter((f) => f.category === "ui").length },
+ { id: "content", name: "Content", icon: FileText, count: features.filter((f) => f.category === "content").length },
+ {
+ id: "communication",
+ name: "Communication",
+ icon: MessageSquare,
+ count: features.filter((f) => f.category === "communication").length,
+ },
+ {
+ id: "advanced",
+ name: "Advanced",
+ icon: Layers,
+ count: features.filter((f) => f.category === "advanced").length,
+ },
+ ]
+
+ const filteredFeatures = features.filter((feature) => {
+ const matchesCategory = selectedCategory === "all" || feature.category === selectedCategory
+ const matchesSearch =
+ feature.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
+ feature.description.toLowerCase().includes(searchQuery.toLowerCase())
+ const notAlreadySelected = !selectedFeatures.some((sf) => sf.id === feature.id)
+ return matchesCategory && matchesSearch && notAlreadySelected
+ })
+
+ const getComplexityColor = (complexity: number) => {
+ if (complexity <= 2) return "bg-green-100 text-green-800"
+ if (complexity <= 3) return "bg-yellow-100 text-yellow-800"
+ return "bg-red-100 text-red-800"
+ }
+
+ const getComplexityLabel = (complexity: number) => {
+ if (complexity <= 2) return "Simple"
+ if (complexity <= 3) return "Moderate"
+ return "Complex"
+ }
+
+ const handleDragStart = (feature: Feature) => {
+ setDraggedFeature(feature)
+ }
+
+ const handleDragOver = (e: React.DragEvent, index?: number) => {
+ e.preventDefault()
+ if (typeof index === "number") {
+ setDragOverIndex(index)
+ }
+ }
+
+ const handleDrop = (e: React.DragEvent, index?: number) => {
+ e.preventDefault()
+ if (!draggedFeature) return
+
+ const newFeature: SelectedFeature = {
+ ...draggedFeature,
+ order: typeof index === "number" ? index : selectedFeatures.length,
+ }
+
+ if (typeof index === "number") {
+ const newFeatures = [...selectedFeatures]
+ newFeatures.splice(index, 0, newFeature)
+ // Update order for all features
+ newFeatures.forEach((f, i) => (f.order = i))
+ setSelectedFeatures(newFeatures)
+ } else {
+ setSelectedFeatures([...selectedFeatures, newFeature])
+ }
+
+ setDraggedFeature(null)
+ setDragOverIndex(null)
+ }
+
+ const removeFeature = (featureId: string) => {
+ setSelectedFeatures(selectedFeatures.filter((f) => f.id !== featureId))
+ }
+
+ const reorderFeatures = (fromIndex: number, toIndex: number) => {
+ const newFeatures = [...selectedFeatures]
+ const [movedFeature] = newFeatures.splice(fromIndex, 1)
+ newFeatures.splice(toIndex, 0, movedFeature)
+ // Update order for all features
+ newFeatures.forEach((f, i) => (f.order = i))
+ setSelectedFeatures(newFeatures)
+ }
+
+ const calculateTotalComplexity = () => {
+ return selectedFeatures.reduce((total, feature) => total + feature.complexity, 0)
+ }
+
+ const calculateEstimatedTime = () => {
+ const totalDays = selectedFeatures.reduce((total, feature) => {
+ const days = feature.timeImpact.match(/(\d+)/g)?.map(Number) || [1]
+ return total + Math.max(...days)
+ }, 0)
+
+ if (totalDays < 7) return `${totalDays} days`
+ if (totalDays < 30) return `${Math.ceil(totalDays / 7)} weeks`
+ return `${Math.ceil(totalDays / 30)} months`
+ }
+
+ const FeatureCard = ({ feature, isDraggable = true }: { feature: Feature; isDraggable?: boolean }) => {
+ const Icon = feature.icon
+ return (
+ isDraggable && handleDragStart(feature)}
+ >
+
+
+
+
+
+
+
+
{feature.name}
+
+
+ {getComplexityLabel(feature.complexity)}
+
+ {feature.isCore && Core}
+ {feature.isPopular && (
+
+
+ Popular
+
+ )}
+
+
+
+ {isDraggable &&
}
+
+ {feature.description}
+
+
+
+
+ Time Impact: {feature.timeImpact}
+ Complexity: {feature.complexity}/5
+
+
+
+
Tech Stack:
+
+ {feature.techStack.slice(0, 3).map((tech, index) => (
+
+ {tech}
+
+ ))}
+ {feature.techStack.length > 3 && (
+
+ +{feature.techStack.length - 3}
+
+ )}
+
+
+
+ {feature.dependencies.length > 0 && (
+
+ Dependencies:
+
+ {feature.dependencies
+ .map((depId) => {
+ const dep = features.find((f) => f.id === depId)
+ return dep?.name
+ })
+ .join(", ")}
+
+
+ )}
+
+
+ )
+ }
+
+ const SelectedFeatureCard = ({ feature, index }: { feature: SelectedFeature; index: number }) => {
+ const Icon = feature.icon
+ return (
+ handleDragStart(feature)}
+ onDragOver={(e) => handleDragOver(e, index)}
+ onDrop={(e) => handleDrop(e, index)}
+ >
+
+
+
+
+
+
+
+
+
{feature.name}
+
{feature.timeImpact}
+
+
+
+ {feature.complexity}
+
+
+
+
+
+ )
+ }
+
+ return (
+
+
+
+
+ {/* Features Library */}
+
+
+
Features Library
+
+
+
+ setSearchQuery(e.target.value)}
+ className="pl-10 w-80"
+ />
+
+
+
+
+ {/* Category Filters */}
+
+ {categories.map((category) => {
+ const Icon = category.icon
+ return (
+
+ )
+ })}
+
+
+ {/* Features Grid */}
+
+ {filteredFeatures.map((feature) => (
+
+ ))}
+
+
+
+ {/* Selected Features Panel */}
+
+
+
+
+ Selected Features
+ {selectedFeatures.length}
+
+ Drag features here to build your project
+
+
+ {/* Project Summary */}
+
+
+ Total Complexity:
+ 20
+ ? "destructive"
+ : calculateTotalComplexity() > 15
+ ? "default"
+ : "secondary"
+ }
+ >
+ {calculateTotalComplexity()}/50
+
+
+
+ Estimated Time:
+ {calculateEstimatedTime()}
+
+
+
+ {/* Drop Zone */}
+
+ {selectedFeatures.length === 0 ? (
+
+
+
+ Drag features from the library to start building your project
+
+
+ ) : (
+
+ {selectedFeatures
+ .sort((a, b) => a.order - b.order)
+ .map((feature, index) => (
+
+ ))}
+
+ )}
+
+
+ {/* Actions */}
+ {selectedFeatures.length > 0 && (
+
+
+
+
+ )}
+
+
+
+
+
+
+ )
+}
diff --git a/src/components/layout/app-layout.tsx b/src/components/layout/app-layout.tsx
new file mode 100644
index 0000000..511211d
--- /dev/null
+++ b/src/components/layout/app-layout.tsx
@@ -0,0 +1,49 @@
+"use client"
+
+import { useAuth } from "@/contexts/auth-context"
+import Header from "@/components/navigation/header"
+import { usePathname } from "next/navigation"
+
+interface AppLayoutProps {
+ children: React.ReactNode
+}
+
+export function AppLayout({ children }: AppLayoutProps) {
+ const { isAuthenticated, isLoading } = useAuth()
+ const pathname = usePathname()
+
+ // Don't show header on auth pages
+ const isAuthPage = pathname === "/auth"
+
+ // Show loading state while checking auth
+ if (isLoading) {
+ return (
+
+ )
+ }
+
+ // For auth pages, don't show header
+ if (isAuthPage) {
+ return <>{children}>
+ }
+
+ // For authenticated users on other pages, show header
+ if (isAuthenticated) {
+ return (
+ <>
+
+ {children}
+ >
+ )
+ }
+
+ // For unauthenticated users on non-auth pages, redirect to auth
+ return (
+ <>
+
+ {children}
+ >
+ )
+}
diff --git a/src/components/main-dashboard.tsx b/src/components/main-dashboard.tsx
new file mode 100644
index 0000000..472a05f
--- /dev/null
+++ b/src/components/main-dashboard.tsx
@@ -0,0 +1,806 @@
+"use client"
+
+import { useState } from "react"
+import Link from "next/link"
+import { Button } from "@/components/ui/button"
+import { Input } from "@/components/ui/input"
+import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
+import { Badge } from "@/components/ui/badge"
+import { ArrowRight, Plus, Globe, BarChart3, Zap, Code, Search, Star, Clock, Users, Layers } from "lucide-react"
+
+interface Template {
+ id: string
+ title: string
+ description: string
+ category: string
+ features: string[]
+ complexity: number
+ timeEstimate: string
+ techStack: string[]
+ popularity?: number
+ lastUpdated?: string
+}
+
+function TemplateSelectionStep({ onNext }: { onNext: (template: Template) => void }) {
+ const [selectedCategory, setSelectedCategory] = useState("all")
+ const [searchQuery, setSearchQuery] = useState("")
+
+ const templates: Template[] = [
+ // Marketing Templates (10)
+ {
+ id: "marketing-website",
+ title: "Marketing Website",
+ description: "Professional marketing site with CMS and lead generation",
+ category: "marketing",
+ features: ["Content Management", "Contact Forms", "SEO Optimization", "Analytics Integration"],
+ complexity: 2,
+ timeEstimate: "1-2 weeks",
+ techStack: ["Next.js", "Sanity CMS", "Tailwind CSS", "Vercel"],
+ popularity: 95,
+ lastUpdated: "2024-01-15",
+ },
+ {
+ id: "landing-page",
+ title: "Landing Page",
+ description: "High-converting landing page with A/B testing capabilities",
+ category: "marketing",
+ features: ["A/B Testing", "Conversion Tracking", "Lead Capture", "Mobile Optimization"],
+ complexity: 2,
+ timeEstimate: "3-5 days",
+ techStack: ["Next.js", "Tailwind CSS", "Google Analytics", "Mailchimp"],
+ popularity: 88,
+ lastUpdated: "2024-01-10",
+ },
+ {
+ id: "blog-platform",
+ title: "Blog Platform",
+ description: "Content-rich blog with SEO optimization and social sharing",
+ category: "marketing",
+ features: ["Content Management", "SEO Tools", "Social Sharing", "Comment System"],
+ complexity: 3,
+ timeEstimate: "1-2 weeks",
+ techStack: ["Next.js", "MDX", "Tailwind CSS", "Disqus"],
+ popularity: 82,
+ lastUpdated: "2024-01-12",
+ },
+ {
+ id: "portfolio-site",
+ title: "Portfolio Website",
+ description: "Personal or agency portfolio with project showcase",
+ category: "marketing",
+ features: ["Project Gallery", "Contact Forms", "Blog", "Responsive Design"],
+ complexity: 2,
+ timeEstimate: "1-2 weeks",
+ techStack: ["Next.js", "MDX", "Tailwind CSS", "Framer Motion"],
+ popularity: 79,
+ lastUpdated: "2024-01-08",
+ },
+ {
+ id: "agency-website",
+ title: "Agency Website",
+ description: "Full-service agency site with team profiles and case studies",
+ category: "marketing",
+ features: ["Team Profiles", "Case Studies", "Service Pages", "Client Testimonials"],
+ complexity: 3,
+ timeEstimate: "2-3 weeks",
+ techStack: ["Next.js", "Strapi", "Tailwind CSS", "Framer Motion"],
+ popularity: 76,
+ lastUpdated: "2024-01-14",
+ },
+ {
+ id: "event-website",
+ title: "Event Website",
+ description: "Event promotion site with registration and ticketing",
+ category: "marketing",
+ features: ["Event Registration", "Ticketing", "Speaker Profiles", "Schedule Management"],
+ complexity: 4,
+ timeEstimate: "2-3 weeks",
+ techStack: ["Next.js", "Stripe", "Calendar API", "Email Integration"],
+ popularity: 73,
+ lastUpdated: "2024-01-11",
+ },
+ {
+ id: "restaurant-website",
+ title: "Restaurant Website",
+ description: "Restaurant site with menu, reservations, and online ordering",
+ category: "marketing",
+ features: ["Menu Display", "Online Reservations", "Order System", "Location Info"],
+ complexity: 3,
+ timeEstimate: "1-2 weeks",
+ techStack: ["Next.js", "Reservation API", "Payment Processing", "Google Maps"],
+ popularity: 70,
+ lastUpdated: "2024-01-09",
+ },
+ {
+ id: "nonprofit-website",
+ title: "Nonprofit Website",
+ description: "Nonprofit organization site with donation and volunteer management",
+ category: "marketing",
+ features: ["Donation Processing", "Volunteer Registration", "Event Management", "Impact Tracking"],
+ complexity: 3,
+ timeEstimate: "2-3 weeks",
+ techStack: ["Next.js", "Stripe", "Volunteer API", "Analytics"],
+ popularity: 67,
+ lastUpdated: "2024-01-13",
+ },
+ {
+ id: "real-estate-website",
+ title: "Real Estate Website",
+ description: "Property listing site with search and contact features",
+ category: "marketing",
+ features: ["Property Listings", "Search Filters", "Contact Forms", "Virtual Tours"],
+ complexity: 4,
+ timeEstimate: "2-4 weeks",
+ techStack: ["Next.js", "Property API", "Map Integration", "Image Gallery"],
+ popularity: 64,
+ lastUpdated: "2024-01-07",
+ },
+ {
+ id: "personal-brand",
+ title: "Personal Brand Site",
+ description: "Personal branding site for professionals and creators",
+ category: "marketing",
+ features: ["About Page", "Services", "Testimonials", "Contact Integration"],
+ complexity: 2,
+ timeEstimate: "1 week",
+ techStack: ["Next.js", "Tailwind CSS", "Contact Forms", "Social Links"],
+ popularity: 61,
+ lastUpdated: "2024-01-06",
+ },
+
+ // Software Templates (10)
+ {
+ id: "saas-platform",
+ title: "SaaS Platform",
+ description: "Complete SaaS application with user management, billing, and analytics",
+ category: "software",
+ features: ["User Authentication", "Payment Processing", "Analytics Integration", "API Management"],
+ complexity: 5,
+ timeEstimate: "4-6 weeks",
+ techStack: ["Next.js", "PostgreSQL", "Stripe", "NextAuth.js"],
+ popularity: 92,
+ lastUpdated: "2024-01-15",
+ },
+ {
+ id: "dashboard-app",
+ title: "Analytics Dashboard",
+ description: "Data visualization dashboard with real-time updates",
+ category: "software",
+ features: ["Data Visualization", "Real-time Updates", "User Authentication", "Export Features"],
+ complexity: 4,
+ timeEstimate: "3-4 weeks",
+ techStack: ["Next.js", "Chart.js", "WebSockets", "PostgreSQL"],
+ popularity: 89,
+ lastUpdated: "2024-01-14",
+ },
+ {
+ id: "mobile-app",
+ title: "Mobile App (PWA)",
+ description: "Progressive web app with mobile-first design",
+ category: "software",
+ features: ["Offline Support", "Push Notifications", "Mobile Optimization", "App Install"],
+ complexity: 4,
+ timeEstimate: "2-3 weeks",
+ techStack: ["Next.js", "PWA", "Service Workers", "Push API"],
+ popularity: 86,
+ lastUpdated: "2024-01-13",
+ },
+ {
+ id: "project-management",
+ title: "Project Management Tool",
+ description: "Team collaboration and project tracking application",
+ category: "software",
+ features: ["Task Management", "Team Collaboration", "Time Tracking", "Reporting"],
+ complexity: 5,
+ timeEstimate: "4-5 weeks",
+ techStack: ["Next.js", "PostgreSQL", "Real-time Updates", "File Upload"],
+ popularity: 83,
+ lastUpdated: "2024-01-12",
+ },
+ {
+ id: "crm-system",
+ title: "CRM System",
+ description: "Customer relationship management with sales pipeline",
+ category: "software",
+ features: ["Contact Management", "Sales Pipeline", "Email Integration", "Reporting"],
+ complexity: 5,
+ timeEstimate: "3-5 weeks",
+ techStack: ["Next.js", "PostgreSQL", "Email API", "Calendar Integration"],
+ popularity: 80,
+ lastUpdated: "2024-01-11",
+ },
+ {
+ id: "inventory-management",
+ title: "Inventory Management",
+ description: "Stock tracking and warehouse management system",
+ category: "software",
+ features: ["Stock Tracking", "Barcode Scanning", "Supplier Management", "Reports"],
+ complexity: 4,
+ timeEstimate: "3-4 weeks",
+ techStack: ["Next.js", "PostgreSQL", "Barcode API", "PDF Generation"],
+ popularity: 77,
+ lastUpdated: "2024-01-10",
+ },
+ {
+ id: "learning-platform",
+ title: "Learning Management System",
+ description: "Online education platform with courses and assessments",
+ category: "software",
+ features: ["Course Management", "Video Streaming", "Assessments", "Progress Tracking"],
+ complexity: 5,
+ timeEstimate: "4-6 weeks",
+ techStack: ["Next.js", "Video API", "PostgreSQL", "Payment Processing"],
+ popularity: 74,
+ lastUpdated: "2024-01-09",
+ },
+ {
+ id: "booking-system",
+ title: "Booking System",
+ description: "Appointment and reservation management platform",
+ category: "software",
+ features: ["Calendar Integration", "Payment Processing", "Notifications", "Customer Management"],
+ complexity: 4,
+ timeEstimate: "2-4 weeks",
+ techStack: ["Next.js", "Calendar API", "Stripe", "Email Integration"],
+ popularity: 71,
+ lastUpdated: "2024-01-08",
+ },
+ {
+ id: "chat-application",
+ title: "Chat Application",
+ description: "Real-time messaging platform with file sharing",
+ category: "software",
+ features: ["Real-time Messaging", "File Sharing", "Group Chats", "User Presence"],
+ complexity: 4,
+ timeEstimate: "2-3 weeks",
+ techStack: ["Next.js", "WebSockets", "File Storage", "Real-time DB"],
+ popularity: 68,
+ lastUpdated: "2024-01-07",
+ },
+ {
+ id: "api-platform",
+ title: "API Platform",
+ description: "RESTful API with documentation and rate limiting",
+ category: "software",
+ features: ["API Documentation", "Rate Limiting", "Authentication", "Monitoring"],
+ complexity: 4,
+ timeEstimate: "2-3 weeks",
+ techStack: ["Next.js", "Swagger", "Redis", "Monitoring Tools"],
+ popularity: 65,
+ lastUpdated: "2024-01-06",
+ },
+
+ // SEO Templates (10)
+ {
+ id: "seo-optimized-blog",
+ title: "SEO-Optimized Blog",
+ description: "Blog platform with advanced SEO features and schema markup",
+ category: "seo",
+ features: ["Schema Markup", "Meta Optimization", "Sitemap Generation", "Performance Optimization"],
+ complexity: 3,
+ timeEstimate: "2-3 weeks",
+ techStack: ["Next.js", "SEO Tools", "Schema.org", "Google Search Console"],
+ popularity: 90,
+ lastUpdated: "2024-01-15",
+ },
+ {
+ id: "local-business-site",
+ title: "Local Business Website",
+ description: "Local SEO optimized site with Google My Business integration",
+ category: "seo",
+ features: ["Local SEO", "Google My Business", "Review Management", "Location Pages"],
+ complexity: 3,
+ timeEstimate: "1-2 weeks",
+ techStack: ["Next.js", "Google APIs", "Review APIs", "Local Schema"],
+ popularity: 87,
+ lastUpdated: "2024-01-14",
+ },
+ {
+ id: "ecommerce-seo",
+ title: "E-commerce SEO Site",
+ description: "Product-focused e-commerce with advanced SEO optimization",
+ category: "seo",
+ features: ["Product Schema", "Category Optimization", "Review Rich Snippets", "Performance"],
+ complexity: 4,
+ timeEstimate: "3-4 weeks",
+ techStack: ["Next.js", "Product APIs", "Review Systems", "CDN"],
+ popularity: 84,
+ lastUpdated: "2024-01-13",
+ },
+ {
+ id: "news-website",
+ title: "News Website",
+ description: "News platform with article SEO and AMP support",
+ category: "seo",
+ features: ["Article Schema", "AMP Support", "Breaking News", "Social Sharing"],
+ complexity: 4,
+ timeEstimate: "2-4 weeks",
+ techStack: ["Next.js", "AMP", "News APIs", "Social APIs"],
+ popularity: 81,
+ lastUpdated: "2024-01-12",
+ },
+ {
+ id: "directory-website",
+ title: "Business Directory",
+ description: "Local business directory with search and listings",
+ category: "seo",
+ features: ["Business Listings", "Search Optimization", "Category Pages", "Review System"],
+ complexity: 4,
+ timeEstimate: "3-4 weeks",
+ techStack: ["Next.js", "Search APIs", "Location Services", "Review APIs"],
+ popularity: 78,
+ lastUpdated: "2024-01-11",
+ },
+ {
+ id: "recipe-website",
+ title: "Recipe Website",
+ description: "Recipe platform with rich snippets and cooking schema",
+ category: "seo",
+ features: ["Recipe Schema", "Nutrition Info", "Cooking Times", "User Ratings"],
+ complexity: 3,
+ timeEstimate: "2-3 weeks",
+ techStack: ["Next.js", "Recipe APIs", "Nutrition APIs", "Rating System"],
+ popularity: 75,
+ lastUpdated: "2024-01-10",
+ },
+ {
+ id: "job-board",
+ title: "Job Board",
+ description: "Job listing platform with structured data for search engines",
+ category: "seo",
+ features: ["Job Schema", "Search Filters", "Application Tracking", "Company Profiles"],
+ complexity: 4,
+ timeEstimate: "3-4 weeks",
+ techStack: ["Next.js", "Job APIs", "Application System", "Company APIs"],
+ popularity: 72,
+ lastUpdated: "2024-01-09",
+ },
+ {
+ id: "review-website",
+ title: "Review Website",
+ description: "Product/service review platform with rich snippets",
+ category: "seo",
+ features: ["Review Schema", "Rating System", "Comparison Tools", "User Profiles"],
+ complexity: 4,
+ timeEstimate: "2-4 weeks",
+ techStack: ["Next.js", "Review APIs", "Rating System", "Comparison Tools"],
+ popularity: 69,
+ lastUpdated: "2024-01-08",
+ },
+ {
+ id: "travel-website",
+ title: "Travel Website",
+ description: "Travel guide with location-based SEO and booking integration",
+ category: "seo",
+ features: ["Location Schema", "Travel Guides", "Booking Integration", "Photo Galleries"],
+ complexity: 4,
+ timeEstimate: "3-4 weeks",
+ techStack: ["Next.js", "Travel APIs", "Booking APIs", "Map Integration"],
+ popularity: 66,
+ lastUpdated: "2024-01-07",
+ },
+ {
+ id: "healthcare-website",
+ title: "Healthcare Website",
+ description: "Medical practice website with health-focused SEO",
+ category: "seo",
+ features: ["Medical Schema", "Appointment Booking", "Health Articles", "Doctor Profiles"],
+ complexity: 3,
+ timeEstimate: "2-3 weeks",
+ techStack: ["Next.js", "Medical APIs", "Booking System", "Content Management"],
+ popularity: 63,
+ lastUpdated: "2024-01-06",
+ },
+ ]
+
+ const categories = [
+ { id: "all", name: "All Templates", icon: Globe, count: templates.length },
+ {
+ id: "marketing",
+ name: "Marketing & Branding",
+ icon: Zap,
+ count: templates.filter((t) => t.category === "marketing").length,
+ },
+ {
+ id: "software",
+ name: "Software & Tools",
+ icon: Code,
+ count: templates.filter((t) => t.category === "software").length,
+ },
+ { id: "seo", name: "SEO & Content", icon: BarChart3, count: templates.filter((t) => t.category === "seo").length },
+ ]
+
+ const filteredTemplates = templates.filter((template) => {
+ const matchesCategory = selectedCategory === "all" || template.category === selectedCategory
+ const matchesSearch =
+ template.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
+ template.description.toLowerCase().includes(searchQuery.toLowerCase()) ||
+ template.features.some((feature) => feature.toLowerCase().includes(searchQuery.toLowerCase()))
+ return matchesCategory && matchesSearch
+ })
+
+ const getComplexityColor = (complexity: number) => {
+ if (complexity <= 2) return "bg-green-100 text-green-800"
+ if (complexity <= 3) return "bg-yellow-100 text-yellow-800"
+ return "bg-red-100 text-red-800"
+ }
+
+ const getComplexityLabel = (complexity: number) => {
+ if (complexity <= 2) return "Simple"
+ if (complexity <= 3) return "Moderate"
+ return "Complex"
+ }
+
+ return (
+
+ {/* Header */}
+
+
Choose Your Project Template
+
+ Select from our comprehensive library of professionally designed templates
+
+
+
+ {/* Search and Filter */}
+
+
+
+ setSearchQuery(e.target.value)}
+ className="pl-10 h-12 text-lg border-2 border-gray-200 hover:border-blue-300 focus:border-blue-500 focus:ring-2 focus:ring-blue-200 rounded-xl shadow-sm transition-all duration-300"
+ />
+
+
+ {/* Category Filters */}
+
+ {categories.map((category) => {
+ const Icon = category.icon
+ return (
+
+ )
+ })}
+
+
+
+ {/* Templates Grid */}
+
+ {filteredTemplates.map((template) => (
+
+ {/* Card Header with gradient background */}
+
+
+
+
+ {template.title}
+
+
+
+ {getComplexityLabel(template.complexity)}
+
+ {template.popularity && (
+
+
+ {template.popularity}%
+
+ )}
+
+
+
+
{template.description}
+
+
+
+
+ {/* Stats Row */}
+
+
+
+ {template.timeEstimate}
+
+
+
+ {template.features.length} features
+
+
+
+ {/* Features Section */}
+
+
+
+
+ Key Features
+
+
+ {template.features.slice(0, 3).map((feature, index) => (
+
+ {feature}
+
+ ))}
+ {template.features.length > 3 && (
+
+ +{template.features.length - 3} more
+
+ )}
+
+
+
+ {/* Tech Stack Section */}
+
+
+
+ Tech Stack
+
+
+ {template.techStack.slice(0, 3).map((tech, index) => (
+
+ {tech}
+
+ ))}
+ {template.techStack.length > 3 && (
+
+ +{template.techStack.length - 3}
+
+ )}
+
+
+
+
+
+ {/* Action Button - Always at bottom */}
+
+
+
+
+
+ ))}
+
+
+ {/* Custom Template Option */}
+
+
+
+ Create Custom Template
+
+ Don't see what you need? Create a custom project type with your specific requirements and tech stack.
+
+
+
+
+
+ {/* Results Summary */}
+ {searchQuery && (
+
+
+ Showing {filteredTemplates.length} template{filteredTemplates.length !== 1 ? "s" : ""}
+ {searchQuery && ` matching "${searchQuery}"`}
+
+
+ )}
+
+ )
+}
+
+// Feature Selection Step Component
+function FeatureSelectionStep({
+ template,
+ onNext,
+ onBack,
+}: { template: Template; onNext: () => void; onBack: () => void }) {
+ return (
+
+ {/* Header */}
+
+
Select Features for {template.title}
+
+ Choose the features that best fit your project requirements.
+
+
+
+ {/* Features List */}
+
+ {template.features.map((feature, index) => (
+
+
+
+ {feature}
+
+
+
+
+
+ This feature enhances your project with {feature} capabilities.
+
+
+
+ ))}
+
+
+ {/* Navigation Buttons */}
+
+
+
+
+
+
+
+ )
+}
+
+// Main Dashboard Component
+export function MainDashboard() {
+ const [currentStep, setCurrentStep] = useState(1)
+ const [selectedTemplate, setSelectedTemplate] = useState(null)
+
+ const steps = [
+ { id: 1, name: "Project Type", description: "Choose template" },
+ { id: 2, name: "Features", description: "Select features" },
+ { id: 3, name: "Business Context", description: "Define requirements" },
+ { id: 4, name: "Generate", description: "Create project" },
+ { id: 5, name: "Architecture", description: "Review & deploy" },
+ ]
+
+ const renderStep = () => {
+ switch (currentStep) {
+ case 1:
+ return (
+ {
+ setSelectedTemplate(template)
+ setCurrentStep(2)
+ }}
+ />
+ )
+ case 2:
+ return selectedTemplate ? (
+ setCurrentStep(3)}
+ onBack={() => setCurrentStep(1)}
+ />
+ ) : null
+ case 3:
+ return (
+
+
Business Context Step
+
Coming soon - Define your business requirements and scaling needs
+
+
+
+
+
+ )
+ case 4:
+ return (
+
+
Generate Step
+
Coming soon - Generate your project architecture and code
+
+
+
+
+
+ )
+ case 5:
+ return (
+
+
Architecture Step
+
Coming soon - Review architecture and deploy your project
+
+
+
+
+
+ )
+ default:
+ return null
+ }
+ }
+
+ return (
+
+
+ {/* Progress Steps */}
+
+
+
+
+
+
+
+
+ {/* Main Content */}
+
+ {renderStep()}
+
+
+ )
+}
\ No newline at end of file
diff --git a/src/components/navigation/header.tsx b/src/components/navigation/header.tsx
new file mode 100644
index 0000000..98aeb5b
--- /dev/null
+++ b/src/components/navigation/header.tsx
@@ -0,0 +1,152 @@
+"use client"
+
+import { useState } from "react"
+import Link from "next/link"
+import { usePathname } from "next/navigation"
+import { Button } from "@/components/ui/button"
+import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuLabel,
+ DropdownMenuSeparator,
+ DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu"
+import { Badge } from "@/components/ui/badge"
+import { Bell, Settings, LogOut, User, Menu, X } from "lucide-react"
+import { useAuth } from "@/contexts/auth-context"
+
+const navigation = [
+ { name: "Project Builder", href: "/", current: false },
+ { name: "Templates", href: "/templates", current: false },
+ { name: "Features", href: "/features", current: false },
+ { name: "Business Context", href: "/business-context", current: false },
+ { name: "Architecture", href: "/architecture", current: false },
+]
+
+export default function Header() {
+ const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
+ const pathname = usePathname()
+ const { user, logout } = useAuth()
+
+ return (
+
+ )
+}
diff --git a/src/components/templates/template-page.tsx b/src/components/templates/template-page.tsx
new file mode 100644
index 0000000..3b085a6
--- /dev/null
+++ b/src/components/templates/template-page.tsx
@@ -0,0 +1,414 @@
+"use client"
+
+import { useState } from "react"
+import Link from "next/link"
+import Image from "next/image"
+import { Button } from "@/components/ui/button"
+import { Input } from "@/components/ui/input"
+import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
+import { Badge } from "@/components/ui/badge"
+import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
+import {
+ Search,
+ Star,
+ Clock,
+ Plus,
+ Copy,
+ Globe,
+ BarChart3,
+ Zap,
+ Code,
+ ArrowRight,
+ Download,
+ Eye,
+ Heart,
+ Share2,
+} from "lucide-react"
+
+interface Template {
+ id: string
+ title: string
+ description: string
+ category: string
+ features: string[]
+ complexity: number
+ timeEstimate: string
+ techStack: string[]
+ popularity?: number
+ lastUpdated?: string
+ downloads?: number
+ likes?: number
+ author?: string
+ isPublic?: boolean
+ preview?: string
+}
+
+export function TemplatesPage() {
+ const [activeTab, setActiveTab] = useState("browse")
+ const [selectedCategory, setSelectedCategory] = useState("all")
+ const [searchQuery, setSearchQuery] = useState("")
+ const [sortBy, setSortBy] = useState("popularity")
+
+ const templates: Template[] = [
+ // Marketing Templates
+ {
+ id: "marketing-website",
+ title: "Marketing Website",
+ description: "Professional marketing site with CMS and lead generation",
+ category: "marketing",
+ features: ["Content Management", "Contact Forms", "SEO Optimization", "Analytics Integration"],
+ complexity: 2,
+ timeEstimate: "1-2 weeks",
+ techStack: ["Next.js", "Sanity CMS", "Tailwind CSS", "Vercel"],
+ popularity: 95,
+ lastUpdated: "2024-01-15",
+ downloads: 1250,
+ likes: 89,
+ author: "Codenuk Team",
+ isPublic: true,
+ preview: "/marketing-website-preview.png",
+ },
+ {
+ id: "landing-page",
+ title: "Landing Page",
+ description: "High-converting landing page with A/B testing capabilities",
+ category: "marketing",
+ features: ["A/B Testing", "Conversion Tracking", "Lead Capture", "Mobile Optimization"],
+ complexity: 2,
+ timeEstimate: "3-5 days",
+ techStack: ["Next.js", "Tailwind CSS", "Google Analytics", "Mailchimp"],
+ popularity: 88,
+ lastUpdated: "2024-01-10",
+ downloads: 980,
+ likes: 76,
+ author: "Codenuk Team",
+ isPublic: true,
+ preview: "/landing-page-preview.png",
+ },
+ {
+ id: "blog-platform",
+ title: "Blog Platform",
+ description: "Content-rich blog with SEO optimization and social sharing",
+ category: "marketing",
+ features: ["Content Management", "SEO Tools", "Social Sharing", "Comment System"],
+ complexity: 3,
+ timeEstimate: "1-2 weeks",
+ techStack: ["Next.js", "MDX", "Tailwind CSS", "Disqus"],
+ popularity: 82,
+ lastUpdated: "2024-01-12",
+ downloads: 756,
+ likes: 64,
+ author: "Community",
+ isPublic: true,
+ preview: "/blog-platform-preview.png",
+ },
+ // Software Templates
+ {
+ id: "saas-platform",
+ title: "SaaS Platform",
+ description: "Complete SaaS application with user management, billing, and analytics",
+ category: "software",
+ features: ["User Authentication", "Payment Processing", "Analytics Integration", "API Management"],
+ complexity: 5,
+ timeEstimate: "4-6 weeks",
+ techStack: ["Next.js", "PostgreSQL", "Stripe", "NextAuth.js"],
+ popularity: 92,
+ lastUpdated: "2024-01-15",
+ downloads: 2100,
+ likes: 156,
+ author: "Codenuk Team",
+ isPublic: true,
+ preview: "/saas-platform-preview.png",
+ },
+ {
+ id: "dashboard-app",
+ title: "Analytics Dashboard",
+ description: "Data visualization dashboard with real-time updates",
+ category: "software",
+ features: ["Data Visualization", "Real-time Updates", "User Authentication", "Export Features"],
+ complexity: 4,
+ timeEstimate: "3-4 weeks",
+ techStack: ["Next.js", "Chart.js", "WebSockets", "PostgreSQL"],
+ popularity: 89,
+ lastUpdated: "2024-01-14",
+ downloads: 1890,
+ likes: 134,
+ author: "Community",
+ isPublic: true,
+ preview: "/analytics-dashboard-preview.png",
+ },
+ // SEO Templates
+ {
+ id: "seo-optimized-blog",
+ title: "SEO-Optimized Blog",
+ description: "Blog platform with advanced SEO features and schema markup",
+ category: "seo",
+ features: ["Schema Markup", "Meta Optimization", "Sitemap Generation", "Performance Optimization"],
+ complexity: 3,
+ timeEstimate: "2-3 weeks",
+ techStack: ["Next.js", "SEO Tools", "Schema.org", "Google Search Console"],
+ popularity: 90,
+ lastUpdated: "2024-01-15",
+ downloads: 1456,
+ likes: 98,
+ author: "SEO Expert",
+ isPublic: true,
+ preview: "/seo-blog-preview.png",
+ },
+ ]
+
+ const categories = [
+ { id: "all", name: "All Templates", icon: Globe, count: templates.length },
+ {
+ id: "marketing",
+ name: "Marketing",
+ icon: Zap,
+ count: templates.filter((t) => t.category === "marketing").length,
+ },
+ { id: "software", name: "Software", icon: Code, count: templates.filter((t) => t.category === "software").length },
+ { id: "seo", name: "SEO", icon: BarChart3, count: templates.filter((t) => t.category === "seo").length },
+ ]
+
+ const filteredTemplates = templates.filter((template) => {
+ const matchesCategory = selectedCategory === "all" || template.category === selectedCategory
+ const matchesSearch =
+ template.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
+ template.description.toLowerCase().includes(searchQuery.toLowerCase()) ||
+ template.features.some((feature) => feature.toLowerCase().includes(searchQuery.toLowerCase()))
+ return matchesCategory && matchesSearch
+ })
+
+ const sortedTemplates = [...filteredTemplates].sort((a, b) => {
+ switch (sortBy) {
+ case "popularity":
+ return (b.popularity || 0) - (a.popularity || 0)
+ case "downloads":
+ return (b.downloads || 0) - (a.downloads || 0)
+ case "recent":
+ return new Date(b.lastUpdated || "").getTime() - new Date(a.lastUpdated || "").getTime()
+ case "likes":
+ return (b.likes || 0) - (a.likes || 0)
+ default:
+ return 0
+ }
+ })
+
+ const getComplexityColor = (complexity: number) => {
+ if (complexity <= 2) return "bg-green-100 text-green-800"
+ if (complexity <= 3) return "bg-yellow-100 text-yellow-800"
+ return "bg-red-100 text-red-800"
+ }
+
+ const getComplexityLabel = (complexity: number) => {
+ if (complexity <= 2) return "Simple"
+ if (complexity <= 3) return "Moderate"
+ return "Complex"
+ }
+
+ const TemplateCard = ({ template }: { template: Template }) => (
+
+
+
+
+
+
+
{template.title}
+
+
+ {getComplexityLabel(template.complexity)}
+
+
+
+ {template.popularity}%
+
+
+
+
+ {template.description}
+
+
+
+
+
+
+ {template.timeEstimate}
+
+
+
+ {template.downloads}
+
+
+
+
+
+
Features:
+
+ {template.features.slice(0, 2).map((feature, index) => (
+
+ {feature}
+
+ ))}
+ {template.features.length > 2 && (
+
+ +{template.features.length - 2} more
+
+ )}
+
+
+
+
+
Tech Stack:
+
+ {template.techStack.slice(0, 3).map((tech, index) => (
+
+ {tech}
+
+ ))}
+
+
+
+
+
+
+
+
+
+
+
+ by {template.author}
+ {template.lastUpdated}
+
+
+
+ )
+
+ return (
+
+
+
+
+
+
+ Browse Templates
+ My Templates
+ Favorites
+
+
+
+
+
+ setSearchQuery(e.target.value)}
+ className="pl-10 w-80"
+ />
+
+
+
+
+
+
+ {/* Category Filters */}
+
+ {categories.map((category) => {
+ const Icon = category.icon
+ return (
+
+ )
+ })}
+
+
+ {/* Templates Grid */}
+
+ {sortedTemplates.map((template) => (
+
+ ))}
+
+
+ {/* Results Summary */}
+
+
+ Showing {sortedTemplates.length} template{sortedTemplates.length !== 1 ? "s" : ""}
+ {searchQuery && ` matching "${searchQuery}"`}
+
+
+
+
+
+
+
+
No Templates Yet
+
+ Create your first template to get started. Templates you create will appear here.
+
+
+
+
+
+
+
+
+
No Favorites Yet
+
+ Heart templates you like to save them here for quick access later.
+
+
+
+
+
+
+
+ )
+}
diff --git a/src/components/ui/avatar.tsx b/src/components/ui/avatar.tsx
new file mode 100644
index 0000000..71e428b
--- /dev/null
+++ b/src/components/ui/avatar.tsx
@@ -0,0 +1,53 @@
+"use client"
+
+import * as React from "react"
+import * as AvatarPrimitive from "@radix-ui/react-avatar"
+
+import { cn } from "@/lib/utils"
+
+function Avatar({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+function AvatarImage({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+function AvatarFallback({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+export { Avatar, AvatarImage, AvatarFallback }
diff --git a/src/components/ui/badge.tsx b/src/components/ui/badge.tsx
new file mode 100644
index 0000000..0205413
--- /dev/null
+++ b/src/components/ui/badge.tsx
@@ -0,0 +1,46 @@
+import * as React from "react"
+import { Slot } from "@radix-ui/react-slot"
+import { cva, type VariantProps } from "class-variance-authority"
+
+import { cn } from "@/lib/utils"
+
+const badgeVariants = cva(
+ "inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
+ {
+ variants: {
+ variant: {
+ default:
+ "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
+ secondary:
+ "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
+ destructive:
+ "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
+ outline:
+ "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ },
+ }
+)
+
+function Badge({
+ className,
+ variant,
+ asChild = false,
+ ...props
+}: React.ComponentProps<"span"> &
+ VariantProps & { asChild?: boolean }) {
+ const Comp = asChild ? Slot : "span"
+
+ return (
+
+ )
+}
+
+export { Badge, badgeVariants }
diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx
new file mode 100644
index 0000000..a2df8dc
--- /dev/null
+++ b/src/components/ui/button.tsx
@@ -0,0 +1,59 @@
+import * as React from "react"
+import { Slot } from "@radix-ui/react-slot"
+import { cva, type VariantProps } from "class-variance-authority"
+
+import { cn } from "@/lib/utils"
+
+const buttonVariants = cva(
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
+ {
+ variants: {
+ variant: {
+ default:
+ "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
+ destructive:
+ "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
+ outline:
+ "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
+ secondary:
+ "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
+ ghost:
+ "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
+ link: "text-primary underline-offset-4 hover:underline",
+ },
+ size: {
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
+ sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
+ icon: "size-9",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ size: "default",
+ },
+ }
+)
+
+function Button({
+ className,
+ variant,
+ size,
+ asChild = false,
+ ...props
+}: React.ComponentProps<"button"> &
+ VariantProps & {
+ asChild?: boolean
+ }) {
+ const Comp = asChild ? Slot : "button"
+
+ return (
+
+ )
+}
+
+export { Button, buttonVariants }
diff --git a/src/components/ui/card.tsx b/src/components/ui/card.tsx
new file mode 100644
index 0000000..d05bbc6
--- /dev/null
+++ b/src/components/ui/card.tsx
@@ -0,0 +1,92 @@
+import * as React from "react"
+
+import { cn } from "@/lib/utils"
+
+function Card({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+function CardAction({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+function CardContent({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+export {
+ Card,
+ CardHeader,
+ CardFooter,
+ CardTitle,
+ CardAction,
+ CardDescription,
+ CardContent,
+}
diff --git a/src/components/ui/checkbox.tsx b/src/components/ui/checkbox.tsx
new file mode 100644
index 0000000..fa0e4b5
--- /dev/null
+++ b/src/components/ui/checkbox.tsx
@@ -0,0 +1,32 @@
+"use client"
+
+import * as React from "react"
+import * as CheckboxPrimitive from "@radix-ui/react-checkbox"
+import { CheckIcon } from "lucide-react"
+
+import { cn } from "@/lib/utils"
+
+function Checkbox({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
+
+
+
+ )
+}
+
+export { Checkbox }
diff --git a/src/components/ui/dropdown-menu.tsx b/src/components/ui/dropdown-menu.tsx
new file mode 100644
index 0000000..ec51e9c
--- /dev/null
+++ b/src/components/ui/dropdown-menu.tsx
@@ -0,0 +1,257 @@
+"use client"
+
+import * as React from "react"
+import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
+import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"
+
+import { cn } from "@/lib/utils"
+
+function DropdownMenu({
+ ...props
+}: React.ComponentProps) {
+ return
+}
+
+function DropdownMenuPortal({
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+function DropdownMenuTrigger({
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+function DropdownMenuContent({
+ className,
+ sideOffset = 4,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
+
+ )
+}
+
+function DropdownMenuGroup({
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+function DropdownMenuItem({
+ className,
+ inset,
+ variant = "default",
+ ...props
+}: React.ComponentProps & {
+ inset?: boolean
+ variant?: "default" | "destructive"
+}) {
+ return (
+
+ )
+}
+
+function DropdownMenuCheckboxItem({
+ className,
+ children,
+ checked,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
+
+
+
+
+ {children}
+
+ )
+}
+
+function DropdownMenuRadioGroup({
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+function DropdownMenuRadioItem({
+ className,
+ children,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
+
+
+
+
+ {children}
+
+ )
+}
+
+function DropdownMenuLabel({
+ className,
+ inset,
+ ...props
+}: React.ComponentProps & {
+ inset?: boolean
+}) {
+ return (
+
+ )
+}
+
+function DropdownMenuSeparator({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+function DropdownMenuShortcut({
+ className,
+ ...props
+}: React.ComponentProps<"span">) {
+ return (
+
+ )
+}
+
+function DropdownMenuSub({
+ ...props
+}: React.ComponentProps) {
+ return
+}
+
+function DropdownMenuSubTrigger({
+ className,
+ inset,
+ children,
+ ...props
+}: React.ComponentProps & {
+ inset?: boolean
+}) {
+ return (
+
+ {children}
+
+
+ )
+}
+
+function DropdownMenuSubContent({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+export {
+ DropdownMenu,
+ DropdownMenuPortal,
+ DropdownMenuTrigger,
+ DropdownMenuContent,
+ DropdownMenuGroup,
+ DropdownMenuLabel,
+ DropdownMenuItem,
+ DropdownMenuCheckboxItem,
+ DropdownMenuRadioGroup,
+ DropdownMenuRadioItem,
+ DropdownMenuSeparator,
+ DropdownMenuShortcut,
+ DropdownMenuSub,
+ DropdownMenuSubTrigger,
+ DropdownMenuSubContent,
+}
diff --git a/src/components/ui/input.tsx b/src/components/ui/input.tsx
new file mode 100644
index 0000000..03295ca
--- /dev/null
+++ b/src/components/ui/input.tsx
@@ -0,0 +1,21 @@
+import * as React from "react"
+
+import { cn } from "@/lib/utils"
+
+function Input({ className, type, ...props }: React.ComponentProps<"input">) {
+ return (
+
+ )
+}
+
+export { Input }
diff --git a/src/components/ui/label.tsx b/src/components/ui/label.tsx
new file mode 100644
index 0000000..fb5fbc3
--- /dev/null
+++ b/src/components/ui/label.tsx
@@ -0,0 +1,24 @@
+"use client"
+
+import * as React from "react"
+import * as LabelPrimitive from "@radix-ui/react-label"
+
+import { cn } from "@/lib/utils"
+
+function Label({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+export { Label }
diff --git a/src/components/ui/progress.tsx b/src/components/ui/progress.tsx
new file mode 100644
index 0000000..e7a416c
--- /dev/null
+++ b/src/components/ui/progress.tsx
@@ -0,0 +1,31 @@
+"use client"
+
+import * as React from "react"
+import * as ProgressPrimitive from "@radix-ui/react-progress"
+
+import { cn } from "@/lib/utils"
+
+function Progress({
+ className,
+ value,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
+
+ )
+}
+
+export { Progress }
diff --git a/src/components/ui/radio-group.tsx b/src/components/ui/radio-group.tsx
new file mode 100644
index 0000000..5e6778c
--- /dev/null
+++ b/src/components/ui/radio-group.tsx
@@ -0,0 +1,45 @@
+"use client"
+
+import * as React from "react"
+import * as RadioGroupPrimitive from "@radix-ui/react-radio-group"
+import { CircleIcon } from "lucide-react"
+
+import { cn } from "@/lib/utils"
+
+function RadioGroup({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+function RadioGroupItem({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
+
+
+
+ )
+}
+
+export { RadioGroup, RadioGroupItem }
diff --git a/src/components/ui/select.tsx b/src/components/ui/select.tsx
new file mode 100644
index 0000000..dcbbc0c
--- /dev/null
+++ b/src/components/ui/select.tsx
@@ -0,0 +1,185 @@
+"use client"
+
+import * as React from "react"
+import * as SelectPrimitive from "@radix-ui/react-select"
+import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react"
+
+import { cn } from "@/lib/utils"
+
+function Select({
+ ...props
+}: React.ComponentProps) {
+ return
+}
+
+function SelectGroup({
+ ...props
+}: React.ComponentProps) {
+ return
+}
+
+function SelectValue({
+ ...props
+}: React.ComponentProps) {
+ return
+}
+
+function SelectTrigger({
+ className,
+ size = "default",
+ children,
+ ...props
+}: React.ComponentProps & {
+ size?: "sm" | "default"
+}) {
+ return (
+
+ {children}
+
+
+
+
+ )
+}
+
+function SelectContent({
+ className,
+ children,
+ position = "popper",
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
+
+
+ {children}
+
+
+
+
+ )
+}
+
+function SelectLabel({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+function SelectItem({
+ className,
+ children,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
+
+
+
+
+ {children}
+
+ )
+}
+
+function SelectSeparator({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+function SelectScrollUpButton({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
+
+ )
+}
+
+function SelectScrollDownButton({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
+
+ )
+}
+
+export {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectLabel,
+ SelectScrollDownButton,
+ SelectScrollUpButton,
+ SelectSeparator,
+ SelectTrigger,
+ SelectValue,
+}
diff --git a/src/components/ui/tabs.tsx b/src/components/ui/tabs.tsx
new file mode 100644
index 0000000..497ba5e
--- /dev/null
+++ b/src/components/ui/tabs.tsx
@@ -0,0 +1,66 @@
+"use client"
+
+import * as React from "react"
+import * as TabsPrimitive from "@radix-ui/react-tabs"
+
+import { cn } from "@/lib/utils"
+
+function Tabs({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+function TabsList({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+function TabsTrigger({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+function TabsContent({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+export { Tabs, TabsList, TabsTrigger, TabsContent }
diff --git a/src/contexts/auth-context.tsx b/src/contexts/auth-context.tsx
new file mode 100644
index 0000000..a59f1ba
--- /dev/null
+++ b/src/contexts/auth-context.tsx
@@ -0,0 +1,138 @@
+"use client"
+
+import React, { createContext, useContext, useState, useEffect, ReactNode } from "react"
+
+interface User {
+ id: string
+ name: string
+ email: string
+ avatar?: string
+}
+
+interface AuthContextType {
+ user: User | null
+ isAuthenticated: boolean
+ isLoading: boolean
+ login: (email: string, password: string) => Promise
+ signup: (name: string, email: string, password: string) => Promise
+ logout: () => void
+}
+
+const AuthContext = createContext(undefined)
+
+export function useAuth() {
+ const context = useContext(AuthContext)
+ if (context === undefined) {
+ throw new Error("useAuth must be used within an AuthProvider")
+ }
+ return context
+}
+
+interface AuthProviderProps {
+ children: ReactNode
+}
+
+export function AuthProvider({ children }: AuthProviderProps) {
+ const [user, setUser] = useState(null)
+ const [isLoading, setIsLoading] = useState(true)
+
+ // Check if user is logged in on mount
+ useEffect(() => {
+ const checkAuth = () => {
+ // Check localStorage for user data
+ const userData = localStorage.getItem("codenuk_user")
+ if (userData) {
+ try {
+ const user = JSON.parse(userData)
+ setUser(user)
+ } catch (error) {
+ console.error("Error parsing user data:", error)
+ localStorage.removeItem("codenuk_user")
+ }
+ }
+ setIsLoading(false)
+ }
+
+ checkAuth()
+ }, [])
+
+ const login = async (email: string, password: string): Promise => {
+ try {
+ setIsLoading(true)
+
+ // Simulate API call
+ await new Promise(resolve => setTimeout(resolve, 1000))
+
+ // For demo purposes, accept any email/password combination
+ if (email && password) {
+ const user: User = {
+ id: "1",
+ name: email.split("@")[0], // Use email prefix as name
+ email: email,
+ avatar: "/avatars/01.png"
+ }
+
+ setUser(user)
+ localStorage.setItem("codenuk_user", JSON.stringify(user))
+ return true
+ }
+
+ return false
+ } catch (error) {
+ console.error("Login error:", error)
+ return false
+ } finally {
+ setIsLoading(false)
+ }
+ }
+
+ const signup = async (name: string, email: string, password: string): Promise => {
+ try {
+ setIsLoading(true)
+
+ // Simulate API call
+ await new Promise(resolve => setTimeout(resolve, 1000))
+
+ // For demo purposes, create user if all fields are provided
+ if (name && email && password) {
+ const user: User = {
+ id: "1",
+ name: name,
+ email: email,
+ avatar: "/avatars/01.png"
+ }
+
+ setUser(user)
+ localStorage.setItem("codenuk_user", JSON.stringify(user))
+ return true
+ }
+
+ return false
+ } catch (error) {
+ console.error("Signup error:", error)
+ return false
+ } finally {
+ setIsLoading(false)
+ }
+ }
+
+ const logout = () => {
+ setUser(null)
+ localStorage.removeItem("codenuk_user")
+ }
+
+ const value: AuthContextType = {
+ user,
+ isAuthenticated: !!user,
+ isLoading,
+ login,
+ signup,
+ logout
+ }
+
+ return (
+
+ {children}
+
+ )
+}
diff --git a/src/lib/utils.ts b/src/lib/utils.ts
new file mode 100644
index 0000000..bd0c391
--- /dev/null
+++ b/src/lib/utils.ts
@@ -0,0 +1,6 @@
+import { clsx, type ClassValue } from "clsx"
+import { twMerge } from "tailwind-merge"
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs))
+}
diff --git a/src/types/feature.ts b/src/types/feature.ts
new file mode 100644
index 0000000..97e8c7a
--- /dev/null
+++ b/src/types/feature.ts
@@ -0,0 +1,30 @@
+import { LucideIcon } from "lucide-react"
+
+export interface Feature {
+ id: string
+ name: string
+ description: string
+ category: string
+ icon: LucideIcon
+ complexity: number
+ timeImpact: string
+ dependencies: string[]
+ conflicts: string[]
+ techStack: string[]
+ businessQuestions: string[]
+ isCore?: boolean
+ isPopular?: boolean
+ }
+
+ export interface SelectedFeature extends Feature {
+ order: number
+ customConfig?: Record
+ }
+
+ export interface FeatureCategory {
+ id: string
+ name: string
+ icon: LucideIcon
+ count: number
+ }
+
\ No newline at end of file
diff --git a/src/types/template.ts b/src/types/template.ts
new file mode 100644
index 0000000..5269d33
--- /dev/null
+++ b/src/types/template.ts
@@ -0,0 +1,27 @@
+import { LucideIcon } from "lucide-react"
+
+export interface Template {
+ id: string
+ title: string
+ description: string
+ category: string
+ features: string[]
+ complexity: number
+ timeEstimate: string
+ techStack: string[]
+ popularity?: number
+ lastUpdated?: string
+ downloads?: number
+ likes?: number
+ author?: string
+ isPublic?: boolean
+ preview?: string
+ }
+
+ export interface TemplateCategory {
+ id: string
+ name: string
+ icon: LucideIcon
+ count: number
+ }
+
\ No newline at end of file