feat: added pages, forms, and functionality.
All checks were successful
Smart Deploy / build-deploy (push) Successful in 2m38s
All checks were successful
Smart Deploy / build-deploy (push) Successful in 2m38s
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
// @ts-check
|
// @ts-check
|
||||||
import { defineConfig } from 'astro/config';
|
import { defineConfig } from 'astro/config';
|
||||||
|
import react from '@astrojs/react';
|
||||||
|
|
||||||
import tailwindcss from '@tailwindcss/vite';
|
import tailwindcss from '@tailwindcss/vite';
|
||||||
import netlify from '@astrojs/netlify';
|
import netlify from '@astrojs/netlify';
|
||||||
@@ -10,5 +11,6 @@ export default defineConfig({
|
|||||||
plugins: [tailwindcss()]
|
plugins: [tailwindcss()]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
integrations: [react()],
|
||||||
adapter: netlify()
|
adapter: netlify()
|
||||||
});
|
});
|
||||||
615
package-lock.json
generated
615
package-lock.json
generated
@@ -9,9 +9,17 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/netlify": "^6.6.4",
|
"@astrojs/netlify": "^6.6.4",
|
||||||
|
"@astrojs/react": "^4.4.2",
|
||||||
"@tailwindcss/vite": "^4.1.18",
|
"@tailwindcss/vite": "^4.1.18",
|
||||||
"astro": "^5.17.1",
|
"astro": "^5.17.1",
|
||||||
"tailwindcss": "^4.1.18"
|
"clsx": "^2.1.1",
|
||||||
|
"framer-motion": "^12.33.0",
|
||||||
|
"lucide-react": "^0.563.0",
|
||||||
|
"react": "^19.2.4",
|
||||||
|
"react-dom": "^19.2.4",
|
||||||
|
"tailwind-merge": "^3.4.0",
|
||||||
|
"tailwindcss": "^4.1.18",
|
||||||
|
"tailwindcss-animate": "^1.0.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@astrojs/compiler": {
|
"node_modules/@astrojs/compiler": {
|
||||||
@@ -87,6 +95,26 @@
|
|||||||
"node": "18.20.8 || ^20.3.0 || >=22.0.0"
|
"node": "18.20.8 || ^20.3.0 || >=22.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@astrojs/react": {
|
||||||
|
"version": "4.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@astrojs/react/-/react-4.4.2.tgz",
|
||||||
|
"integrity": "sha512-1tl95bpGfuaDMDn8O3x/5Dxii1HPvzjvpL2YTuqOOrQehs60I2DKiDgh1jrKc7G8lv+LQT5H15V6QONQ+9waeQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@vitejs/plugin-react": "^4.7.0",
|
||||||
|
"ultrahtml": "^1.6.0",
|
||||||
|
"vite": "^6.4.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "18.20.8 || ^20.3.0 || >=22.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "^17.0.50 || ^18.0.21 || ^19.0.0",
|
||||||
|
"@types/react-dom": "^17.0.17 || ^18.0.6 || ^19.0.0",
|
||||||
|
"react": "^17.0.2 || ^18.0.0 || ^19.0.0",
|
||||||
|
"react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@astrojs/telemetry": {
|
"node_modules/@astrojs/telemetry": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.3.0.tgz",
|
||||||
@@ -125,6 +153,159 @@
|
|||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@babel/compat-data": {
|
||||||
|
"version": "7.29.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz",
|
||||||
|
"integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/core": {
|
||||||
|
"version": "7.29.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz",
|
||||||
|
"integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/code-frame": "^7.29.0",
|
||||||
|
"@babel/generator": "^7.29.0",
|
||||||
|
"@babel/helper-compilation-targets": "^7.28.6",
|
||||||
|
"@babel/helper-module-transforms": "^7.28.6",
|
||||||
|
"@babel/helpers": "^7.28.6",
|
||||||
|
"@babel/parser": "^7.29.0",
|
||||||
|
"@babel/template": "^7.28.6",
|
||||||
|
"@babel/traverse": "^7.29.0",
|
||||||
|
"@babel/types": "^7.29.0",
|
||||||
|
"@jridgewell/remapping": "^2.3.5",
|
||||||
|
"convert-source-map": "^2.0.0",
|
||||||
|
"debug": "^4.1.0",
|
||||||
|
"gensync": "^1.0.0-beta.2",
|
||||||
|
"json5": "^2.2.3",
|
||||||
|
"semver": "^6.3.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/babel"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/core/node_modules/semver": {
|
||||||
|
"version": "6.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||||
|
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||||
|
"license": "ISC",
|
||||||
|
"bin": {
|
||||||
|
"semver": "bin/semver.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/generator": {
|
||||||
|
"version": "7.29.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz",
|
||||||
|
"integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/parser": "^7.29.0",
|
||||||
|
"@babel/types": "^7.29.0",
|
||||||
|
"@jridgewell/gen-mapping": "^0.3.12",
|
||||||
|
"@jridgewell/trace-mapping": "^0.3.28",
|
||||||
|
"jsesc": "^3.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/helper-compilation-targets": {
|
||||||
|
"version": "7.28.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz",
|
||||||
|
"integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/compat-data": "^7.28.6",
|
||||||
|
"@babel/helper-validator-option": "^7.27.1",
|
||||||
|
"browserslist": "^4.24.0",
|
||||||
|
"lru-cache": "^5.1.1",
|
||||||
|
"semver": "^6.3.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": {
|
||||||
|
"version": "5.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
|
||||||
|
"integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"yallist": "^3.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/helper-compilation-targets/node_modules/semver": {
|
||||||
|
"version": "6.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||||
|
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||||
|
"license": "ISC",
|
||||||
|
"bin": {
|
||||||
|
"semver": "bin/semver.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/helper-compilation-targets/node_modules/yallist": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
|
"node_modules/@babel/helper-globals": {
|
||||||
|
"version": "7.28.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
|
||||||
|
"integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/helper-module-imports": {
|
||||||
|
"version": "7.28.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz",
|
||||||
|
"integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/traverse": "^7.28.6",
|
||||||
|
"@babel/types": "^7.28.6"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/helper-module-transforms": {
|
||||||
|
"version": "7.28.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz",
|
||||||
|
"integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/helper-module-imports": "^7.28.6",
|
||||||
|
"@babel/helper-validator-identifier": "^7.28.5",
|
||||||
|
"@babel/traverse": "^7.28.6"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/core": "^7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/helper-plugin-utils": {
|
||||||
|
"version": "7.28.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz",
|
||||||
|
"integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@babel/helper-string-parser": {
|
"node_modules/@babel/helper-string-parser": {
|
||||||
"version": "7.27.1",
|
"version": "7.27.1",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
|
||||||
@@ -143,6 +324,28 @@
|
|||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@babel/helper-validator-option": {
|
||||||
|
"version": "7.27.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
|
||||||
|
"integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/helpers": {
|
||||||
|
"version": "7.28.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz",
|
||||||
|
"integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/template": "^7.28.6",
|
||||||
|
"@babel/types": "^7.28.6"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@babel/parser": {
|
"node_modules/@babel/parser": {
|
||||||
"version": "7.29.0",
|
"version": "7.29.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz",
|
||||||
@@ -158,6 +361,68 @@
|
|||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@babel/plugin-transform-react-jsx-self": {
|
||||||
|
"version": "7.27.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz",
|
||||||
|
"integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/helper-plugin-utils": "^7.27.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/core": "^7.0.0-0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/plugin-transform-react-jsx-source": {
|
||||||
|
"version": "7.27.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz",
|
||||||
|
"integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/helper-plugin-utils": "^7.27.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/core": "^7.0.0-0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/template": {
|
||||||
|
"version": "7.28.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz",
|
||||||
|
"integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/code-frame": "^7.28.6",
|
||||||
|
"@babel/parser": "^7.28.6",
|
||||||
|
"@babel/types": "^7.28.6"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/traverse": {
|
||||||
|
"version": "7.29.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz",
|
||||||
|
"integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/code-frame": "^7.29.0",
|
||||||
|
"@babel/generator": "^7.29.0",
|
||||||
|
"@babel/helper-globals": "^7.28.0",
|
||||||
|
"@babel/parser": "^7.29.0",
|
||||||
|
"@babel/template": "^7.28.6",
|
||||||
|
"@babel/types": "^7.29.0",
|
||||||
|
"debug": "^4.3.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@babel/types": {
|
"node_modules/@babel/types": {
|
||||||
"version": "7.29.0",
|
"version": "7.29.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
|
||||||
@@ -3309,6 +3574,12 @@
|
|||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@rolldown/pluginutils": {
|
||||||
|
"version": "1.0.0-beta.27",
|
||||||
|
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz",
|
||||||
|
"integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@rollup/pluginutils": {
|
"node_modules/@rollup/pluginutils": {
|
||||||
"version": "5.3.0",
|
"version": "5.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz",
|
||||||
@@ -3996,6 +4267,47 @@
|
|||||||
"vite": "^5.2.0 || ^6 || ^7"
|
"vite": "^5.2.0 || ^6 || ^7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/babel__core": {
|
||||||
|
"version": "7.20.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
|
||||||
|
"integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/parser": "^7.20.7",
|
||||||
|
"@babel/types": "^7.20.7",
|
||||||
|
"@types/babel__generator": "*",
|
||||||
|
"@types/babel__template": "*",
|
||||||
|
"@types/babel__traverse": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/babel__generator": {
|
||||||
|
"version": "7.27.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
|
||||||
|
"integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/types": "^7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/babel__template": {
|
||||||
|
"version": "7.4.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
|
||||||
|
"integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/parser": "^7.1.0",
|
||||||
|
"@babel/types": "^7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/babel__traverse": {
|
||||||
|
"version": "7.28.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
|
||||||
|
"integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/types": "^7.28.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/debug": {
|
"node_modules/@types/debug": {
|
||||||
"version": "4.1.12",
|
"version": "4.1.12",
|
||||||
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz",
|
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz",
|
||||||
@@ -4060,6 +4372,26 @@
|
|||||||
"integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==",
|
"integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/react": {
|
||||||
|
"version": "19.2.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.13.tgz",
|
||||||
|
"integrity": "sha512-KkiJeU6VbYbUOp5ITMIc7kBfqlYkKA5KhEHVrGMmUUMt7NeaZg65ojdPk+FtNrBAOXNVM5QM72jnADjM+XVRAQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"csstype": "^3.2.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/react-dom": {
|
||||||
|
"version": "19.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz",
|
||||||
|
"integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "^19.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/retry": {
|
"node_modules/@types/retry": {
|
||||||
"version": "0.12.2",
|
"version": "0.12.2",
|
||||||
"resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz",
|
||||||
@@ -4220,6 +4552,26 @@
|
|||||||
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
|
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@vitejs/plugin-react": {
|
||||||
|
"version": "4.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz",
|
||||||
|
"integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/core": "^7.28.0",
|
||||||
|
"@babel/plugin-transform-react-jsx-self": "^7.27.1",
|
||||||
|
"@babel/plugin-transform-react-jsx-source": "^7.27.1",
|
||||||
|
"@rolldown/pluginutils": "1.0.0-beta.27",
|
||||||
|
"@types/babel__core": "^7.20.5",
|
||||||
|
"react-refresh": "^0.17.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^14.18.0 || >=16.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@vue/compiler-core": {
|
"node_modules/@vue/compiler-core": {
|
||||||
"version": "3.5.27",
|
"version": "3.5.27",
|
||||||
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.27.tgz",
|
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.27.tgz",
|
||||||
@@ -4821,6 +5173,15 @@
|
|||||||
],
|
],
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/baseline-browser-mapping": {
|
||||||
|
"version": "2.9.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz",
|
||||||
|
"integrity": "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"bin": {
|
||||||
|
"baseline-browser-mapping": "dist/cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/better-ajv-errors": {
|
"node_modules/better-ajv-errors": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/better-ajv-errors/-/better-ajv-errors-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/better-ajv-errors/-/better-ajv-errors-1.2.0.tgz",
|
||||||
@@ -4941,6 +5302,40 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/browserslist": {
|
||||||
|
"version": "4.28.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz",
|
||||||
|
"integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/browserslist"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "tidelift",
|
||||||
|
"url": "https://tidelift.com/funding/github/npm/browserslist"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ai"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"baseline-browser-mapping": "^2.9.0",
|
||||||
|
"caniuse-lite": "^1.0.30001759",
|
||||||
|
"electron-to-chromium": "^1.5.263",
|
||||||
|
"node-releases": "^2.0.27",
|
||||||
|
"update-browserslist-db": "^1.2.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"browserslist": "cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/buffer": {
|
"node_modules/buffer": {
|
||||||
"version": "6.0.3",
|
"version": "6.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
|
||||||
@@ -5006,6 +5401,26 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/caniuse-lite": {
|
||||||
|
"version": "1.0.30001769",
|
||||||
|
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001769.tgz",
|
||||||
|
"integrity": "sha512-BCfFL1sHijQlBGWBMuJyhZUhzo7wer5sVj9hqekB/7xn0Ypy+pER/edCYQm4exbXj4WiySGp40P8UuTh6w1srg==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/browserslist"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "tidelift",
|
||||||
|
"url": "https://tidelift.com/funding/github/npm/caniuse-lite"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ai"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "CC-BY-4.0"
|
||||||
|
},
|
||||||
"node_modules/ccount": {
|
"node_modules/ccount": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz",
|
||||||
@@ -5384,6 +5799,12 @@
|
|||||||
"node": "^14.18.0 || >=16.10.0"
|
"node": "^14.18.0 || >=16.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/convert-source-map": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/cookie": {
|
"node_modules/cookie": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz",
|
||||||
@@ -5586,6 +6007,12 @@
|
|||||||
"integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==",
|
"integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==",
|
||||||
"license": "CC0-1.0"
|
"license": "CC0-1.0"
|
||||||
},
|
},
|
||||||
|
"node_modules/csstype": {
|
||||||
|
"version": "3.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
|
||||||
|
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/data-uri-to-buffer": {
|
"node_modules/data-uri-to-buffer": {
|
||||||
"version": "4.0.1",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
|
||||||
@@ -5989,6 +6416,12 @@
|
|||||||
"safe-buffer": "^5.0.1"
|
"safe-buffer": "^5.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/electron-to-chromium": {
|
||||||
|
"version": "1.5.286",
|
||||||
|
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.286.tgz",
|
||||||
|
"integrity": "sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
"node_modules/emoji-regex": {
|
"node_modules/emoji-regex": {
|
||||||
"version": "10.6.0",
|
"version": "10.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz",
|
||||||
@@ -6567,6 +7000,33 @@
|
|||||||
"node": ">=12.20.0"
|
"node": ">=12.20.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/framer-motion": {
|
||||||
|
"version": "12.33.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.33.0.tgz",
|
||||||
|
"integrity": "sha512-ca8d+rRPcDP5iIF+MoT3WNc0KHJMjIyFAbtVLvM9eA7joGSpeqDfiNH/kCs1t4CHi04njYvWyj0jS4QlEK/rJQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"motion-dom": "^12.33.0",
|
||||||
|
"motion-utils": "^12.29.2",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@emotion/is-prop-valid": "*",
|
||||||
|
"react": "^18.0.0 || ^19.0.0",
|
||||||
|
"react-dom": "^18.0.0 || ^19.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@emotion/is-prop-valid": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fsevents": {
|
"node_modules/fsevents": {
|
||||||
"version": "2.3.3",
|
"version": "2.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||||
@@ -6590,6 +7050,15 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/gensync": {
|
||||||
|
"version": "1.0.0-beta.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
|
||||||
|
"integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/get-amd-module-type": {
|
"node_modules/get-amd-module-type": {
|
||||||
"version": "6.0.1",
|
"version": "6.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/get-amd-module-type/-/get-amd-module-type-6.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/get-amd-module-type/-/get-amd-module-type-6.0.1.tgz",
|
||||||
@@ -7400,12 +7869,36 @@
|
|||||||
"js-yaml": "bin/js-yaml.js"
|
"js-yaml": "bin/js-yaml.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/jsesc": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"jsesc": "bin/jsesc"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/json-schema-traverse": {
|
"node_modules/json-schema-traverse": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/json5": {
|
||||||
|
"version": "2.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
|
||||||
|
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"json5": "lib/cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/jsonpointer": {
|
"node_modules/jsonpointer": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz",
|
||||||
@@ -7955,6 +8448,15 @@
|
|||||||
"node": "20 || >=22"
|
"node": "20 || >=22"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/lucide-react": {
|
||||||
|
"version": "0.563.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.563.0.tgz",
|
||||||
|
"integrity": "sha512-8dXPB2GI4dI8jV4MgUDGBeLdGk8ekfqVZ0BdLcrRzocGgG75ltNEmWS+gE7uokKF/0oSUuczNDT+g9hFJ23FkA==",
|
||||||
|
"license": "ISC",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/luxon": {
|
"node_modules/luxon": {
|
||||||
"version": "3.7.2",
|
"version": "3.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/luxon/-/luxon-3.7.2.tgz",
|
"resolved": "https://registry.npmjs.org/luxon/-/luxon-3.7.2.tgz",
|
||||||
@@ -8977,6 +9479,21 @@
|
|||||||
"integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==",
|
"integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/motion-dom": {
|
||||||
|
"version": "12.33.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.33.0.tgz",
|
||||||
|
"integrity": "sha512-XRPebVypsl0UM+7v0Hr8o9UAj0S2djsQWRdHBd5iVouVpMrQqAI0C/rDAT3QaYnXnHuC5hMcwDHCboNeyYjPoQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"motion-utils": "^12.29.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/motion-utils": {
|
||||||
|
"version": "12.29.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.29.2.tgz",
|
||||||
|
"integrity": "sha512-G3kc34H2cX2gI63RqU+cZq+zWRRPSsNIOjpdl9TN4AQwC4sgwYPl/Q/Obf/d53nOm569T0fYK+tcoSV50BWx8A==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/mrmime": {
|
"node_modules/mrmime": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz",
|
||||||
@@ -9114,6 +9631,12 @@
|
|||||||
"integrity": "sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==",
|
"integrity": "sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/node-releases": {
|
||||||
|
"version": "2.0.27",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz",
|
||||||
|
"integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/node-source-walk": {
|
"node_modules/node-source-walk": {
|
||||||
"version": "7.0.1",
|
"version": "7.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/node-source-walk/-/node-source-walk-7.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/node-source-walk/-/node-source-walk-7.0.1.tgz",
|
||||||
@@ -9777,6 +10300,38 @@
|
|||||||
"integrity": "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==",
|
"integrity": "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/react": {
|
||||||
|
"version": "19.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz",
|
||||||
|
"integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-dom": {
|
||||||
|
"version": "19.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz",
|
||||||
|
"integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"scheduler": "^0.27.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^19.2.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-refresh": {
|
||||||
|
"version": "0.17.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz",
|
||||||
|
"integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/read-package-up": {
|
"node_modules/read-package-up": {
|
||||||
"version": "11.0.0",
|
"version": "11.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/read-package-up/-/read-package-up-11.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/read-package-up/-/read-package-up-11.0.0.tgz",
|
||||||
@@ -10305,6 +10860,12 @@
|
|||||||
"node": ">=11.0.0"
|
"node": ">=11.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/scheduler": {
|
||||||
|
"version": "0.27.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
|
||||||
|
"integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/semver": {
|
"node_modules/semver": {
|
||||||
"version": "7.7.4",
|
"version": "7.7.4",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
|
||||||
@@ -10722,11 +11283,31 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tailwind-merge": {
|
||||||
|
"version": "3.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.4.0.tgz",
|
||||||
|
"integrity": "sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/dcastil"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/tailwindcss": {
|
"node_modules/tailwindcss": {
|
||||||
"version": "4.1.18",
|
"version": "4.1.18",
|
||||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz",
|
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz",
|
||||||
"integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==",
|
"integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==",
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
|
},
|
||||||
|
"node_modules/tailwindcss-animate": {
|
||||||
|
"version": "1.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz",
|
||||||
|
"integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"tailwindcss": ">=3.0.0 || insiders"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"node_modules/tapable": {
|
"node_modules/tapable": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
@@ -11294,6 +11875,36 @@
|
|||||||
"integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
|
"integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/update-browserslist-db": {
|
||||||
|
"version": "1.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
|
||||||
|
"integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/browserslist"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "tidelift",
|
||||||
|
"url": "https://tidelift.com/funding/github/npm/browserslist"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ai"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"escalade": "^3.2.0",
|
||||||
|
"picocolors": "^1.1.1"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"update-browserslist-db": "cli.js"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"browserslist": ">= 4.21.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/uqr": {
|
"node_modules/uqr": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/uqr/-/uqr-0.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/uqr/-/uqr-0.1.2.tgz",
|
||||||
|
|||||||
10
package.json
10
package.json
@@ -10,8 +10,16 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/netlify": "^6.6.4",
|
"@astrojs/netlify": "^6.6.4",
|
||||||
|
"@astrojs/react": "^4.4.2",
|
||||||
"@tailwindcss/vite": "^4.1.18",
|
"@tailwindcss/vite": "^4.1.18",
|
||||||
"astro": "^5.17.1",
|
"astro": "^5.17.1",
|
||||||
"tailwindcss": "^4.1.18"
|
"clsx": "^2.1.1",
|
||||||
|
"framer-motion": "^12.33.0",
|
||||||
|
"lucide-react": "^0.563.0",
|
||||||
|
"react": "^19.2.4",
|
||||||
|
"react-dom": "^19.2.4",
|
||||||
|
"tailwind-merge": "^3.4.0",
|
||||||
|
"tailwindcss": "^4.1.18",
|
||||||
|
"tailwindcss-animate": "^1.0.7"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
186
src/components/Footer.astro
Normal file
186
src/components/Footer.astro
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
---
|
||||||
|
import { Code2, Github, Twitter, Linkedin } from "lucide-react";
|
||||||
|
---
|
||||||
|
|
||||||
|
<footer class="py-20 border-t border-white/5 bg-slate-950">
|
||||||
|
<div class="container mx-auto px-6">
|
||||||
|
<div class="grid md:grid-cols-4 gap-12 mb-16">
|
||||||
|
<div class="col-span-1 md:col-span-2">
|
||||||
|
<div class="flex items-center gap-2 mb-6">
|
||||||
|
<div
|
||||||
|
class="w-8 h-8 bg-amber-500 rounded-lg flex items-center justify-center transform rotate-12"
|
||||||
|
>
|
||||||
|
<Code2 size={18} className="text-slate-900" />
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="text-xl font-bold font-heading tracking-tight text-white"
|
||||||
|
>
|
||||||
|
Move. <span class="text-indigo-400">Compete.</span> Play.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<p class="text-slate-500 max-w-sm mb-6 leading-relaxed">
|
||||||
|
The premier hub for tech professionals to transition from
|
||||||
|
AI-anxiety to AI-mastery through building and community.
|
||||||
|
</p>
|
||||||
|
<div class="flex gap-4">
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
class="w-10 h-10 rounded-lg bg-slate-900 border border-slate-800 flex items-center justify-center text-slate-400 hover:text-amber-500 hover:border-amber-500/50 transition-all"
|
||||||
|
>
|
||||||
|
<span class="sr-only">Discord</span>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="18"
|
||||||
|
height="18"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M9.5 7.5c-.828 0-1.5.671-1.5 1.5 0 .828.672 1.5 1.5 1.5s1.5-.672 1.5-1.5c0-.829-.672-1.5-1.5-1.5zm5 0c-.828 0-1.5.671-1.5 1.5 0 .828.672 1.5 1.5 1.5s1.5-.672 1.5-1.5c0-.829-.672-1.5-1.5-1.5z"
|
||||||
|
></path>
|
||||||
|
<path
|
||||||
|
d="M18.7 4.1c-1.26-.42-2.61-.73-4-.91-.18.31-.35.63-.49.97-1.5-.23-3-.23-4.5 0-.14-.34-.31-.66-.49-.97-1.39.18-2.74.49-4 .91-2.59 3.89-3.29 7.69-2.94 11.44 1.69 1.25 3.33 2.01 4.95 2.51.4-.54.75-1.12 1.05-1.72-.58-.22-1.13-.48-1.66-.78.14-.1.27-.21.4-.32 3.21 1.49 6.76 1.49 9.96 0 .13.11.26.22.4.32-.53.3-1.08.56-1.66.78.3.6.65 1.18 1.05 1.72 1.62-.5 3.26-1.26 4.95-2.51.39-4.2-.65-7.84-2.94-11.44z"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
id="footer-gitea-trigger"
|
||||||
|
href="#"
|
||||||
|
class="w-10 h-10 rounded-lg bg-slate-900 border border-slate-800 flex items-center justify-center text-slate-400 hover:text-amber-500 hover:border-amber-500/50 transition-all"
|
||||||
|
>
|
||||||
|
<span class="sr-only">Gitea</span>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="18"
|
||||||
|
height="18"
|
||||||
|
viewBox="0 0 640 640"
|
||||||
|
fill="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M395.9,484.2l-126.9-61c-12.5-6-17.9-21.2-11.8-33.8l61-126.9c6-12.5,21.2-17.9,33.8-11.8 c17.2,8.3,27.1,13,27.1,13l-0.1-109.2l16.7-0.1l0.1,117.1c0,0,57.4,24.2,83.1,40.1c3.7,2.3,10.2,6.8,12.9,14.4 c2.1,6.1,2,13.1-1,19.3l-61,126.9C423.6,484.9,408.4,490.3,395.9,484.2z"
|
||||||
|
></path>
|
||||||
|
<path
|
||||||
|
d="M622.7,149.8c-4.1-4.1-9.6-4-9.6-4s-117.2,6.6-177.9,8c-13.3,0.3-26.5,0.6-39.6,0.7c0,39.1,0,78.2,0,117.2 c-5.5-2.6-11.1-5.3-16.6-7.9c0-36.4-0.1-109.2-0.1-109.2c-29,0.4-89.2-2.2-89.2-2.2s-141.4-7.1-156.8-8.5 c-9.8-0.6-22.5-2.1-39,1.5c-8.7,1.8-33.5,7.4-53.8,26.9C-4.9,212.4,6.6,276.2,8,285.8c1.7,11.7,6.9,44.2,31.7,72.5 c45.8,56.1,144.4,54.8,144.4,54.8s12.1,28.9,30.6,55.5c25,33.1,50.7,58.9,75.7,62c63,0,188.9-0.1,188.9-0.1s12,0.1,28.3-10.3 c14-8.5,26.5-23.4,26.5-23.4s12.9-13.8,30.9-45.3c5.5-9.7,10.1-19.1,14.1-28c0,0,55.2-117.1,55.2-231.1 C633.2,157.9,624.7,151.8,622.7,149.8z M125.6,353.9c-25.9-8.5-36.9-18.7-36.9-18.7S69.6,321.8,60,295.4 c-16.5-44.2-1.4-71.2-1.4-71.2s8.4-22.5,38.5-30c13.8-3.7,31-3.1,31-3.1s7.1,59.4,15.7,94.2c7.2,29.2,24.8,77.7,24.8,77.7 S142.5,359.9,125.6,353.9z M425.9,461.5c0,0-6.1,14.5-19.6,15.4c-5.8,0.4-10.3-1.2-10.3-1.2s-0.3-0.1-5.3-2.1l-112.9-55 c0,0-10.9-5.7-12.8-15.6c-2.2-8.1,2.7-18.1,2.7-18.1L322,273c0,0,4.8-9.7,12.2-13c0.6-0.3,2.3-1,4.5-1.5c8.1-2.1,18,2.8,18,2.8 l110.7,53.7c0,0,12.6,5.7,15.3,16.2c1.9,7.4-0.5,14-1.8,17.2C474.6,363.8,425.9,461.5,425.9,461.5z"
|
||||||
|
></path>
|
||||||
|
<path
|
||||||
|
d="M326.8,380.1c-8.2,0.1-15.4,5.8-17.3,13.8c-1.9,8,2,16.3,9.1,20c7.7,4,17.5,1.8,22.7-5.4 c5.1-7.1,4.3-16.9-1.8-23.1l24-49.1c1.5,0.1,3.7,0.2,6.2-0.5c4.1-0.9,7.1-3.6,7.1-3.6c4.2,1.8,8.6,3.8,13.2,6.1 c4.8,2.4,9.3,4.9,13.4,7.3c0.9,0.5,1.8,1.1,2.8,1.9c1.6,1.3,3.4,3.1,4.7,5.5c1.9,5.5-1.9,14.9-1.9,14.9 c-2.3,7.6-18.4,40.6-18.4,40.6c-8.1-0.2-15.3,5-17.7,12.5c-2.6,8.1,1.1,17.3,8.9,21.3c7.8,4,17.4,1.7,22.5-5.3 c5-6.8,4.6-16.3-1.1-22.6c1.9-3.7,3.7-7.4,5.6-11.3c5-10.4,13.5-30.4,13.5-30.4c0.9-1.7,5.7-10.3,2.7-21.3 c-2.5-11.4-12.6-16.7-12.6-16.7c-12.2-7.9-29.2-15.2-29.2-15.2s0-4.1-1.1-7.1c-1.1-3.1-2.8-5.1-3.9-6.3c4.7-9.7,9.4-19.3,14.1-29 c-4.1-2-8.1-4-12.2-6.1c-4.8,9.8-9.7,19.7-14.5,29.5c-6.7-0.1-12.9,3.5-16.1,9.4c-3.4,6.3-2.7,14.1,1.9,19.8 C343.2,346.5,335,363.3,326.8,380.1z"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
class="w-10 h-10 rounded-lg bg-slate-900 border border-slate-800 flex items-center justify-center text-slate-400 hover:text-amber-500 hover:border-amber-500/50 transition-all"
|
||||||
|
>
|
||||||
|
<span class="sr-only">Twitter</span>
|
||||||
|
<Twitter size={18} />
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
class="w-10 h-10 rounded-lg bg-slate-900 border border-slate-800 flex items-center justify-center text-slate-400 hover:text-amber-500 hover:border-amber-500/50 transition-all"
|
||||||
|
>
|
||||||
|
<span class="sr-only">LinkedIn</span>
|
||||||
|
<Linkedin size={18} />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h5 class="text-white font-bold mb-6 font-heading">Resource</h5>
|
||||||
|
<ul class="space-y-4 text-sm text-slate-500">
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
class="hover:text-amber-400 transition-colors"
|
||||||
|
>The Manifesto</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
class="hover:text-amber-400 transition-colors"
|
||||||
|
>Build Kits</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
class="hover:text-amber-400 transition-colors"
|
||||||
|
>Squad Directory</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
class="hover:text-amber-400 transition-colors"
|
||||||
|
>Alumni Network</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h5 class="text-white font-bold mb-6 font-heading">
|
||||||
|
Protocols
|
||||||
|
</h5>
|
||||||
|
<ul class="space-y-4 text-sm text-slate-500 font-mono">
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
class="hover:text-indigo-400 transition-colors"
|
||||||
|
>MCP Spec</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
class="hover:text-indigo-400 transition-colors"
|
||||||
|
>UCP Handshake</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
class="hover:text-indigo-400 transition-colors"
|
||||||
|
>Agent SDK</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
class="hover:text-indigo-400 transition-colors"
|
||||||
|
>A2A Messaging</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="flex flex-col md:flex-row justify-between items-center gap-6 pt-10 border-t border-white/5"
|
||||||
|
>
|
||||||
|
<p class="text-sm text-slate-600 font-heading font-bold">
|
||||||
|
© {new Date().getFullYear()} Move. Compete. Play. — The future belongs
|
||||||
|
to the builders. ⚡ Built with AI
|
||||||
|
</p>
|
||||||
|
<div class="flex gap-8 text-xs text-slate-600">
|
||||||
|
<a href="#" class="hover:text-slate-400">Privacy Policy</a>
|
||||||
|
<a href="#" class="hover:text-slate-400">Terms of Service</a>
|
||||||
|
<a href="#" class="hover:text-slate-400">Code of Conduct</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const footerTrigger = document.getElementById("footer-gitea-trigger");
|
||||||
|
if (footerTrigger) {
|
||||||
|
footerTrigger.addEventListener("click", (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
window.dispatchEvent(new CustomEvent("open-join-modal"));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
97
src/components/Navbar.astro
Normal file
97
src/components/Navbar.astro
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
---
|
||||||
|
import { Code2 } from "lucide-react";
|
||||||
|
---
|
||||||
|
|
||||||
|
<nav
|
||||||
|
id="navbar"
|
||||||
|
class="fixed top-0 w-full z-50 transition-all duration-300 py-6 bg-transparent"
|
||||||
|
>
|
||||||
|
<div class="container mx-auto px-6 flex items-center justify-between">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<div
|
||||||
|
class="w-8 h-8 bg-amber-500 rounded-lg flex items-center justify-center transform rotate-12"
|
||||||
|
>
|
||||||
|
<Code2 size={18} className="text-slate-900" />
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="text-xl font-bold font-heading tracking-tight text-white"
|
||||||
|
>
|
||||||
|
Move. <span class="text-indigo-400">Compete.</span> Play.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="hidden md:flex items-center gap-10">
|
||||||
|
{
|
||||||
|
[
|
||||||
|
{ name: "The Mission", href: "#the-mission" },
|
||||||
|
{ name: "Build Projects", href: "/#build-season" },
|
||||||
|
{ name: "Squads", href: "#squads" },
|
||||||
|
{ name: "Manifesto", href: "#manifesto" },
|
||||||
|
].map((link) => (
|
||||||
|
<a
|
||||||
|
href={link.href}
|
||||||
|
class="text-sm font-medium text-slate-300 hover:text-amber-400 transition-colors"
|
||||||
|
>
|
||||||
|
{link.name}
|
||||||
|
</a>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
id="join-trigger"
|
||||||
|
class="bg-amber-500 hover:bg-amber-400 text-slate-900 font-bold px-4 py-2 text-sm md:px-6 md:py-2.5 md:text-base rounded-full transition-all hover:scale-105 active:scale-95 shadow-lg shadow-amber-500/20 cursor-pointer flex items-center gap-2"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
viewBox="0 0 640 640"
|
||||||
|
fill="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M395.9,484.2l-126.9-61c-12.5-6-17.9-21.2-11.8-33.8l61-126.9c6-12.5,21.2-17.9,33.8-11.8 c17.2,8.3,27.1,13,27.1,13l-0.1-109.2l16.7-0.1l0.1,117.1c0,0,57.4,24.2,83.1,40.1c3.7,2.3,10.2,6.8,12.9,14.4 c2.1,6.1,2,13.1-1,19.3l-61,126.9C423.6,484.9,408.4,490.3,395.9,484.2z"
|
||||||
|
></path>
|
||||||
|
<path
|
||||||
|
d="M622.7,149.8c-4.1-4.1-9.6-4-9.6-4s-117.2,6.6-177.9,8c-13.3,0.3-26.5,0.6-39.6,0.7c0,39.1,0,78.2,0,117.2 c-5.5-2.6-11.1-5.3-16.6-7.9c0-36.4-0.1-109.2-0.1-109.2c-29,0.4-89.2-2.2-89.2-2.2s-141.4-7.1-156.8-8.5 c-9.8-0.6-22.5-2.1-39,1.5c-8.7,1.8-33.5,7.4-53.8,26.9C-4.9,212.4,6.6,276.2,8,285.8c1.7,11.7,6.9,44.2,31.7,72.5 c45.8,56.1,144.4,54.8,144.4,54.8s12.1,28.9,30.6,55.5c25,33.1,50.7,58.9,75.7,62c63,0,188.9-0.1,188.9-0.1s12,0.1,28.3-10.3 c14-8.5,26.5-23.4,26.5-23.4s12.9-13.8,30.9-45.3c5.5-9.7,10.1-19.1,14.1-28c0,0,55.2-117.1,55.2-231.1 C633.2,157.9,624.7,151.8,622.7,149.8z M125.6,353.9c-25.9-8.5-36.9-18.7-36.9-18.7S69.6,321.8,60,295.4 c-16.5-44.2-1.4-71.2-1.4-71.2s8.4-22.5,38.5-30c13.8-3.7,31-3.1,31-3.1s7.1,59.4,15.7,94.2c7.2,29.2,24.8,77.7,24.8,77.7 S142.5,359.9,125.6,353.9z M425.9,461.5c0,0-6.1,14.5-19.6,15.4c-5.8,0.4-10.3-1.2-10.3-1.2s-0.3-0.1-5.3-2.1l-112.9-55 c0,0-10.9-5.7-12.8-15.6c-2.2-8.1,2.7-18.1,2.7-18.1L322,273c0,0,4.8-9.7,12.2-13c0.6-0.3,2.3-1,4.5-1.5c8.1-2.1,18,2.8,18,2.8 l110.7,53.7c0,0,12.6,5.7,15.3,16.2c1.9,7.4-0.5,14-1.8,17.2C474.6,363.8,425.9,461.5,425.9,461.5z"
|
||||||
|
></path>
|
||||||
|
<path
|
||||||
|
d="M326.8,380.1c-8.2,0.1-15.4,5.8-17.3,13.8c-1.9,8,2,16.3,9.1,20c7.7,4,17.5,1.8,22.7-5.4 c5.1-7.1,4.3-16.9-1.8-23.1l24-49.1c1.5,0.1,3.7,0.2,6.2-0.5c4.1-0.9,7.1-3.6,7.1-3.6c4.2,1.8,8.6,3.8,13.2,6.1 c4.8,2.4,9.3,4.9,13.4,7.3c0.9,0.5,1.8,1.1,2.8,1.9c1.6,1.3,3.4,3.1,4.7,5.5c1.9,5.5-1.9,14.9-1.9,14.9 c-2.3,7.6-18.4,40.6-18.4,40.6c-8.1-0.2-15.3,5-17.7,12.5c-2.6,8.1,1.1,17.3,8.9,21.3c7.8,4,17.4,1.7,22.5-5.3 c5-6.8,4.6-16.3-1.1-22.6c1.9-3.7,3.7-7.4,5.6-11.3c5-10.4,13.5-30.4,13.5-30.4c0.9-1.7,5.7-10.3,2.7-21.3 c-2.5-11.4-12.6-16.7-12.6-16.7c-12.2-7.9-29.2-15.2-29.2-15.2s0-4.1-1.1-7.1c-1.1-3.1-2.8-5.1-3.9-6.3c4.7-9.7,9.4-19.3,14.1-29 c-4.1-2-8.1-4-12.2-6.1c-4.8,9.8-9.7,19.7-14.5,29.5c-6.7-0.1-12.9,3.5-16.1,9.4c-3.4,6.3-2.7,14.1,1.9,19.8 C343.2,346.5,335,363.3,326.8,380.1z"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
Contribute
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const nav = document.getElementById("navbar");
|
||||||
|
if (nav) {
|
||||||
|
const joinTrigger = document.getElementById("join-trigger");
|
||||||
|
if (joinTrigger) {
|
||||||
|
joinTrigger.addEventListener("click", () => {
|
||||||
|
window.dispatchEvent(new CustomEvent("open-join-modal"));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("scroll", () => {
|
||||||
|
if (window.scrollY > 50) {
|
||||||
|
nav.classList.add(
|
||||||
|
"bg-slate-900/80",
|
||||||
|
"backdrop-blur-md",
|
||||||
|
"py-4",
|
||||||
|
"shadow-xl",
|
||||||
|
);
|
||||||
|
nav.classList.remove("bg-transparent", "py-6");
|
||||||
|
} else {
|
||||||
|
nav.classList.add("bg-transparent", "py-6");
|
||||||
|
nav.classList.remove(
|
||||||
|
"bg-slate-900/80",
|
||||||
|
"backdrop-blur-md",
|
||||||
|
"py-4",
|
||||||
|
"shadow-xl",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
46
src/components/TechMarquee.astro
Normal file
46
src/components/TechMarquee.astro
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
---
|
||||||
|
const TECH_STACK = [
|
||||||
|
"MCP",
|
||||||
|
"Supabase",
|
||||||
|
"Gemini",
|
||||||
|
"Claude",
|
||||||
|
"UCP",
|
||||||
|
"Agent-to-Agent",
|
||||||
|
"OpenAI",
|
||||||
|
"LangChain",
|
||||||
|
"VectorDB",
|
||||||
|
"LlamaIndex",
|
||||||
|
"Pinecone",
|
||||||
|
];
|
||||||
|
---
|
||||||
|
|
||||||
|
<section class="py-12 border-y border-white/5 bg-slate-800">
|
||||||
|
<div class="flex overflow-hidden group">
|
||||||
|
<div
|
||||||
|
class="flex animate-scroll hover:[animation-play-state:paused] whitespace-nowrap"
|
||||||
|
>
|
||||||
|
{
|
||||||
|
[...TECH_STACK, ...TECH_STACK].map((tech) => (
|
||||||
|
<div class="mx-8 px-6 py-2 rounded-full border border-slate-800 bg-slate-800/30 text-slate-400 font-mono text-sm flex items-center gap-2 hover:border-indigo-500/50 hover:text-indigo-400 transition-all cursor-default">
|
||||||
|
<div class="w-1.5 h-1.5 rounded-full bg-indigo-500/50" />
|
||||||
|
{tech}
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@keyframes scroll {
|
||||||
|
0% {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.animate-scroll {
|
||||||
|
animation: scroll 30s linear infinite;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
70
src/components/react/CodeWindow.tsx
Normal file
70
src/components/react/CodeWindow.tsx
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
import { useState } from 'react';
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
|
||||||
|
export const CodeWindow = () => {
|
||||||
|
const [lines] = useState([
|
||||||
|
{ text: "const agent = new BuilderAgent({", color: "text-indigo-400" },
|
||||||
|
{ text: " protocol: 'MCP',", color: "text-amber-400" },
|
||||||
|
{ text: " squad: 'Alpha-Team',", color: "text-amber-400" },
|
||||||
|
{ text: " mission: 'Future-Proof',", color: "text-amber-400" },
|
||||||
|
{ text: "});", color: "text-indigo-400" },
|
||||||
|
{ text: "", color: "" },
|
||||||
|
{ text: "await agent.startBuilding();", color: "text-emerald-400" }
|
||||||
|
]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="bg-[#0f172a] rounded-xl border border-slate-700 overflow-hidden shadow-2xl h-full flex flex-col font-mono text-sm">
|
||||||
|
<div className="flex items-center gap-2 px-4 py-3 bg-slate-800/50 border-b border-slate-700">
|
||||||
|
<div className="flex gap-1.5">
|
||||||
|
<div className="w-3 h-3 rounded-full bg-red-500/50" />
|
||||||
|
<div className="w-3 h-3 rounded-full bg-amber-500/50" />
|
||||||
|
<div className="w-3 h-3 rounded-full bg-emerald-500/50" />
|
||||||
|
</div>
|
||||||
|
<div className="ml-4 text-slate-500 text-xs tracking-wider">BUILDER_SQUAD_01.ts</div>
|
||||||
|
</div>
|
||||||
|
<div className="p-6 flex-1 relative">
|
||||||
|
<div className="space-y-2">
|
||||||
|
{lines.map((line, i) => (
|
||||||
|
<motion.div
|
||||||
|
key={i}
|
||||||
|
initial={{ opacity: 0, x: -10 }}
|
||||||
|
animate={{ opacity: 1, x: 0 }}
|
||||||
|
transition={{ delay: i * 0.1 }}
|
||||||
|
className="flex gap-4"
|
||||||
|
>
|
||||||
|
<span className="text-slate-600 w-4 text-right select-none">{i + 1}</span>
|
||||||
|
<span className={line.color}>{line.text}</span>
|
||||||
|
</motion.div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Animated Cursors */}
|
||||||
|
<motion.div
|
||||||
|
animate={{ x: [0, 40, -20, 0], y: [0, 60, 20, 0] }}
|
||||||
|
transition={{ duration: 8, repeat: Infinity, ease: "easeInOut" }}
|
||||||
|
className="absolute top-20 left-40"
|
||||||
|
>
|
||||||
|
<div className="relative group">
|
||||||
|
<div className="w-1 h-5 bg-amber-400" />
|
||||||
|
<div className="absolute left-1 top-0 bg-amber-400 text-[#1E293B] text-[10px] px-1.5 py-0.5 rounded-sm whitespace-nowrap font-bold">
|
||||||
|
Priya_Dev
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
<motion.div
|
||||||
|
animate={{ x: [0, -30, 40, 0], y: [0, -20, 80, 0] }}
|
||||||
|
transition={{ duration: 12, repeat: Infinity, ease: "easeInOut", delay: 1 }}
|
||||||
|
className="absolute top-10 left-60"
|
||||||
|
>
|
||||||
|
<div className="relative group">
|
||||||
|
<div className="w-1 h-5 bg-indigo-400" />
|
||||||
|
<div className="absolute left-1 top-0 bg-indigo-400 text-white text-[10px] px-1.5 py-0.5 rounded-sm whitespace-nowrap font-bold">
|
||||||
|
Arjun_AI
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
117
src/components/react/Community.tsx
Normal file
117
src/components/react/Community.tsx
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
import { ArrowRight } from 'lucide-react';
|
||||||
|
import { ProfileCard, type Profile } from './ProfileCard';
|
||||||
|
|
||||||
|
const PROFILES: Profile[] = [
|
||||||
|
{
|
||||||
|
name: "The Student",
|
||||||
|
role: "Future-Proofing the Degree",
|
||||||
|
story: "Universities teach theory; the market demands shipping. Stop worrying about your GPA and start building an Agent portfolio that makes recruiters ignore your grades.",
|
||||||
|
badge: "Portfolio Builder",
|
||||||
|
image: "https://images.unsplash.com/photo-1539571696357-5a69c17a67c6?w=400&h=400&fit=crop",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "The IT Professional",
|
||||||
|
role: "Surviving the Shift",
|
||||||
|
story: "Afraid of AI automating your services job? Don't compete with it—manage it. Pivot from 'Legacy Maintenance' to 'AI Infrastructure Lead' by mastering MCP.",
|
||||||
|
badge: "AI Architect",
|
||||||
|
image: "https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=400&h=400&fit=crop",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "The Founder",
|
||||||
|
role: "Building an AI Workforce",
|
||||||
|
story: "Overwhelmed by the speed of tech? Stop hiring expensive agencies. Use our Squads to build your own custom AI tools and ship your MVP in weeks, not months.",
|
||||||
|
badge: "Solo Shipper",
|
||||||
|
image: "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=400&h=400&fit=crop",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const Community = () => {
|
||||||
|
return (
|
||||||
|
<section className="py-24">
|
||||||
|
<div className="container mx-auto px-6">
|
||||||
|
<div className="flex flex-col md:flex-row justify-between items-end mb-16 gap-6">
|
||||||
|
<div className="max-w-xl">
|
||||||
|
<h2 className="text-4xl font-bold font-heading mb-4 text-white">
|
||||||
|
From Anxiety to Action
|
||||||
|
</h2>
|
||||||
|
<p className="text-slate-400 font-sans">
|
||||||
|
The Gym is open for everyone. Whether you are starting out or leveling up, you have a
|
||||||
|
squad waiting for you.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<button className="text-amber-500 font-bold flex items-center gap-2 hover:text-amber-400 transition-colors cursor-pointer">
|
||||||
|
See all alumni <ArrowRight size={18} />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid md:grid-cols-3 gap-8">
|
||||||
|
{PROFILES.map((profile, i) => (
|
||||||
|
<ProfileCard key={i} profile={profile} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
id="build-season"
|
||||||
|
className="mt-20 p-12 rounded-[2rem] bg-gradient-to-br from-indigo-600/20 to-amber-600/10 border border-white/10 relative overflow-hidden scroll-mt-32"
|
||||||
|
>
|
||||||
|
<div className="relative z-10 flex flex-col md:flex-row items-center gap-10">
|
||||||
|
<div className="flex-1">
|
||||||
|
<h3 className="text-3xl font-bold font-heading mb-4 text-white">
|
||||||
|
Build Season #01 is approaching. 📣
|
||||||
|
</h3>
|
||||||
|
<p className="text-slate-300 text-lg mb-8 max-w-lg font-sans">
|
||||||
|
Don't build alone. Join a Squad of 4-5 builders to ship your first MCP Agent in 6
|
||||||
|
weeks. Whether you are a student looking for a portfolio piece or a pro updating
|
||||||
|
your skills—your Squad keeps you shipping.
|
||||||
|
</p>
|
||||||
|
<div className="flex flex-wrap gap-4">
|
||||||
|
<a
|
||||||
|
href="/apply-season"
|
||||||
|
className="bg-white text-slate-900 font-bold px-8 py-4 rounded-xl hover:bg-slate-200 transition-all cursor-pointer inline-block"
|
||||||
|
>
|
||||||
|
Apply for Season #01
|
||||||
|
</a>
|
||||||
|
<div className="flex items-center gap-4 px-6 text-sm text-slate-400 border-l border-white/10">
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<span className="font-bold text-white uppercase tracking-widest text-[10px]">
|
||||||
|
START DATE
|
||||||
|
</span>
|
||||||
|
<span>TBD</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="hidden lg:grid grid-cols-2 gap-4 flex-shrink-0">
|
||||||
|
<div className="p-4 bg-slate-900/60 rounded-xl border border-white/5 text-center">
|
||||||
|
<div className="text-2xl font-bold text-amber-500">Build an MCP Server</div>
|
||||||
|
<div className="text-[10px] text-slate-500 uppercase font-bold tracking-widest">
|
||||||
|
CURRENT MISSION
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="p-4 bg-slate-900/60 rounded-xl border border-white/5 text-center">
|
||||||
|
<div className="text-2xl font-bold text-indigo-400">4-6 Builders</div>
|
||||||
|
<div className="text-[10px] text-slate-500 uppercase font-bold tracking-widest">
|
||||||
|
SQUAD SIZE
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="p-4 bg-slate-900/60 rounded-xl border border-white/5 text-center">
|
||||||
|
<div className="text-2xl font-bold text-emerald-400">6 Weeks</div>
|
||||||
|
<div className="text-[10px] text-slate-500 uppercase font-bold tracking-widest">
|
||||||
|
DURATION
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="p-4 bg-slate-900/60 rounded-xl border border-white/5 text-center">
|
||||||
|
<div className="text-2xl font-bold text-purple-400">Free</div>
|
||||||
|
<div className="text-[10px] text-slate-500 uppercase font-bold tracking-widest">
|
||||||
|
COST
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* Background elements for this section */}
|
||||||
|
<div className="absolute top-0 right-0 w-full h-full bg-[radial-gradient(circle_at_top_right,rgba(99,102,241,0.1),transparent)] pointer-events-none" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
40
src/components/react/Features.tsx
Normal file
40
src/components/react/Features.tsx
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import { Tv, Network, Handshake } from 'lucide-react';
|
||||||
|
import { GlassCard } from './GlassCard';
|
||||||
|
|
||||||
|
export const Features = () => {
|
||||||
|
return (
|
||||||
|
<section className="py-24 bg-slate-900/50">
|
||||||
|
<div className="container mx-auto px-6">
|
||||||
|
<div className="text-center mb-16">
|
||||||
|
<h2 className="text-3xl md:text-4xl font-bold font-heading mb-4 text-white">
|
||||||
|
A Gym for Builders, Not a Classroom
|
||||||
|
</h2>
|
||||||
|
<p className="text-slate-400 max-w-2xl mx-auto font-sans">
|
||||||
|
Skip the generic videos. Join a community where the curriculum is "Building things that
|
||||||
|
matter."
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="grid md:grid-cols-3 gap-8">
|
||||||
|
<GlassCard
|
||||||
|
icon={Tv}
|
||||||
|
title="No More Tutorials"
|
||||||
|
text="Stop gathering 'knowledge' and start building skill. Tutorials make you feel smart while your skills stagnate. We ship from Day 1."
|
||||||
|
delay={0.1}
|
||||||
|
/>
|
||||||
|
<GlassCard
|
||||||
|
icon={Network}
|
||||||
|
title="Protocol First"
|
||||||
|
text="Master the plumbing of the future. Deep dive into Model Context Protocol (MCP), Universal Commerce Protocol (UCP), and Agentic frameworks."
|
||||||
|
delay={0.2}
|
||||||
|
/>
|
||||||
|
<GlassCard
|
||||||
|
icon={Handshake}
|
||||||
|
title="Squad Mode"
|
||||||
|
text="Never build alone. Match with creators who share your stack. Weekly sprints, peer reviews, and collaborative repos."
|
||||||
|
delay={0.3}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
26
src/components/react/GlassCard.tsx
Normal file
26
src/components/react/GlassCard.tsx
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { motion } from 'framer-motion';
|
||||||
|
import type { LucideIcon } from 'lucide-react';
|
||||||
|
|
||||||
|
interface GlassCardProps {
|
||||||
|
icon: LucideIcon;
|
||||||
|
title: string;
|
||||||
|
text: string;
|
||||||
|
delay?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const GlassCard = ({ icon: Icon, title, text, delay = 0 }: GlassCardProps) => (
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
transition={{ duration: 0.6, delay }}
|
||||||
|
className="relative group p-8 rounded-2xl border border-white/10 bg-white/5 backdrop-blur-xl hover:bg-white/10 transition-all duration-300"
|
||||||
|
>
|
||||||
|
<div className="mb-6 w-12 h-12 flex items-center justify-center rounded-lg bg-indigo-500/20 text-indigo-400 group-hover:scale-110 transition-transform duration-300">
|
||||||
|
<Icon size={24} />
|
||||||
|
</div>
|
||||||
|
<h3 className="text-xl font-bold mb-3 text-white font-heading">{title}</h3>
|
||||||
|
<p className="text-slate-400 leading-relaxed font-sans">{text}</p>
|
||||||
|
<div className="absolute inset-0 border-2 border-transparent group-hover:border-indigo-500/30 rounded-2xl transition-all duration-300 pointer-events-none" />
|
||||||
|
</motion.div>
|
||||||
|
);
|
||||||
137
src/components/react/Hero.tsx
Normal file
137
src/components/react/Hero.tsx
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
import { motion } from 'framer-motion';
|
||||||
|
import { Zap, ChevronRight, Terminal } from 'lucide-react';
|
||||||
|
import { CodeWindow } from './CodeWindow';
|
||||||
|
|
||||||
|
export const Hero = () => {
|
||||||
|
return (
|
||||||
|
<section className="relative pt-32 pb-20 overflow-hidden">
|
||||||
|
{/* Background Grid Pattern */}
|
||||||
|
<div
|
||||||
|
className="absolute inset-0 z-0 opacity-10 pointer-events-none"
|
||||||
|
style={{
|
||||||
|
backgroundImage: 'radial-gradient(#6366F1 0.5px, transparent 0.5px)',
|
||||||
|
backgroundSize: '24px 24px',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div className="absolute top-0 right-0 w-[500px] h-[500px] bg-indigo-500/10 blur-[120px] rounded-full -z-10" />
|
||||||
|
<div className="absolute bottom-0 left-0 w-[500px] h-[500px] bg-amber-500/5 blur-[120px] rounded-full -z-10" />
|
||||||
|
|
||||||
|
<div className="container mx-auto px-6 relative z-10">
|
||||||
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-16 items-center">
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, x: -50 }}
|
||||||
|
animate={{ opacity: 1, x: 0 }}
|
||||||
|
transition={{ duration: 0.8 }}
|
||||||
|
>
|
||||||
|
<div className="inline-flex items-center gap-2 bg-indigo-500/10 border border-indigo-500/20 px-3 py-1 rounded-full text-indigo-400 text-xs font-bold mb-6 tracking-wide uppercase">
|
||||||
|
<Zap size={14} /> Future-Proof Your Career
|
||||||
|
</div>
|
||||||
|
<h1 className="text-4xl md:text-6xl lg:text-7xl font-bold font-heading leading-[1.1] mb-8 text-white">
|
||||||
|
Don't Fear the AI. <br />
|
||||||
|
<span className="text-transparent bg-clip-text bg-gradient-to-r from-amber-400 to-amber-600">
|
||||||
|
Build with AI.
|
||||||
|
</span>
|
||||||
|
</h1>
|
||||||
|
<p className="text-xl text-slate-400 mb-10 leading-relaxed max-w-xl font-sans">
|
||||||
|
The safe harbor for developers, students, and founders to stop watching tutorials and
|
||||||
|
start shipping. Master MCP, UCP, and Agents by building real products together.
|
||||||
|
</p>
|
||||||
|
<div className="flex flex-col sm:flex-row gap-4">
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
window.dispatchEvent(
|
||||||
|
new CustomEvent('open-join-modal', {
|
||||||
|
detail: { mode: 'opensource' },
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
className="w-full sm:w-auto bg-amber-500 hover:bg-amber-400 text-slate-900 font-bold px-8 py-4 rounded-xl transition-all flex items-center justify-center gap-2 group cursor-pointer"
|
||||||
|
>
|
||||||
|
Join the Community
|
||||||
|
</button>
|
||||||
|
<button className="w-full sm:w-auto border border-slate-700 hover:border-slate-500 bg-white/5 px-8 py-4 rounded-xl font-bold transition-all text-white flex items-center justify-center gap-2 cursor-pointer">
|
||||||
|
Read Manifesto
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-12 flex flex-col sm:flex-row items-start sm:items-center gap-6">
|
||||||
|
<div className="flex -space-x-3">
|
||||||
|
{[1, 2, 3, 4].map((i) => (
|
||||||
|
<div
|
||||||
|
key={i}
|
||||||
|
className="w-10 h-10 rounded-full border-2 border-slate-900 bg-slate-700 flex items-center justify-center overflow-hidden"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={`https://api.dicebear.com/7.x/avataaars/svg?seed=${i + 123}`}
|
||||||
|
alt="avatar"
|
||||||
|
className="w-full h-full object-cover"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
<div className="w-10 h-10 rounded-full border-2 border-slate-900 bg-indigo-600 flex items-center justify-center text-[10px] font-bold text-white">
|
||||||
|
+
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col sm:flex-row sm:items-center gap-2 sm:gap-0">
|
||||||
|
<p
|
||||||
|
className="text-sm text-slate-500 flex items-center gap-2"
|
||||||
|
style={{
|
||||||
|
fontWeight: '400',
|
||||||
|
fontStyle: 'normal',
|
||||||
|
color: '#90a1b9',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Join the Founding Class of 2026
|
||||||
|
</p>
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
const buildSection = document.getElementById('build-season');
|
||||||
|
buildSection?.scrollIntoView({
|
||||||
|
behavior: 'smooth',
|
||||||
|
block: 'center',
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
className="inline-flex items-center gap-1 px-3 py-1 rounded-full bg-amber-500/10 border border-amber-500/20 text-amber-500 text-xs font-bold hover:bg-amber-500/20 transition-all cursor-pointer sm:ml-2"
|
||||||
|
>
|
||||||
|
Learn More <ChevronRight size={14} />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, scale: 0.9 }}
|
||||||
|
animate={{ opacity: 1, scale: 1 }}
|
||||||
|
transition={{ duration: 0.8, delay: 0.2 }}
|
||||||
|
className="relative mt-12 lg:mt-0"
|
||||||
|
>
|
||||||
|
<div className="relative z-10">
|
||||||
|
<CodeWindow />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Decorative elements */}
|
||||||
|
<div className="absolute -top-12 -right-8 w-64 h-64 bg-indigo-500/20 rounded-full blur-[80px] -z-10" />
|
||||||
|
<div className="absolute -bottom-8 -left-12 w-48 h-48 bg-amber-500/10 rounded-full blur-[60px] -z-10" />
|
||||||
|
|
||||||
|
{/* Floating Badge */}
|
||||||
|
<motion.div
|
||||||
|
animate={{ y: [0, -10, 0] }}
|
||||||
|
transition={{ duration: 4, repeat: Infinity, ease: 'easeInOut' }}
|
||||||
|
className="absolute -bottom-6 right-10 z-20 bg-slate-800 border border-slate-700 p-4 rounded-xl shadow-2xl flex items-center gap-3"
|
||||||
|
>
|
||||||
|
<div className="p-2 bg-amber-500/10 text-amber-500 rounded-lg">
|
||||||
|
<Terminal size={20} />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div className="text-[10px] text-slate-500 uppercase font-bold tracking-widest">
|
||||||
|
Active Stack
|
||||||
|
</div>
|
||||||
|
<div className="text-sm font-bold text-white">Gemini 3 Pro + MCP</div>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
179
src/components/react/JoinModal.tsx
Normal file
179
src/components/react/JoinModal.tsx
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
import { useState, useEffect } from "react";
|
||||||
|
import { motion, AnimatePresence } from "framer-motion";
|
||||||
|
import { X, Check } from "lucide-react";
|
||||||
|
|
||||||
|
export const JoinModal = () => {
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
const [isSubmitted, setIsSubmitted] = useState(false);
|
||||||
|
const [contentMode, setContentMode] = useState<'default' | 'opensource'>('default');
|
||||||
|
const [source, setSource] = useState('gitea_contribute');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handleOpen = (event: CustomEvent) => {
|
||||||
|
const mode = event.detail?.mode || 'default';
|
||||||
|
setContentMode(mode);
|
||||||
|
setSource(mode === 'opensource' ? 'community_join' : 'gitea_contribute');
|
||||||
|
setIsOpen(true);
|
||||||
|
};
|
||||||
|
window.addEventListener("open-join-modal", handleOpen as EventListener);
|
||||||
|
return () => window.removeEventListener("open-join-modal", handleOpen as EventListener);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleSubmit = (e: React.FormEvent) => {
|
||||||
|
// Allow default form submission for Netlify to handle redirect
|
||||||
|
setIsSubmitted(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AnimatePresence>
|
||||||
|
{isOpen && (
|
||||||
|
<div className="fixed inset-0 z-[100] flex items-center justify-center px-4">
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
animate={{ opacity: 1 }}
|
||||||
|
exit={{ opacity: 0 }}
|
||||||
|
onClick={() => setIsOpen(false)}
|
||||||
|
className="absolute inset-0 bg-slate-950/80 backdrop-blur-sm"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, scale: 0.95, y: 20 }}
|
||||||
|
animate={{ opacity: 1, scale: 1, y: 0 }}
|
||||||
|
exit={{ opacity: 0, scale: 0.95, y: 20 }}
|
||||||
|
className="relative z-10 w-full max-w-2xl bg-slate-900 border border-white/10 rounded-2xl shadow-2xl overflow-hidden"
|
||||||
|
>
|
||||||
|
<div className="absolute top-4 right-4 z-20">
|
||||||
|
<button
|
||||||
|
onClick={() => setIsOpen(false)}
|
||||||
|
className="p-2 text-slate-400 hover:text-white hover:bg-white/10 rounded-full transition-colors cursor-pointer"
|
||||||
|
>
|
||||||
|
<X size={20} />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col md:flex-row h-full">
|
||||||
|
{/* Content Side */}
|
||||||
|
<div className="p-8 md:p-10 flex-1">
|
||||||
|
<h2 className="text-3xl font-bold font-heading text-white mb-6">
|
||||||
|
{contentMode === 'opensource' ? "Build on Open Ground." : "Claim Your Locker."}
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div className="space-y-4 text-slate-300 text-sm leading-relaxed mb-8">
|
||||||
|
<p>
|
||||||
|
{contentMode === 'opensource'
|
||||||
|
? "We believe in tools that grant freedom, not locked gardens. Join a network of builders who value ownership over convenience."
|
||||||
|
: "We don't build on rented land. While the rest of the world relies on centralized platforms, we host our own infrastructure."}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h4 className="font-bold text-white mb-1">
|
||||||
|
{contentMode === 'opensource' ? "Why Open Source?" : "Why Gitea?"}
|
||||||
|
</h4>
|
||||||
|
<ul className="space-y-2 list-disc pl-4 marker:text-amber-500">
|
||||||
|
{contentMode === 'opensource' ? (
|
||||||
|
<>
|
||||||
|
<li>
|
||||||
|
<b className="text-slate-200">Transparency:</b> Code that can be audited, trusted, and improved by everyone. No black boxes.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<b className="text-slate-200">Collaboration:</b> A global community of builders pushing the boundaries together.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<b className="text-slate-200">Longevity:</b> Software that survives its creators. We build for the long game.
|
||||||
|
</li>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<li>
|
||||||
|
<b className="text-slate-200">Sovereignty:</b> We own our data, our code, and our community. No corporate shutdowns or VC pivots.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<b className="text-slate-200">Focus:</b> A noise-free environment designed purely for shipping products. No vanity metrics, just commits.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<b className="text-slate-200">The Badge:</b> Access is earned. having an <code className="bg-slate-800 px-1 py-0.5 rounded text-indigo-400">movecompeteplay gitea access</code> is a mark of a serious builder.
|
||||||
|
</li>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<blockquote className="hidden md:block border-l-2 border-amber-500 pl-4 italic text-slate-400 my-4">
|
||||||
|
{contentMode === 'opensource'
|
||||||
|
? "\"Open source is not just a license; it's a statement of independence.\""
|
||||||
|
: "\"The code won't write itself. The servers won't maintain themselves. We do it the hard way because it's the right way.\""}
|
||||||
|
</blockquote>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form
|
||||||
|
name="join-community"
|
||||||
|
method="POST"
|
||||||
|
action="/success"
|
||||||
|
data-netlify="true"
|
||||||
|
netlify-honeypot="bot-field"
|
||||||
|
className="space-y-4"
|
||||||
|
>
|
||||||
|
<input type="hidden" name="form-name" value="join-community" />
|
||||||
|
<input type="hidden" name="source" value={source} />
|
||||||
|
<p className="hidden">
|
||||||
|
<label>
|
||||||
|
Don’t fill this out if you’re human: <input name="bot-field" />
|
||||||
|
</label>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="flex flex-col md:flex-row gap-4">
|
||||||
|
<div className="flex-1">
|
||||||
|
<label htmlFor="email" className="block text-xs font-bold text-slate-500 uppercase tracking-widest mb-2">
|
||||||
|
Email Address
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
name="email"
|
||||||
|
type="email"
|
||||||
|
id="email"
|
||||||
|
required
|
||||||
|
placeholder="builder@example.com"
|
||||||
|
className="w-full bg-slate-950 border border-slate-700 rounded-xl px-4 py-3 text-white placeholder:text-slate-600 focus:outline-none focus:border-amber-500 transition-colors"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="flex-1">
|
||||||
|
<label htmlFor="social" className="block text-xs font-bold text-slate-500 uppercase tracking-widest mb-2">
|
||||||
|
LinkedIn / Twitter URL
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
name="social"
|
||||||
|
type="url"
|
||||||
|
id="social"
|
||||||
|
placeholder="twitter.com/builder"
|
||||||
|
className="w-full bg-slate-950 border border-slate-700 rounded-xl px-4 py-3 text-white placeholder:text-slate-600 focus:outline-none focus:border-amber-500 transition-colors"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label htmlFor="project" className="block text-xs font-bold text-slate-500 uppercase tracking-widest mb-2">
|
||||||
|
What will you build?
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
name="project"
|
||||||
|
type="text"
|
||||||
|
id="project"
|
||||||
|
required
|
||||||
|
placeholder="A new agent framework..."
|
||||||
|
className="w-full bg-slate-950 border border-slate-700 rounded-xl px-4 py-3 text-white placeholder:text-slate-600 focus:outline-none focus:border-amber-500 transition-colors"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
className="w-full bg-amber-500 hover:bg-amber-400 text-slate-900 font-bold py-4 rounded-xl transition-all hover:scale-[1.02] active:scale-[0.98] shadow-lg shadow-amber-500/20 cursor-pointer"
|
||||||
|
>
|
||||||
|
Request Access
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</AnimatePresence>
|
||||||
|
);
|
||||||
|
};
|
||||||
31
src/components/react/ProfileCard.tsx
Normal file
31
src/components/react/ProfileCard.tsx
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import { motion } from 'framer-motion';
|
||||||
|
|
||||||
|
export interface Profile {
|
||||||
|
name: string;
|
||||||
|
role: string;
|
||||||
|
story: string;
|
||||||
|
badge: string;
|
||||||
|
image: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ProfileCard = ({ profile }: { profile: Profile }) => (
|
||||||
|
<motion.div
|
||||||
|
whileHover={{ y: -5 }}
|
||||||
|
className="bg-slate-800/40 border border-slate-700/50 p-6 rounded-2xl flex flex-col items-center text-center group"
|
||||||
|
>
|
||||||
|
<div className="relative mb-6">
|
||||||
|
<div className="w-24 h-24 rounded-full overflow-hidden border-2 border-indigo-500/30 group-hover:border-indigo-400 transition-colors">
|
||||||
|
<img src={profile.image} alt={profile.name} className="w-full h-full object-cover" />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="absolute -bottom-2 -right-2 bg-amber-500 text-[#1E293B] text-[10px] font-bold px-2 py-1 rounded-full uppercase tracking-tighter shadow-lg"
|
||||||
|
style={{ fontSize: "9px" }}
|
||||||
|
>
|
||||||
|
{profile.badge}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h4 className="text-white font-bold text-lg mb-1">{profile.name}</h4>
|
||||||
|
<p className="text-indigo-400 text-sm font-mono mb-4">{profile.role}</p>
|
||||||
|
<p className="text-slate-400 text-sm italic">"{profile.story}"</p>
|
||||||
|
</motion.div>
|
||||||
|
);
|
||||||
29
src/layouts/Layout.astro
Normal file
29
src/layouts/Layout.astro
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
import "../styles/global.css";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
title: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { title } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en" class="dark">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta
|
||||||
|
name="description"
|
||||||
|
content="Move. Compete. Play. — The future belongs to the builders."
|
||||||
|
/>
|
||||||
|
<meta name="viewport" content="width=device-width" />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
|
<meta name="generator" content={Astro.generator} />
|
||||||
|
<title>{title}</title>
|
||||||
|
</head>
|
||||||
|
<body
|
||||||
|
class="bg-background text-foreground font-sans min-h-screen selection:bg-amber-500/30 selection:text-amber-200"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
6
src/lib/utils.ts
Normal file
6
src/lib/utils.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { type ClassValue, clsx } from 'clsx';
|
||||||
|
import { twMerge } from 'tailwind-merge';
|
||||||
|
|
||||||
|
export function cn(...inputs: ClassValue[]) {
|
||||||
|
return twMerge(clsx(inputs));
|
||||||
|
}
|
||||||
233
src/pages/apply-season.astro
Normal file
233
src/pages/apply-season.astro
Normal file
@@ -0,0 +1,233 @@
|
|||||||
|
---
|
||||||
|
import Layout from "../layouts/Layout.astro";
|
||||||
|
---
|
||||||
|
|
||||||
|
<Layout title="Draft Day: Season #01 - Move. Compete. Play.">
|
||||||
|
<div class="min-h-screen bg-slate-950 py-20 px-4 md:px-0">
|
||||||
|
<div class="container mx-auto max-w-2xl">
|
||||||
|
{/* Header */}
|
||||||
|
<div class="mb-12">
|
||||||
|
<div
|
||||||
|
class="inline-flex items-center gap-2 bg-amber-500/10 border border-amber-500/20 px-3 py-1 rounded-full text-amber-500 text-xs font-bold mb-6 tracking-wide uppercase"
|
||||||
|
>
|
||||||
|
Cohort #01 Applications Open
|
||||||
|
</div>
|
||||||
|
<h1
|
||||||
|
class="text-4xl md:text-5xl font-bold font-heading text-white mb-6"
|
||||||
|
>
|
||||||
|
Draft Day: Season #01
|
||||||
|
</h1>
|
||||||
|
<p class="text-xl text-slate-400 font-sans mb-8">
|
||||||
|
6 Weeks. 1 Squad. 1 Shipped Product.
|
||||||
|
</p>
|
||||||
|
<blockquote
|
||||||
|
class="border-l-4 border-indigo-500 pl-6 py-2 italic text-slate-300 bg-indigo-500/5 rounded-r-xl"
|
||||||
|
>
|
||||||
|
"We curate teams based on skill, timezone, and ambition. You
|
||||||
|
are not just joining a server; you are joining a roster."
|
||||||
|
</blockquote>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Form */}
|
||||||
|
<form
|
||||||
|
name="draft-application"
|
||||||
|
method="POST"
|
||||||
|
action="/success"
|
||||||
|
data-netlify="true"
|
||||||
|
netlify-honeypot="bot-field"
|
||||||
|
class="space-y-12 bg-slate-900/50 p-8 md:p-12 rounded-3xl border border-white/5"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="hidden"
|
||||||
|
name="form-name"
|
||||||
|
value="draft-application"
|
||||||
|
/>
|
||||||
|
<p class="hidden">
|
||||||
|
<label>
|
||||||
|
Don’t fill this out if you’re human: <input
|
||||||
|
name="bot-field"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* 1. Identity */}
|
||||||
|
<div class="space-y-6">
|
||||||
|
<h2
|
||||||
|
class="text-2xl font-bold text-white border-b border-white/10 pb-4"
|
||||||
|
>
|
||||||
|
1. Identity
|
||||||
|
</h2>
|
||||||
|
<div class="grid md:grid-cols-2 gap-6">
|
||||||
|
<div class="space-y-2">
|
||||||
|
<label
|
||||||
|
for="pilot-name"
|
||||||
|
class="block text-xs font-bold text-slate-400 uppercase tracking-widest"
|
||||||
|
>
|
||||||
|
Pilot Name
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="pilot-name"
|
||||||
|
name="pilot-name"
|
||||||
|
required
|
||||||
|
class="w-full bg-slate-950 border border-slate-700 rounded-xl px-4 py-3 text-white placeholder:text-slate-600 focus:outline-none focus:border-amber-500 transition-colors"
|
||||||
|
placeholder="Callsign"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="space-y-2">
|
||||||
|
<label
|
||||||
|
for="email"
|
||||||
|
class="block text-xs font-bold text-slate-400 uppercase tracking-widest"
|
||||||
|
>
|
||||||
|
Comms (Email)
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
id="email"
|
||||||
|
name="email"
|
||||||
|
required
|
||||||
|
class="w-full bg-slate-950 border border-slate-700 rounded-xl px-4 py-3 text-white placeholder:text-slate-600 focus:outline-none focus:border-amber-500 transition-colors"
|
||||||
|
placeholder="hacker@example.com"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 2. Squad Fit */}
|
||||||
|
<div class="space-y-6">
|
||||||
|
<h2
|
||||||
|
class="text-2xl font-bold text-white border-b border-white/10 pb-4"
|
||||||
|
>
|
||||||
|
2. Squad Fit
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div class="space-y-4">
|
||||||
|
<label
|
||||||
|
class="block text-xs font-bold text-slate-400 uppercase tracking-widest"
|
||||||
|
>
|
||||||
|
What is your Primary Role?
|
||||||
|
</label>
|
||||||
|
<div class="space-y-3">
|
||||||
|
<label
|
||||||
|
class="flex items-start gap-3 p-4 bg-slate-950 rounded-xl border border-slate-800 cursor-pointer hover:border-amber-500/50 transition-colors group"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="role"
|
||||||
|
value="engineer"
|
||||||
|
required
|
||||||
|
class="mt-1 text-amber-500 focus:ring-amber-500 bg-slate-900 border-slate-700"
|
||||||
|
/>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="font-bold text-white group-hover:text-amber-500 transition-colors"
|
||||||
|
>
|
||||||
|
Engineer
|
||||||
|
</div>
|
||||||
|
<div class="text-sm text-slate-400">
|
||||||
|
Full Stack, Backend, AI
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
<label
|
||||||
|
class="flex items-start gap-3 p-4 bg-slate-950 rounded-xl border border-slate-800 cursor-pointer hover:border-amber-500/50 transition-colors group"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="role"
|
||||||
|
value="designer"
|
||||||
|
required
|
||||||
|
class="mt-1 text-amber-500 focus:ring-amber-500 bg-slate-900 border-slate-700"
|
||||||
|
/>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="font-bold text-white group-hover:text-amber-500 transition-colors"
|
||||||
|
>
|
||||||
|
Designer
|
||||||
|
</div>
|
||||||
|
<div class="text-sm text-slate-400">
|
||||||
|
UI/UX, Frontend Polish
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
<label
|
||||||
|
class="flex items-start gap-3 p-4 bg-slate-950 rounded-xl border border-slate-800 cursor-pointer hover:border-amber-500/50 transition-colors group"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="role"
|
||||||
|
value="operator"
|
||||||
|
required
|
||||||
|
class="mt-1 text-amber-500 focus:ring-amber-500 bg-slate-900 border-slate-700"
|
||||||
|
/>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="font-bold text-white group-hover:text-amber-500 transition-colors"
|
||||||
|
>
|
||||||
|
Operator
|
||||||
|
</div>
|
||||||
|
<div class="text-sm text-slate-400">
|
||||||
|
PM, Growth, Documentation
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="space-y-2">
|
||||||
|
<label
|
||||||
|
for="tech-stack"
|
||||||
|
class="block text-xs font-bold text-slate-400 uppercase tracking-widest"
|
||||||
|
>
|
||||||
|
Your Tech Stack
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="tech-stack"
|
||||||
|
name="tech-stack"
|
||||||
|
required
|
||||||
|
class="w-full bg-slate-950 border border-slate-700 rounded-xl px-4 py-3 text-white placeholder:text-slate-600 focus:outline-none focus:border-amber-500 transition-colors"
|
||||||
|
placeholder="e.g., Next.js, Python/FastAPI, Flutter"
|
||||||
|
/>
|
||||||
|
<p class="text-xs text-slate-500">
|
||||||
|
Be specific so we can match you with compatible
|
||||||
|
builders.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 3. The Pledge */}
|
||||||
|
<div class="space-y-6">
|
||||||
|
<h2
|
||||||
|
class="text-2xl font-bold text-white border-b border-white/10 pb-4"
|
||||||
|
>
|
||||||
|
3. The Pledge
|
||||||
|
</h2>
|
||||||
|
<label
|
||||||
|
class="flex items-start gap-4 p-4 bg-amber-500/5 border border-amber-500/20 rounded-xl cursor-pointer"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
name="pledge"
|
||||||
|
required
|
||||||
|
class="mt-1 w-5 h-5 text-amber-500 rounded focus:ring-amber-500 bg-slate-900 border-slate-700"
|
||||||
|
/>
|
||||||
|
<span class="text-slate-300 text-sm leading-relaxed">
|
||||||
|
I commit to the 6-week sprint. I understand that if
|
||||||
|
I ghost my squad, I will be banned from future
|
||||||
|
seasons. This is a team sport.
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 4. CTA */}
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="w-full bg-amber-500 hover:bg-amber-400 text-slate-900 font-bold py-5 text-lg rounded-xl transition-all hover:scale-[1.01] active:scale-[0.99] shadow-lg shadow-amber-500/20 cursor-pointer flex items-center justify-center gap-2"
|
||||||
|
>
|
||||||
|
Submit Application <span class="text-xl">-></span>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Layout>
|
||||||
@@ -1,17 +1,22 @@
|
|||||||
---
|
---
|
||||||
|
import Layout from "../layouts/Layout.astro";
|
||||||
|
import Navbar from "../components/Navbar.astro";
|
||||||
|
import Footer from "../components/Footer.astro";
|
||||||
|
import TechMarquee from "../components/TechMarquee.astro";
|
||||||
|
import { Hero } from "../components/react/Hero";
|
||||||
|
import { Features } from "../components/react/Features";
|
||||||
|
import { Community } from "../components/react/Community";
|
||||||
|
import { JoinModal } from "../components/react/JoinModal";
|
||||||
|
---
|
||||||
|
|
||||||
---
|
<Layout title="Move. Compete. Play. — The future belongs to the builders.">
|
||||||
|
<Navbar />
|
||||||
<html lang="en">
|
<JoinModal client:load />
|
||||||
<head>
|
<main>
|
||||||
<meta charset="utf-8" />
|
<Hero client:load />
|
||||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
<Features client:visible />
|
||||||
<link rel="icon" href="/favicon.ico" />
|
<TechMarquee />
|
||||||
<meta name="viewport" content="width=device-width" />
|
<Community client:visible />
|
||||||
<meta name="generator" content={Astro.generator} />
|
</main>
|
||||||
<title>Astro</title>
|
<Footer />
|
||||||
</head>
|
</Layout>
|
||||||
<body>
|
|
||||||
<h1>Astro</h1>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|||||||
51
src/pages/success.astro
Normal file
51
src/pages/success.astro
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
---
|
||||||
|
import Layout from "../layouts/Layout.astro";
|
||||||
|
import { Check } from "lucide-react";
|
||||||
|
---
|
||||||
|
|
||||||
|
<Layout title="Request Received - Move. Compete. Play.">
|
||||||
|
<div class="min-h-screen bg-slate-950 flex items-center justify-center p-4">
|
||||||
|
<div
|
||||||
|
class="max-w-md w-full bg-slate-900 border border-white/10 rounded-2xl p-8 md:p-12 text-center shadow-2xl relative overflow-hidden"
|
||||||
|
>
|
||||||
|
{/* Background decoration */}
|
||||||
|
<div
|
||||||
|
class="absolute top-0 right-0 w-64 h-64 bg-indigo-500/10 rounded-full blur-[80px] -z-10"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="absolute bottom-0 left-0 w-48 h-48 bg-amber-500/5 rounded-full blur-[60px] -z-10"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="w-16 h-16 bg-emerald-500/10 rounded-full flex items-center justify-center mx-auto mb-6 border border-emerald-500/20"
|
||||||
|
>
|
||||||
|
<Check class="text-emerald-500" size={32} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h1 class="text-3xl font-bold font-heading text-white mb-4">
|
||||||
|
You're in the Queue.
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<div class="space-y-4 text-slate-400 text-sm leading-relaxed mb-8">
|
||||||
|
<p>
|
||||||
|
We've received your request for a locker. Our team reviews
|
||||||
|
every application manually to ensure the quality of the
|
||||||
|
community.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Keep an eye on your inbox. If you have the code, you'll get
|
||||||
|
the keys.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a
|
||||||
|
href="/"
|
||||||
|
class="inline-block w-full bg-amber-500 hover:bg-amber-400 text-slate-900 font-bold py-4 rounded-xl transition-all hover:scale-[1.02] active:scale-[0.98] shadow-lg shadow-amber-500/20 cursor-pointer"
|
||||||
|
>
|
||||||
|
Return to Base
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Layout>
|
||||||
@@ -1 +1,142 @@
|
|||||||
@import "tailwindcss";
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Space+Grotesk:wght@400;500;600;700&display=swap');
|
||||||
|
@import "tailwindcss";
|
||||||
|
|
||||||
|
@plugin "tailwindcss-animate";
|
||||||
|
|
||||||
|
@custom-variant dark (&:is(.dark *));
|
||||||
|
|
||||||
|
@theme inline {
|
||||||
|
--color-background: var(--background);
|
||||||
|
--color-foreground: var(--foreground);
|
||||||
|
--font-sans: "Inter", sans-serif;
|
||||||
|
--font-heading: "Space Grotesk", sans-serif;
|
||||||
|
--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: var(--radius-sm);
|
||||||
|
--radius-md: var(--radius-md);
|
||||||
|
--radius-lg: var(--radius-lg);
|
||||||
|
--radius-xl: var(--radius-xl);
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--card: #F8FAFC;
|
||||||
|
--ring: #FE9A00;
|
||||||
|
--input: #E2E8F0;
|
||||||
|
--muted: #CBD5E1;
|
||||||
|
--accent: #FE9A00;
|
||||||
|
--border: #E2E8F0;
|
||||||
|
--chart-1: #293445;
|
||||||
|
--chart-2: #FE9A00;
|
||||||
|
--chart-3: #10B981;
|
||||||
|
--chart-4: #F59E0B;
|
||||||
|
--chart-5: #3B82F6;
|
||||||
|
--popover: #FFFFFF;
|
||||||
|
--primary: #293445;
|
||||||
|
--sidebar: #F8FAFC;
|
||||||
|
--secondary: #E2E8F0;
|
||||||
|
--background: #FFFFFF;
|
||||||
|
--foreground: #1E293B;
|
||||||
|
--destructive: #EF4444;
|
||||||
|
--sidebar-ring: #FE9A00;
|
||||||
|
--sidebar-accent: #FE9A00;
|
||||||
|
--sidebar-border: #E2E8F0;
|
||||||
|
--card-foreground: #1E293B;
|
||||||
|
--sidebar-primary: #293445;
|
||||||
|
--muted-foreground: #64748B;
|
||||||
|
--accent-foreground: #1E293B;
|
||||||
|
--popover-foreground: #1E293B;
|
||||||
|
--primary-foreground: #FFFFFF;
|
||||||
|
--sidebar-foreground: #1E293B;
|
||||||
|
--secondary-foreground: #1E293B;
|
||||||
|
--destructive-foreground: #FFFFFF;
|
||||||
|
--sidebar-accent-foreground: #1E293B;
|
||||||
|
--sidebar-primary-foreground: #FFFFFF;
|
||||||
|
--radius: 0rem;
|
||||||
|
--shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
|
||||||
|
--font-body: Inter;
|
||||||
|
--radius-lg: 0.875rem;
|
||||||
|
--radius-md: 0.5rem;
|
||||||
|
--radius-sm: 0.25rem;
|
||||||
|
--radius-xl: 1rem;
|
||||||
|
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
||||||
|
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
||||||
|
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
||||||
|
--shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
|
||||||
|
--shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25);
|
||||||
|
--font-heading: Space Grotesk;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark {
|
||||||
|
--card: #293445;
|
||||||
|
--ring: #FE9A00;
|
||||||
|
--input: #334155;
|
||||||
|
--muted: #475569;
|
||||||
|
--accent: #FE9A00;
|
||||||
|
--border: #334155;
|
||||||
|
--chart-1: #293445;
|
||||||
|
--chart-2: #FE9A00;
|
||||||
|
--chart-3: #34D399;
|
||||||
|
--chart-4: #FBBF24;
|
||||||
|
--chart-5: #60A5FA;
|
||||||
|
--popover: #293445;
|
||||||
|
--primary: #293445;
|
||||||
|
--sidebar: #1E293B;
|
||||||
|
--secondary: #334155;
|
||||||
|
--background: #1E293B;
|
||||||
|
--foreground: #F1F5F9;
|
||||||
|
--destructive: #DC2626;
|
||||||
|
--sidebar-ring: #FE9A00;
|
||||||
|
--sidebar-accent: #FE9A00;
|
||||||
|
--sidebar-border: #334155;
|
||||||
|
--card-foreground: #F1F5F9;
|
||||||
|
--sidebar-primary: #293445;
|
||||||
|
--muted-foreground: #CBD5E1;
|
||||||
|
--accent-foreground: #1E293B;
|
||||||
|
--popover-foreground: #F1F5F9;
|
||||||
|
--primary-foreground: #FFFFFF;
|
||||||
|
--sidebar-foreground: #F1F5F9;
|
||||||
|
--secondary-foreground: #F1F5F9;
|
||||||
|
--destructive-foreground: #FFFFFF;
|
||||||
|
--sidebar-accent-foreground: #1E293B;
|
||||||
|
--sidebar-primary-foreground: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
@layer base {
|
||||||
|
* {
|
||||||
|
@apply border-border outline-ring/50;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
@apply bg-background text-foreground;
|
||||||
|
font-family: var(--font-body);
|
||||||
|
}
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
}
|
||||||
|
}
|
||||||
74
syleguide.md
Normal file
74
syleguide.md
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
# Move. Compete. Play. — Design System
|
||||||
|
|
||||||
|
**Version:** 1.0 (MVP)
|
||||||
|
**Theme:** Warm Futurism / The Developer Gym
|
||||||
|
**Vibe:** Dark, focused, high-performance, but welcoming. Think "Nike Pro meets VS Code."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Color Palette
|
||||||
|
|
||||||
|
### **Primary (The Gym Floor)**
|
||||||
|
* **Slate 950 (`#020617`):** The main background. Deep, infinite, focused.
|
||||||
|
* **Slate 900 (`#0f172a`):** Surface / Cards. Slightly elevated to create depth.
|
||||||
|
* **Slate 50 (`#f8fafc`):** Primary Text. High contrast but not harsh white.
|
||||||
|
|
||||||
|
### **Accent (The Energy)**
|
||||||
|
* **Amber 500 (`#f59e0b`):** "The Spark." Used for primary buttons, active states, and key highlights.
|
||||||
|
* **Amber 400 (`#fbbf24`):** Hover states and glowing text effects.
|
||||||
|
* **Emerald 500 (`#10b981`):** "Success." Used for passing tests, deployed status, and growth metrics.
|
||||||
|
|
||||||
|
### **Gradients (The Atmosphere)**
|
||||||
|
* **The Warm Glow:** `bg-gradient-to-r from-amber-500/20 to-transparent` (Used for background blobs).
|
||||||
|
* **The Glass Surface:** `bg-slate-900/50 backdrop-blur-md border border-slate-800` (Used for HUDs and floating navs).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Typography
|
||||||
|
|
||||||
|
**Font Family:** `Inter` (Sans-serif) for UI / `Calistoga` (Serif) for Headlines (Optional).
|
||||||
|
|
||||||
|
* **H1 (Hero):** Text-5xl / Bold / Tight Tracking.
|
||||||
|
* *Usage:* Landing page main statement.
|
||||||
|
* **H2 (Section):** Text-3xl / Semibold.
|
||||||
|
* *Usage:* "Build Seasons," "Leaderboard."
|
||||||
|
* **Body:** Text-base / Text-slate-400.
|
||||||
|
* *Usage:* Paragraphs. Easy to read, low eye strain.
|
||||||
|
* **Mono:** `JetBrains Mono` or `Fira Code`.
|
||||||
|
* *Usage:* Code snippets, terminal outputs, and data values.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Core Components
|
||||||
|
|
||||||
|
### **Buttons**
|
||||||
|
* **Primary (Action):**
|
||||||
|
* `bg-amber-500 text-slate-950 font-bold px-6 py-3 rounded-lg hover:bg-amber-400 transition-all`
|
||||||
|
* *Effect:* Subtle shadow glow on hover.
|
||||||
|
* **Secondary (Ghost):**
|
||||||
|
* `border border-slate-700 text-slate-300 px-6 py-3 rounded-lg hover:border-slate-500 hover:text-white transition-all`
|
||||||
|
|
||||||
|
### **Cards (Bento Grid Style)**
|
||||||
|
* **Container:** `bg-slate-900 border border-slate-800 rounded-xl p-6`
|
||||||
|
* **Hover Effect:** Border color shifts to `slate-600` or subtle `amber-500/20` glow.
|
||||||
|
* **Content:** Icon top-left, heavy bold title, muted description.
|
||||||
|
|
||||||
|
### **Badges / Tags**
|
||||||
|
* **Status (Live):** `bg-green-500/10 text-green-400 border border-green-500/20 rounded-full px-3 py-1 text-xs uppercase tracking-wider`
|
||||||
|
* **Tag (Tech):** `bg-slate-800 text-slate-400 border border-slate-700 rounded-md px-2 py-1 text-xs font-mono`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Imagery & Effects
|
||||||
|
|
||||||
|
* **Noise Texture:** A subtle grain overlay (5% opacity) to prevent the dark background from looking "flat."
|
||||||
|
* **Glow Orbs:** Blurred circles of Amber or Indigo positioned behind text to separate it from the background.
|
||||||
|
* **Grid Lines:** Very faint (`slate-800/50`) background grid patterns to reinforce the "engineering" aesthetic.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Tone of Voice
|
||||||
|
|
||||||
|
* **Direct & Action-Oriented:** "Ship Code," "Deploy Now," "Join the League."
|
||||||
|
* **No Fluff:** Avoid corporate jargon like "synergy" or "innovative solutions."
|
||||||
|
* **Encouraging but Tough:** "The code won't write itself." / "Respect the grind."
|
||||||
24
ui_mockup/.gitignore
vendored
Normal file
24
ui_mockup/.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
30
ui_mockup/.prettierignore
Normal file
30
ui_mockup/.prettierignore
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# Build outputs
|
||||||
|
dist/
|
||||||
|
build/
|
||||||
|
out/
|
||||||
|
|
||||||
|
# Dependencies
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Cache
|
||||||
|
.eslintcache
|
||||||
|
.cache/
|
||||||
|
|
||||||
|
# Coverage
|
||||||
|
coverage/
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
.DS_Store
|
||||||
|
.env*
|
||||||
|
!.env.example
|
||||||
|
|
||||||
|
# Debug
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# TypeScript
|
||||||
|
*.tsbuildinfo
|
||||||
10
ui_mockup/.prettierrc
Normal file
10
ui_mockup/.prettierrc
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": true,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"printWidth": 100,
|
||||||
|
"bracketSpacing": true,
|
||||||
|
"arrowParens": "avoid",
|
||||||
|
"endOfLine": "lf"
|
||||||
|
}
|
||||||
21
ui_mockup/components.json
Normal file
21
ui_mockup/components.json
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://ui.shadcn.com/schema.json",
|
||||||
|
"style": "new-york",
|
||||||
|
"rsc": false,
|
||||||
|
"tsx": true,
|
||||||
|
"tailwind": {
|
||||||
|
"config": "",
|
||||||
|
"css": "src/index.css",
|
||||||
|
"baseColor": "neutral",
|
||||||
|
"cssVariables": true,
|
||||||
|
"prefix": ""
|
||||||
|
},
|
||||||
|
"aliases": {
|
||||||
|
"components": "@/components",
|
||||||
|
"utils": "@/lib/utils",
|
||||||
|
"ui": "@/components/ui",
|
||||||
|
"lib": "@/lib",
|
||||||
|
"hooks": "@/hooks"
|
||||||
|
},
|
||||||
|
"iconLibrary": "lucide"
|
||||||
|
}
|
||||||
26
ui_mockup/eslint.config.js
Normal file
26
ui_mockup/eslint.config.js
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import js from '@eslint/js';
|
||||||
|
import globals from 'globals';
|
||||||
|
import reactHooks from 'eslint-plugin-react-hooks';
|
||||||
|
import reactRefresh from 'eslint-plugin-react-refresh';
|
||||||
|
import tseslint from 'typescript-eslint';
|
||||||
|
|
||||||
|
export default tseslint.config(
|
||||||
|
{ ignores: ['dist'] },
|
||||||
|
{
|
||||||
|
extends: [js.configs.recommended, ...tseslint.configs.recommended],
|
||||||
|
files: ['**/*.{ts,tsx}'],
|
||||||
|
languageOptions: {
|
||||||
|
ecmaVersion: 2020,
|
||||||
|
globals: globals.browser,
|
||||||
|
},
|
||||||
|
plugins: {
|
||||||
|
'react-hooks': reactHooks,
|
||||||
|
'react-refresh': reactRefresh,
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
...reactHooks.configs.recommended.rules,
|
||||||
|
'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
|
||||||
|
'@typescript-eslint/no-unused-vars': 'off',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
12
ui_mockup/index.html
Normal file
12
ui_mockup/index.html
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Move Compete Play Landing</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
65
ui_mockup/package.json
Normal file
65
ui_mockup/package.json
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
{
|
||||||
|
"name": "component-forge",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "tsc -b && vite build",
|
||||||
|
"lint": "eslint .",
|
||||||
|
"preview": "vite preview",
|
||||||
|
"format": "prettier --write .",
|
||||||
|
"format:check": "prettier --check ."
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@dnd-kit/core": "^6.3.1",
|
||||||
|
"@dnd-kit/modifiers": "^9.0.0",
|
||||||
|
"@dnd-kit/sortable": "^10.0.0",
|
||||||
|
"@headless-tree/core": "^1.4.0",
|
||||||
|
"@headless-tree/react": "^1.4.0",
|
||||||
|
"@hookform/resolvers": "^5.2.1",
|
||||||
|
"@react-three/drei": "^10.0.6",
|
||||||
|
"@react-three/fiber": "^9.1.2",
|
||||||
|
"class-variance-authority": "^0.7.1",
|
||||||
|
"clsx": "^2.1.1",
|
||||||
|
"cmdk": "^1.1.1",
|
||||||
|
"date-fns": "^4.1.0",
|
||||||
|
"embla-carousel-react": "^8.6.0",
|
||||||
|
"framer-motion": "^12.4.10",
|
||||||
|
"input-otp": "^1.4.2",
|
||||||
|
"lucide-react": "^0.542.0",
|
||||||
|
"next-themes": "^0.4.6",
|
||||||
|
"radix-ui": "^1.4.3",
|
||||||
|
"react": "^19.0.0",
|
||||||
|
"react-day-picker": "^9.9.0",
|
||||||
|
"react-dom": "^19.0.0",
|
||||||
|
"react-hook-form": "^7.62.0",
|
||||||
|
"react-resizable-panels": "^3.0.5",
|
||||||
|
"recharts": "2.15.4",
|
||||||
|
"sonner": "^2.0.7",
|
||||||
|
"tailwind-merge": "^3.3.1",
|
||||||
|
"tailwindcss-animate": "^1.0.7",
|
||||||
|
"three": "^0.175.0",
|
||||||
|
"uuid": "^11.1.0",
|
||||||
|
"vaul": "^1.1.2",
|
||||||
|
"zod": "^4.1.5"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@eslint/js": "^9.21.0",
|
||||||
|
"@tailwindcss/vite": "^4.0.9",
|
||||||
|
"@types/node": "^22.13.9",
|
||||||
|
"@types/react": "^19.0.10",
|
||||||
|
"@types/react-dom": "^19.0.4",
|
||||||
|
"@vitejs/plugin-react": "^4.3.4",
|
||||||
|
"eslint": "^9.21.0",
|
||||||
|
"eslint-plugin-react-hooks": "^5.1.0",
|
||||||
|
"eslint-plugin-react-refresh": "^0.4.19",
|
||||||
|
"globals": "^15.15.0",
|
||||||
|
"prettier": "3.5.3",
|
||||||
|
"tailwindcss": "^4.0.9",
|
||||||
|
"tw-animate-css": "^1.3.7",
|
||||||
|
"typescript": "~5.7.2",
|
||||||
|
"typescript-eslint": "^8.24.1",
|
||||||
|
"vite": "^6.2.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
36
ui_mockup/src/App.tsx
Normal file
36
ui_mockup/src/App.tsx
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import { useMemo } from 'react';
|
||||||
|
import { Container, Theme } from './settings/types';
|
||||||
|
import { LandingPage } from './components/generated/LandingPage';
|
||||||
|
|
||||||
|
let theme: Theme = 'dark';
|
||||||
|
// only use 'centered' container for standalone components, never for full page apps or websites.
|
||||||
|
let container: Container = 'none';
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
function setTheme(theme: Theme) {
|
||||||
|
if (theme === 'dark') {
|
||||||
|
document.documentElement.classList.add('dark');
|
||||||
|
} else {
|
||||||
|
document.documentElement.classList.remove('dark');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setTheme(theme);
|
||||||
|
|
||||||
|
const generatedComponent = useMemo(() => {
|
||||||
|
// THIS IS WHERE THE TOP LEVEL GENRATED COMPONENT WILL BE RETURNED!
|
||||||
|
return <LandingPage />; // %EXPORT_STATEMENT%
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (container === 'centered') {
|
||||||
|
return (
|
||||||
|
<div className="h-full w-full flex flex-col items-center justify-center">
|
||||||
|
{generatedComponent}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return generatedComponent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App;
|
||||||
463
ui_mockup/src/components/generated/LandingPage.tsx
Normal file
463
ui_mockup/src/components/generated/LandingPage.tsx
Normal file
@@ -0,0 +1,463 @@
|
|||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import { motion, AnimatePresence } from 'framer-motion';
|
||||||
|
import { ChevronRight, Tv, Network, Handshake, Users, Code2, Zap, ArrowRight, Terminal, Cpu, Layers, Globe, Rocket, Twitter, Github, Linkedin } from 'lucide-react';
|
||||||
|
|
||||||
|
// --- Constants & Types ---
|
||||||
|
|
||||||
|
const TECH_STACK = ["MCP", "Supabase", "Gemini", "Claude", "UCP", "Agent-to-Agent", "OpenAI", "LangChain", "VectorDB", "LlamaIndex", "Pinecone"];
|
||||||
|
const PROFILES = [{
|
||||||
|
name: "Alex Chen",
|
||||||
|
role: "Computer Science Student",
|
||||||
|
story: "From anxious undergrad to shipping an MCP-based task automation agent.",
|
||||||
|
badge: "Automation Pro",
|
||||||
|
image: "https://images.unsplash.com/photo-1539571696357-5a69c17a67c6?w=400&h=400&fit=crop"
|
||||||
|
}, {
|
||||||
|
name: "Sarah Jenkins",
|
||||||
|
role: "IT Specialist",
|
||||||
|
story: "Future-proofed my career by building a private UCP gateway for my company.",
|
||||||
|
badge: "Infrastructure Lead",
|
||||||
|
image: "https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=400&h=400&fit=crop"
|
||||||
|
}, {
|
||||||
|
name: "Marcus Vane",
|
||||||
|
role: "SaaS Founder",
|
||||||
|
story: "Pivoted from legacy software to an AI-first startup using A2A protocols.",
|
||||||
|
badge: "Serial Founder",
|
||||||
|
image: "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=400&h=400&fit=crop"
|
||||||
|
}] as any[];
|
||||||
|
|
||||||
|
// --- Sub-components (Internal) ---
|
||||||
|
|
||||||
|
const GlassCard = ({
|
||||||
|
icon: Icon,
|
||||||
|
title,
|
||||||
|
text,
|
||||||
|
delay = 0
|
||||||
|
}: {
|
||||||
|
icon: any;
|
||||||
|
title: string;
|
||||||
|
text: string;
|
||||||
|
delay?: number;
|
||||||
|
}) => <motion.div initial={{
|
||||||
|
opacity: 0,
|
||||||
|
y: 20
|
||||||
|
}} whileInView={{
|
||||||
|
opacity: 1,
|
||||||
|
y: 0
|
||||||
|
}} viewport={{
|
||||||
|
once: true
|
||||||
|
}} transition={{
|
||||||
|
duration: 0.6,
|
||||||
|
delay
|
||||||
|
}} className="relative group p-8 rounded-2xl border border-white/10 bg-white/5 backdrop-blur-xl hover:bg-white/10 transition-all duration-300">
|
||||||
|
<div className="mb-6 w-12 h-12 flex items-center justify-center rounded-lg bg-indigo-500/20 text-indigo-400 group-hover:scale-110 transition-transform duration-300">
|
||||||
|
<Icon size={24} />
|
||||||
|
</div>
|
||||||
|
<h3 className="text-xl font-bold mb-3 text-white font-['Space_Grotesk']">{title}</h3>
|
||||||
|
<p className="text-slate-400 leading-relaxed font-['Inter']">{text}</p>
|
||||||
|
<div className="absolute inset-0 border-2 border-transparent group-hover:border-indigo-500/30 rounded-2xl transition-all duration-300 pointer-events-none" />
|
||||||
|
</motion.div>;
|
||||||
|
const CodeWindow = () => {
|
||||||
|
const [lines, setLines] = useState([{
|
||||||
|
text: "const agent = new BuilderAgent({",
|
||||||
|
color: "text-indigo-400"
|
||||||
|
}, {
|
||||||
|
text: " protocol: 'MCP',",
|
||||||
|
color: "text-amber-400"
|
||||||
|
}, {
|
||||||
|
text: " squad: 'Alpha-Team',",
|
||||||
|
color: "text-amber-400"
|
||||||
|
}, {
|
||||||
|
text: " mission: 'Future-Proof',",
|
||||||
|
color: "text-amber-400"
|
||||||
|
}, {
|
||||||
|
text: "});",
|
||||||
|
color: "text-indigo-400"
|
||||||
|
}, {
|
||||||
|
text: "",
|
||||||
|
color: ""
|
||||||
|
}, {
|
||||||
|
text: "await agent.startBuilding();",
|
||||||
|
color: "text-emerald-400"
|
||||||
|
}]);
|
||||||
|
return <div className="bg-[#0f172a] rounded-xl border border-slate-700 overflow-hidden shadow-2xl h-full flex flex-col font-mono text-sm">
|
||||||
|
<div className="flex items-center gap-2 px-4 py-3 bg-slate-800/50 border-b border-slate-700">
|
||||||
|
<div className="flex gap-1.5">
|
||||||
|
<div className="w-3 h-3 rounded-full bg-red-500/50" />
|
||||||
|
<div className="w-3 h-3 rounded-full bg-amber-500/50" />
|
||||||
|
<div className="w-3 h-3 rounded-full bg-emerald-500/50" />
|
||||||
|
</div>
|
||||||
|
<div className="ml-4 text-slate-500 text-xs tracking-wider">BUILDER_SQUAD_01.ts</div>
|
||||||
|
</div>
|
||||||
|
<div className="p-6 flex-1 relative">
|
||||||
|
<div className="space-y-2">
|
||||||
|
{lines.map((line, i) => <motion.div key={i} initial={{
|
||||||
|
opacity: 0,
|
||||||
|
x: -10
|
||||||
|
}} animate={{
|
||||||
|
opacity: 1,
|
||||||
|
x: 0
|
||||||
|
}} transition={{
|
||||||
|
delay: i * 0.1
|
||||||
|
}} className="flex gap-4">
|
||||||
|
<span className="text-slate-600 w-4 text-right select-none">{i + 1}</span>
|
||||||
|
<span className={line.color}>{line.text}</span>
|
||||||
|
</motion.div>)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Animated Cursors */}
|
||||||
|
<motion.div animate={{
|
||||||
|
x: [0, 40, -20, 0],
|
||||||
|
y: [0, 60, 20, 0]
|
||||||
|
}} transition={{
|
||||||
|
duration: 8,
|
||||||
|
repeat: Infinity,
|
||||||
|
ease: "easeInOut"
|
||||||
|
}} className="absolute top-20 left-40">
|
||||||
|
<div className="relative group">
|
||||||
|
<div className="w-1 h-5 bg-amber-400" />
|
||||||
|
<div className="absolute left-1 top-0 bg-amber-400 text-[#1E293B] text-[10px] px-1.5 py-0.5 rounded-sm whitespace-nowrap font-bold">Priya_Dev</div>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
<motion.div animate={{
|
||||||
|
x: [0, -30, 40, 0],
|
||||||
|
y: [0, -20, 80, 0]
|
||||||
|
}} transition={{
|
||||||
|
duration: 12,
|
||||||
|
repeat: Infinity,
|
||||||
|
ease: "easeInOut",
|
||||||
|
delay: 1
|
||||||
|
}} className="absolute top-10 left-60">
|
||||||
|
<div className="relative group">
|
||||||
|
<div className="w-1 h-5 bg-indigo-400" />
|
||||||
|
<div className="absolute left-1 top-0 bg-indigo-400 text-white text-[10px] px-1.5 py-0.5 rounded-sm whitespace-nowrap font-bold">Arjun_AI</div>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
</div>;
|
||||||
|
};
|
||||||
|
const ProfileCard = ({
|
||||||
|
profile
|
||||||
|
}: {
|
||||||
|
profile: typeof PROFILES[0];
|
||||||
|
}) => <motion.div whileHover={{
|
||||||
|
y: -5
|
||||||
|
}} className="bg-slate-800/40 border border-slate-700/50 p-6 rounded-2xl flex flex-col items-center text-center group">
|
||||||
|
<div className="relative mb-6">
|
||||||
|
<div className="w-24 h-24 rounded-full overflow-hidden border-2 border-indigo-500/30 group-hover:border-indigo-400 transition-colors">
|
||||||
|
<img src={profile.image} alt={profile.name} className="w-full h-full object-cover" />
|
||||||
|
</div>
|
||||||
|
<div className="absolute -bottom-2 -right-2 bg-amber-500 text-[#1E293B] text-[10px] font-bold px-2 py-1 rounded-full uppercase tracking-tighter shadow-lg" style={{
|
||||||
|
fontSize: "9px"
|
||||||
|
}}>Portfolio Builder</div>
|
||||||
|
</div>
|
||||||
|
<h4 className="text-white font-bold text-lg mb-1">The Student</h4>
|
||||||
|
<p className="text-indigo-400 text-sm font-mono mb-4">Future-Proofing the Degree</p>
|
||||||
|
<p className="text-slate-400 text-sm italic">"Universities teach theory; the market demands shipping. Stop worrying about your GPA and start building an Agent portfolio that makes recruiters ignore your grades."</p>
|
||||||
|
</motion.div>;
|
||||||
|
|
||||||
|
// @component: LandingPage
|
||||||
|
export const LandingPage = () => {
|
||||||
|
const [isScrolled, setIsScrolled] = useState(false);
|
||||||
|
useEffect(() => {
|
||||||
|
const handleScroll = () => setIsScrolled(window.scrollY > 50);
|
||||||
|
window.addEventListener('scroll', handleScroll);
|
||||||
|
return () => window.removeEventListener('scroll', handleScroll);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// @return
|
||||||
|
return <div className="min-h-screen bg-[#1E293B] text-slate-100 selection:bg-amber-500/30 font-['Inter'] selection:text-amber-200">
|
||||||
|
{/* Navbar */}
|
||||||
|
<nav className={`fixed top-0 w-full z-50 transition-all duration-300 ${isScrolled ? 'bg-[#1E293B]/80 backdrop-blur-md py-4 shadow-xl' : 'bg-transparent py-6'}`}>
|
||||||
|
<div className="container mx-auto px-6 flex items-center justify-between">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<div className="w-8 h-8 bg-amber-500 rounded-lg flex items-center justify-center transform rotate-12">
|
||||||
|
<Code2 size={18} className="text-[#1E293B]" />
|
||||||
|
</div>
|
||||||
|
<span className="text-xl font-bold font-['Space_Grotesk'] tracking-tight">
|
||||||
|
Move. <span className="text-indigo-400">Compete.</span> Play.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="hidden md:flex items-center gap-10">
|
||||||
|
{['The Mission', 'Build Projects', 'Squads', 'Manifesto'].map(link => <a key={link} href={`#${link.toLowerCase().replace(' ', '-')}`} className="text-sm font-medium text-slate-300 hover:text-amber-400 transition-colors">
|
||||||
|
{link}
|
||||||
|
</a>)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button className="bg-amber-500 hover:bg-amber-400 text-[#1E293B] font-bold px-6 py-2.5 rounded-full transition-all hover:scale-105 active:scale-95 shadow-lg shadow-amber-500/20">
|
||||||
|
Join the Builders
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
{/* Hero Section */}
|
||||||
|
<section className="relative pt-32 pb-20 overflow-hidden">
|
||||||
|
{/* Background Grid Pattern */}
|
||||||
|
<div className="absolute inset-0 z-0 opacity-10 pointer-events-none" style={{
|
||||||
|
backgroundImage: 'radial-gradient(#6366F1 0.5px, transparent 0.5px)',
|
||||||
|
backgroundSize: '24px 24px'
|
||||||
|
}} />
|
||||||
|
<div className="absolute top-0 right-0 w-[500px] h-[500px] bg-indigo-500/10 blur-[120px] rounded-full -z-10" />
|
||||||
|
<div className="absolute bottom-0 left-0 w-[500px] h-[500px] bg-amber-500/5 blur-[120px] rounded-full -z-10" />
|
||||||
|
|
||||||
|
<div className="container mx-auto px-6 relative z-10">
|
||||||
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-16 items-center">
|
||||||
|
<motion.div initial={{
|
||||||
|
opacity: 0,
|
||||||
|
x: -50
|
||||||
|
}} animate={{
|
||||||
|
opacity: 1,
|
||||||
|
x: 0
|
||||||
|
}} transition={{
|
||||||
|
duration: 0.8
|
||||||
|
}}>
|
||||||
|
<div className="inline-flex items-center gap-2 bg-indigo-500/10 border border-indigo-500/20 px-3 py-1 rounded-full text-indigo-400 text-xs font-bold mb-6 tracking-wide uppercase">
|
||||||
|
<Zap size={14} /> Future-Proof Your Career
|
||||||
|
</div>
|
||||||
|
<h1 className="text-4xl md:text-6xl lg:text-7xl font-bold font-['Space_Grotesk'] leading-[1.1] mb-8">
|
||||||
|
Don't Fear the AI. <br />
|
||||||
|
<span className="text-transparent bg-clip-text bg-gradient-to-r from-amber-400 to-amber-600">Build with AI.</span>
|
||||||
|
</h1>
|
||||||
|
<p className="text-xl text-slate-400 mb-10 leading-relaxed max-w-xl">
|
||||||
|
The safe harbor for developers, students, and founders to stop watching tutorials and start shipping. Master MCP, UCP, and Agents by building real products together.
|
||||||
|
</p>
|
||||||
|
<div className="flex flex-col sm:flex-row gap-4">
|
||||||
|
<button className="w-full sm:w-auto bg-amber-500 hover:bg-amber-400 text-[#1E293B] font-bold px-8 py-4 rounded-xl transition-all flex items-center justify-center gap-2 group">Join the Community</button>
|
||||||
|
<button className="w-full sm:w-auto border border-slate-700 hover:border-slate-500 bg-white/5 px-8 py-4 rounded-xl font-bold transition-all text-white flex items-center justify-center gap-2">
|
||||||
|
Read Manifesto
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-12 flex items-center gap-6">
|
||||||
|
<div className="flex -space-x-3">
|
||||||
|
{[1, 2, 3, 4].map(i => <div key={i} className="w-10 h-10 rounded-full border-2 border-[#1E293B] bg-slate-700 flex items-center justify-center overflow-hidden">
|
||||||
|
<img src={`https://api.dicebear.com/7.x/avataaars/svg?seed=${i + 123}`} alt="avatar" />
|
||||||
|
</div>)}
|
||||||
|
<div className="w-10 h-10 rounded-full border-2 border-[#1E293B] bg-indigo-600 flex items-center justify-center text-[10px] font-bold">+</div>
|
||||||
|
</div>
|
||||||
|
<p className="text-sm text-slate-500" style={{
|
||||||
|
fontWeight: "400",
|
||||||
|
fontStyle: "normal",
|
||||||
|
color: "#90a1b9"
|
||||||
|
}}>
|
||||||
|
Join the Founding Class of 2026
|
||||||
|
<button onClick={() => {
|
||||||
|
const buildSection = document.getElementById('build-season');
|
||||||
|
buildSection?.scrollIntoView({
|
||||||
|
behavior: 'smooth',
|
||||||
|
block: 'center'
|
||||||
|
});
|
||||||
|
}} className="ml-2 inline-flex items-center gap-1 px-3 py-1 rounded-full bg-amber-500/10 border border-amber-500/20 text-amber-500 text-xs font-bold hover:bg-amber-500/20 transition-all">
|
||||||
|
Learn More <ChevronRight size={14} />
|
||||||
|
</button>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
<motion.div initial={{
|
||||||
|
opacity: 0,
|
||||||
|
scale: 0.9
|
||||||
|
}} animate={{
|
||||||
|
opacity: 1,
|
||||||
|
scale: 1
|
||||||
|
}} transition={{
|
||||||
|
duration: 0.8,
|
||||||
|
delay: 0.2
|
||||||
|
}} className="relative mt-12 lg:mt-0">
|
||||||
|
<div className="relative z-10">
|
||||||
|
<CodeWindow />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Decorative elements */}
|
||||||
|
<div className="absolute -top-12 -right-8 w-64 h-64 bg-indigo-500/20 rounded-full blur-[80px] -z-10" />
|
||||||
|
<div className="absolute -bottom-8 -left-12 w-48 h-48 bg-amber-500/10 rounded-full blur-[60px] -z-10" />
|
||||||
|
|
||||||
|
{/* Floating Badge */}
|
||||||
|
<motion.div animate={{
|
||||||
|
y: [0, -10, 0]
|
||||||
|
}} transition={{
|
||||||
|
duration: 4,
|
||||||
|
repeat: Infinity,
|
||||||
|
ease: "easeInOut"
|
||||||
|
}} className="absolute -bottom-6 right-10 z-20 bg-slate-800 border border-slate-700 p-4 rounded-xl shadow-2xl flex items-center gap-3">
|
||||||
|
<div className="p-2 bg-amber-500/10 text-amber-500 rounded-lg">
|
||||||
|
<Terminal size={20} />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div className="text-[10px] text-slate-500 uppercase font-bold tracking-widest">Active Stack</div>
|
||||||
|
<div className="text-sm font-bold text-white">Gemini 3 Pro + MCP</div>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Feature Grid */}
|
||||||
|
<section className="py-24 bg-slate-900/50">
|
||||||
|
<div className="container mx-auto px-6">
|
||||||
|
<div className="text-center mb-16">
|
||||||
|
<h2 className="text-3xl md:text-4xl font-bold font-['Space_Grotesk'] mb-4">A Gym for Builders, Not a Classroom</h2>
|
||||||
|
<p className="text-slate-400 max-w-2xl mx-auto">Skip the generic videos. Join a community where the curriculum is "Building things that matter."</p>
|
||||||
|
</div>
|
||||||
|
<div className="grid md:grid-cols-3 gap-8">
|
||||||
|
<GlassCard icon={Tv} title="No More Tutorials" text="Stop gathering 'knowledge' and start building skill. Tutorials make you feel smart while your skills stagnate. We ship from Day 1." delay={0.1} />
|
||||||
|
<GlassCard icon={Network} title="Protocol First" text="Master the plumbing of the future. Deep dive into Model Context Protocol (MCP), Universal Commerce Protocol (UCP), and Agentic frameworks." delay={0.2} />
|
||||||
|
<GlassCard icon={Handshake} title="Squad Mode" text="Never build alone. Match with creators who share your stack. Weekly sprints, peer reviews, and collaborative repos." delay={0.3} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Tech Marquee */}
|
||||||
|
<section className="py-12 border-y border-white/5 bg-[#1E293B]">
|
||||||
|
<div className="flex overflow-hidden group">
|
||||||
|
<div className="flex animate-scroll hover:[animation-play-state:paused] whitespace-nowrap">
|
||||||
|
{[...TECH_STACK, ...TECH_STACK].map((tech, i) => <div key={i} className="mx-8 px-6 py-2 rounded-full border border-slate-800 bg-slate-800/30 text-slate-400 font-mono text-sm flex items-center gap-2 hover:border-indigo-500/50 hover:text-indigo-400 transition-all cursor-default">
|
||||||
|
<div className="w-1.5 h-1.5 rounded-full bg-indigo-500/50" />
|
||||||
|
{tech}
|
||||||
|
</div>)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Community Spotlight */}
|
||||||
|
<section className="py-24">
|
||||||
|
<div className="container mx-auto px-6">
|
||||||
|
<div className="flex flex-col md:flex-row justify-between items-end mb-16 gap-6">
|
||||||
|
<div className="max-w-xl">
|
||||||
|
<h2 className="text-4xl font-bold font-['Space_Grotesk'] mb-4">From Anxiety to Action</h2>
|
||||||
|
<p className="text-slate-400">The Gym is open for everyone. Whether you are starting out or leveling up, you have a squad waiting for you.</p>
|
||||||
|
</div>
|
||||||
|
<button className="text-amber-500 font-bold flex items-center gap-2 hover:text-amber-400 transition-colors">
|
||||||
|
See all alumni <ArrowRight size={18} />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid md:grid-cols-3 gap-8">
|
||||||
|
{PROFILES.map((profile, i) => <ProfileCard key={i} profile={profile} />)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="build-season" className="mt-20 p-12 rounded-[2rem] bg-gradient-to-br from-indigo-600/20 to-amber-600/10 border border-white/10 relative overflow-hidden">
|
||||||
|
<div className="relative z-10 flex flex-col md:flex-row items-center gap-10">
|
||||||
|
<div className="flex-1">
|
||||||
|
<h3 className="text-3xl font-bold font-['Space_Grotesk'] mb-4">Build Season #01 is approaching. 📣</h3>
|
||||||
|
<p className="text-slate-300 text-lg mb-8 max-w-lg">Don't build alone. Join a Squad of 4-5 builders to ship your first MCP Agent in 6 weeks. Whether you are a student looking for a portfolio piece or a pro updating your skills—your Squad keeps you shipping.</p>
|
||||||
|
<div className="flex flex-wrap gap-4">
|
||||||
|
<button className="bg-white text-[#1E293B] font-bold px-8 py-4 rounded-xl hover:bg-slate-200 transition-all">Apply for Season #01</button>
|
||||||
|
<div className="flex items-center gap-4 px-6 text-sm text-slate-400 border-l border-white/10">
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<span className="font-bold text-white uppercase tracking-widest text-[10px]">START DATE</span>
|
||||||
|
<span>TBD</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="hidden lg:grid grid-cols-2 gap-4 flex-shrink-0">
|
||||||
|
<div className="p-4 bg-slate-900/60 rounded-xl border border-white/5 text-center">
|
||||||
|
<div className="text-2xl font-bold text-amber-500">Build an MCP Server</div>
|
||||||
|
<div className="text-[10px] text-slate-500 uppercase font-bold tracking-widest">CURRENT MISSION</div>
|
||||||
|
</div>
|
||||||
|
<div className="p-4 bg-slate-900/60 rounded-xl border border-white/5 text-center">
|
||||||
|
<div className="text-2xl font-bold text-indigo-400">4-6 Builders</div>
|
||||||
|
<div className="text-[10px] text-slate-500 uppercase font-bold tracking-widest">SQUAD SIZE</div>
|
||||||
|
</div>
|
||||||
|
<div className="p-4 bg-slate-900/60 rounded-xl border border-white/5 text-center">
|
||||||
|
<div className="text-2xl font-bold text-emerald-400">6 Weeks</div>
|
||||||
|
<div className="text-[10px] text-slate-500 uppercase font-bold tracking-widest">DURATION</div>
|
||||||
|
</div>
|
||||||
|
<div className="p-4 bg-slate-900/60 rounded-xl border border-white/5 text-center">
|
||||||
|
<div className="text-2xl font-bold text-purple-400">Free</div>
|
||||||
|
<div className="text-[10px] text-slate-500 uppercase font-bold tracking-widest">COST</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* Background elements for this section */}
|
||||||
|
<div className="absolute top-0 right-0 w-full h-full bg-[radial-gradient(circle_at_top_right,rgba(99,102,241,0.1),transparent)] pointer-events-none" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Footer */}
|
||||||
|
<footer className="py-20 border-t border-white/5 bg-slate-950">
|
||||||
|
<div className="container mx-auto px-6">
|
||||||
|
<div className="grid md:grid-cols-4 gap-12 mb-16">
|
||||||
|
<div className="col-span-1 md:col-span-2">
|
||||||
|
<div className="flex items-center gap-2 mb-6">
|
||||||
|
<div className="w-8 h-8 bg-amber-500 rounded-lg flex items-center justify-center transform rotate-12">
|
||||||
|
<Code2 size={18} className="text-[#1E293B]" />
|
||||||
|
</div>
|
||||||
|
<span className="text-xl font-bold font-['Space_Grotesk'] tracking-tight">
|
||||||
|
Move. <span className="text-indigo-400">Compete.</span> Play.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<p className="text-slate-500 max-w-sm mb-6 leading-relaxed">
|
||||||
|
The premier hub for tech professionals to transition from AI-anxiety to AI-mastery through building and community.
|
||||||
|
</p>
|
||||||
|
<div className="flex gap-4">
|
||||||
|
<a href="#" className="w-10 h-10 rounded-lg bg-slate-900 border border-slate-800 flex items-center justify-center text-slate-400 hover:text-amber-500 hover:border-amber-500/50 transition-all">
|
||||||
|
<span className="sr-only">Discord</span>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||||
|
<path d="M9.5 7.5c-.828 0-1.5.671-1.5 1.5 0 .828.672 1.5 1.5 1.5s1.5-.672 1.5-1.5c0-.829-.672-1.5-1.5-1.5zm5 0c-.828 0-1.5.671-1.5 1.5 0 .828.672 1.5 1.5 1.5s1.5-.672 1.5-1.5c0-.829-.672-1.5-1.5-1.5z" />
|
||||||
|
<path d="M18.7 4.1c-1.26-.42-2.61-.73-4-.91-.18.31-.35.63-.49.97-1.5-.23-3-.23-4.5 0-.14-.34-.31-.66-.49-.97-1.39.18-2.74.49-4 .91-2.59 3.89-3.29 7.69-2.94 11.44 1.69 1.25 3.33 2.01 4.95 2.51.4-.54.75-1.12 1.05-1.72-.58-.22-1.13-.48-1.66-.78.14-.1.27-.21.4-.32 3.21 1.49 6.76 1.49 9.96 0 .13.11.26.22.4.32-.53.3-1.08.56-1.66.78.3.6.65 1.18 1.05 1.72 1.62-.5 3.26-1.26 4.95-2.51.39-4.2-.65-7.84-2.94-11.44z" />
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
<a href="#" className="w-10 h-10 rounded-lg bg-slate-900 border border-slate-800 flex items-center justify-center text-slate-400 hover:text-amber-500 hover:border-amber-500/50 transition-all">
|
||||||
|
<span className="sr-only">GitHub</span>
|
||||||
|
<Github size={18} />
|
||||||
|
</a>
|
||||||
|
<a href="#" className="w-10 h-10 rounded-lg bg-slate-900 border border-slate-800 flex items-center justify-center text-slate-400 hover:text-amber-500 hover:border-amber-500/50 transition-all">
|
||||||
|
<span className="sr-only">Twitter</span>
|
||||||
|
<Twitter size={18} />
|
||||||
|
</a>
|
||||||
|
<a href="#" className="w-10 h-10 rounded-lg bg-slate-900 border border-slate-800 flex items-center justify-center text-slate-400 hover:text-amber-500 hover:border-amber-500/50 transition-all">
|
||||||
|
<span className="sr-only">LinkedIn</span>
|
||||||
|
<Linkedin size={18} />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h5 className="text-white font-bold mb-6 font-['Space_Grotesk']">Resource</h5>
|
||||||
|
<ul className="space-y-4 text-sm text-slate-500">
|
||||||
|
<li><a href="#" className="hover:text-amber-400 transition-colors">The Manifesto</a></li>
|
||||||
|
<li><a href="#" className="hover:text-amber-400 transition-colors">Build Kits</a></li>
|
||||||
|
<li><a href="#" className="hover:text-amber-400 transition-colors">Squad Directory</a></li>
|
||||||
|
<li><a href="#" className="hover:text-amber-400 transition-colors">Alumni Network</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h5 className="text-white font-bold mb-6 font-['Space_Grotesk']">Protocols</h5>
|
||||||
|
<ul className="space-y-4 text-sm text-slate-500 font-mono">
|
||||||
|
<li><a href="#" className="hover:text-indigo-400 transition-colors">MCP Spec</a></li>
|
||||||
|
<li><a href="#" className="hover:text-indigo-400 transition-colors">UCP Handshake</a></li>
|
||||||
|
<li><a href="#" className="hover:text-indigo-400 transition-colors">Agent SDK</a></li>
|
||||||
|
<li><a href="#" className="hover:text-indigo-400 transition-colors">A2A Messaging</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col md:flex-row justify-between items-center gap-6 pt-10 border-t border-white/5">
|
||||||
|
<p className="text-sm text-slate-600 font-['Space_Grotesk'] font-bold">© 2023 Move. Compete. Play. — The future belongs to the builders. ⚡ Built with AI</p>
|
||||||
|
<div className="flex gap-8 text-xs text-slate-600">
|
||||||
|
<a href="#" className="hover:text-slate-400">Privacy Policy</a>
|
||||||
|
<a href="#" className="hover:text-slate-400">Terms of Service</a>
|
||||||
|
<a href="#" className="hover:text-slate-400">Code of Conduct</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
{/* Global Styles for the marquee animation */}
|
||||||
|
<style>{`
|
||||||
|
@keyframes scroll {
|
||||||
|
0% { transform: translateX(0); }
|
||||||
|
100% { transform: translateX(-50%); }
|
||||||
|
}
|
||||||
|
.animate-scroll {
|
||||||
|
animation: scroll 30s linear infinite;
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
</div>;
|
||||||
|
};
|
||||||
19
ui_mockup/src/hooks/use-mobile.ts
Normal file
19
ui_mockup/src/hooks/use-mobile.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
const MOBILE_BREAKPOINT = 768;
|
||||||
|
|
||||||
|
export function useIsMobile() {
|
||||||
|
const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
|
||||||
|
const onChange = () => {
|
||||||
|
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
||||||
|
};
|
||||||
|
mql.addEventListener('change', onChange);
|
||||||
|
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
||||||
|
return () => mql.removeEventListener('change', onChange);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return !!isMobile;
|
||||||
|
}
|
||||||
181
ui_mockup/src/index.css
Normal file
181
ui_mockup/src/index.css
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
@import url('https://fonts.googleapis.com/css2?family=Inter&family=Arial&family=Helvetica&family=Times+New+Roman&family=Georgia&family=Roboto&display=swap');
|
||||||
|
@import 'tailwindcss';
|
||||||
|
|
||||||
|
@plugin "tailwindcss-animate";
|
||||||
|
|
||||||
|
@custom-variant dark (&:is(.dark *));
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
min-height: 100vh;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: auto;
|
||||||
|
overscroll-behavior-x: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@theme inline {
|
||||||
|
--color-background: var(--background);
|
||||||
|
--color-foreground: var(--foreground);
|
||||||
|
--font-sans: var(--font-geist-sans);
|
||||||
|
--font-body: var(--font-body);
|
||||||
|
--font-heading: var(--font-heading);
|
||||||
|
--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);
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--radius: 0.625rem;
|
||||||
|
--background: oklch(0.2795 0.0368 260.0299);
|
||||||
|
--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;
|
||||||
|
font-family: var(--font-body);
|
||||||
|
}
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
}
|
||||||
|
html,
|
||||||
|
body,
|
||||||
|
#root {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
overscroll-behavior-x: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Broken Image Fallback Styles */
|
||||||
|
img.broken-image-fallback {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
background: #f9fafb;
|
||||||
|
border: 1px solid #e5e7eb;
|
||||||
|
object-fit: none;
|
||||||
|
object-position: center;
|
||||||
|
animation: fadeIn 0.3s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark img.broken-image-fallback {
|
||||||
|
background: #1f2937;
|
||||||
|
border-color: #374151;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
29
ui_mockup/src/lib/utils.ts
Normal file
29
ui_mockup/src/lib/utils.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { clsx, type ClassValue } from 'clsx';
|
||||||
|
import { twMerge } from 'tailwind-merge';
|
||||||
|
|
||||||
|
export function cn(...inputs: ClassValue[]) {
|
||||||
|
return twMerge(clsx(inputs));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensures light mode is always used by removing the dark class from the document element.
|
||||||
|
* This can be called from any component that needs to ensure light mode.
|
||||||
|
*/
|
||||||
|
export function ensureLightMode() {
|
||||||
|
if (typeof document !== 'undefined') {
|
||||||
|
// Always set dark mode to false
|
||||||
|
document.documentElement.classList.toggle('dark', false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes any dark mode classes from a className string
|
||||||
|
* @param className The class string to process
|
||||||
|
* @returns The class string with dark mode classes removed
|
||||||
|
*/
|
||||||
|
export function removeDarkClasses(className: string): string {
|
||||||
|
return className
|
||||||
|
.split(' ')
|
||||||
|
.filter(cls => !cls.startsWith('dark:'))
|
||||||
|
.join(' ');
|
||||||
|
}
|
||||||
45
ui_mockup/src/main.tsx
Normal file
45
ui_mockup/src/main.tsx
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import { StrictMode } from 'react';
|
||||||
|
// Force light mode by removing dark class and preventing it from being added
|
||||||
|
document.documentElement.classList.remove('dark');
|
||||||
|
|
||||||
|
// Override the system preference detection
|
||||||
|
const forceLightMode = () => {
|
||||||
|
// Always set dark mode to false regardless of localStorage or system preference
|
||||||
|
document.documentElement.classList.toggle('dark', false // Force to false instead of checking localStorage or system preference
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const addBrokenImageHandler = () => {
|
||||||
|
document.addEventListener('error', function (e) {
|
||||||
|
if (e.target instanceof HTMLImageElement) {
|
||||||
|
const img = e.target;
|
||||||
|
if (!img.dataset.fallbackApplied) {
|
||||||
|
img.dataset.fallbackApplied = 'true';
|
||||||
|
|
||||||
|
// Create a simple fallback SVG icon as data URL
|
||||||
|
const fallbackSvg = `data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%239ca3af' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect width='18' height='18' x='3' y='3' rx='2' ry='2'/%3E%3Ccircle cx='9' cy='9' r='2'/%3E%3Cpath d='m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21'/%3E%3C/svg%3E`;
|
||||||
|
img.src = fallbackSvg;
|
||||||
|
img.classList.add('broken-image-fallback');
|
||||||
|
if (!img.alt || img.alt.trim() === '') {
|
||||||
|
img.alt = 'Image not available';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Run immediately
|
||||||
|
forceLightMode();
|
||||||
|
addBrokenImageHandler();
|
||||||
|
|
||||||
|
// Also run when the DOM is loaded to ensure it applies
|
||||||
|
document.addEventListener('DOMContentLoaded', forceLightMode);
|
||||||
|
|
||||||
|
// Override system preference changes
|
||||||
|
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
||||||
|
mediaQuery.addEventListener('change', forceLightMode);
|
||||||
|
import { createRoot } from 'react-dom/client';
|
||||||
|
import './index.css';
|
||||||
|
import App from './App.tsx';
|
||||||
|
createRoot(document.getElementById('root')!).render(<StrictMode>
|
||||||
|
<App />
|
||||||
|
</StrictMode>);
|
||||||
19
ui_mockup/src/settings/theme.ts
Normal file
19
ui_mockup/src/settings/theme.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { Theme, Container } from './types';
|
||||||
|
|
||||||
|
const injectedTheme: string = '%INJECTED_THEME%';
|
||||||
|
const injectedContainer: string = '%INJECTED_CONTAINER%';
|
||||||
|
|
||||||
|
let theme: Theme = 'light';
|
||||||
|
let container: Container = 'none';
|
||||||
|
|
||||||
|
if (injectedTheme === 'light' || injectedTheme === 'dark') {
|
||||||
|
theme = injectedTheme;
|
||||||
|
}
|
||||||
|
if (injectedContainer === 'centered' || injectedContainer === 'none') {
|
||||||
|
container = injectedContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
theme,
|
||||||
|
container,
|
||||||
|
};
|
||||||
2
ui_mockup/src/settings/types.d.ts
vendored
Normal file
2
ui_mockup/src/settings/types.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export type Theme = 'light' | 'dark';
|
||||||
|
export type Container = 'centered' | 'none';
|
||||||
1
ui_mockup/src/vite-env.d.ts
vendored
Normal file
1
ui_mockup/src/vite-env.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/// <reference types="vite/client" />
|
||||||
31
ui_mockup/tsconfig.app.json
Normal file
31
ui_mockup/tsconfig.app.json
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
||||||
|
"target": "ES2020",
|
||||||
|
"useDefineForClassFields": true,
|
||||||
|
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||||
|
"module": "ESNext",
|
||||||
|
"skipLibCheck": true,
|
||||||
|
|
||||||
|
/* Bundler mode */
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"moduleDetection": "force",
|
||||||
|
"noEmit": true,
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
|
||||||
|
/* Linting */
|
||||||
|
"strict": true,
|
||||||
|
"noUnusedLocals": false,
|
||||||
|
"noUnusedParameters": false,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"noUncheckedSideEffectImports": true,
|
||||||
|
"noImplicitAny": false,
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./src/*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["src"]
|
||||||
|
}
|
||||||
10
ui_mockup/tsconfig.json
Normal file
10
ui_mockup/tsconfig.json
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"files": [],
|
||||||
|
"references": [{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" }],
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./src/*"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
24
ui_mockup/tsconfig.node.json
Normal file
24
ui_mockup/tsconfig.node.json
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
||||||
|
"target": "ES2022",
|
||||||
|
"lib": ["ES2023"],
|
||||||
|
"module": "ESNext",
|
||||||
|
"skipLibCheck": true,
|
||||||
|
|
||||||
|
/* Bundler mode */
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"moduleDetection": "force",
|
||||||
|
"noEmit": true,
|
||||||
|
|
||||||
|
/* Linting */
|
||||||
|
"strict": true,
|
||||||
|
"noUnusedLocals": false,
|
||||||
|
"noUnusedParameters": false,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"noUncheckedSideEffectImports": true
|
||||||
|
},
|
||||||
|
"include": ["vite.config.ts"]
|
||||||
|
}
|
||||||
14
ui_mockup/vite.config.ts
Normal file
14
ui_mockup/vite.config.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import path from 'path';
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import react from '@vitejs/plugin-react';
|
||||||
|
import tailwindcss from '@tailwindcss/vite';
|
||||||
|
|
||||||
|
// https://vite.dev/config/
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [react(), tailwindcss()],
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'@': path.resolve(__dirname, './src'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
3526
ui_mockup/yarn.lock
Normal file
3526
ui_mockup/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user