From d69d7e9813b9f467eda45c3ef191ad5478b2185c Mon Sep 17 00:00:00 2001 From: Corey Thomas <125082303+Corey-T1000@users.noreply.github.com> Date: Thu, 12 Mar 2026 17:44:48 -0400 Subject: [PATCH 1/4] feat(basin): rebuild as internal tools hub with security hardening MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the external tools catalog with an internal tool directory serving self-contained HTML tools from public/. Add Email Signature generator (converted from sandworm React component) and Voronoi Chromatic Explorer. - Update Next.js 14.0.4 → 14.2.30 (patches 11 CVEs including auth bypass) - Add security headers via next.config.js (CSP, X-Frame-Options, etc.) - Strip 9 unused components (filters, search, sort, card expansion) - Simplify landing page to clean tool card grid Co-Authored-By: Claude Opus 4.6 --- Basin/next.config.js | 22 + Basin/package-lock.json | 128 +- Basin/package.json | 8 +- Basin/public/email-signature/index.html | 483 ++++ Basin/public/voronoi/index.html | 2873 +++++++++++++++++++++++ Basin/src/app/page.tsx | 91 +- Basin/src/components/CategoryFilter.tsx | 42 - Basin/src/components/Header.tsx | 21 - Basin/src/components/MobileFilters.tsx | 55 - Basin/src/components/ProjectCard.tsx | 178 -- Basin/src/components/ProjectGrid.tsx | 108 - Basin/src/components/ProjectList.tsx | 60 - Basin/src/components/SearchBar.tsx | 26 - Basin/src/components/SortSelect.tsx | 34 - Basin/src/components/ViewToggle.tsx | 36 - Basin/src/data/projects.ts | 138 +- Basin/src/hooks/useLocalStorage.ts | 25 - Basin/src/hooks/useProjectCard.ts | 60 - Basin/src/hooks/useTheme.ts | 36 - Basin/src/types/index.ts | 17 +- Basin/src/utils/getOgImage.ts | 12 - 21 files changed, 3513 insertions(+), 940 deletions(-) create mode 100644 Basin/next.config.js create mode 100644 Basin/public/email-signature/index.html create mode 100644 Basin/public/voronoi/index.html delete mode 100644 Basin/src/components/CategoryFilter.tsx delete mode 100644 Basin/src/components/Header.tsx delete mode 100644 Basin/src/components/MobileFilters.tsx delete mode 100644 Basin/src/components/ProjectCard.tsx delete mode 100644 Basin/src/components/ProjectGrid.tsx delete mode 100644 Basin/src/components/ProjectList.tsx delete mode 100644 Basin/src/components/SearchBar.tsx delete mode 100644 Basin/src/components/SortSelect.tsx delete mode 100644 Basin/src/components/ViewToggle.tsx delete mode 100644 Basin/src/hooks/useLocalStorage.ts delete mode 100644 Basin/src/hooks/useProjectCard.ts delete mode 100644 Basin/src/hooks/useTheme.ts delete mode 100644 Basin/src/utils/getOgImage.ts diff --git a/Basin/next.config.js b/Basin/next.config.js new file mode 100644 index 0000000..0e5d877 --- /dev/null +++ b/Basin/next.config.js @@ -0,0 +1,22 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + async headers() { + return [ + { + source: '/(.*)', + headers: [ + { key: 'X-Content-Type-Options', value: 'nosniff' }, + { key: 'X-Frame-Options', value: 'DENY' }, + { key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' }, + { key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' }, + { + key: 'Content-Security-Policy', + value: "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' https: data:; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self';" + }, + ], + }, + ]; + }, +}; + +module.exports = nextConfig; diff --git a/Basin/package-lock.json b/Basin/package-lock.json index 0d357c1..31f8d58 100644 --- a/Basin/package-lock.json +++ b/Basin/package-lock.json @@ -10,7 +10,7 @@ "dependencies": { "clsx": "^2.1.0", "lucide-react": "^0.344.0", - "next": "^14.0.4", + "next": "^14.2.30", "react": "^18.3.1", "react-dom": "^18.3.1", "tailwind-merge": "^2.2.1" @@ -21,7 +21,7 @@ "@types/react-dom": "^18.3.0", "autoprefixer": "^10.4.18", "eslint": "^8.56.0", - "eslint-config-next": "^14.0.4", + "eslint-config-next": "^14.2.30", "postcss": "^8.4.35", "tailwindcss": "^3.4.1", "typescript": "^5.5.3" @@ -200,15 +200,15 @@ } }, "node_modules/@next/env": { - "version": "14.2.20", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.20.tgz", - "integrity": "sha512-JfDpuOCB0UBKlEgEy/H6qcBSzHimn/YWjUHzKl1jMeUO+QVRdzmTTl8gFJaNO87c8DXmVKhFCtwxQ9acqB3+Pw==", + "version": "14.2.35", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.35.tgz", + "integrity": "sha512-DuhvCtj4t9Gwrx80dmz2F4t/zKQ4ktN8WrMwOuVzkJfBilwAwGr6v16M5eI8yCuZ63H9TTuEU09Iu2HqkzFPVQ==", "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { - "version": "14.2.20", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.20.tgz", - "integrity": "sha512-T0JRi706KLbvR1Uc46t56VtawbhR/igdBagzOrA7G+vv4rvjwnlu/Y4/Iq6X9TDVj5UZjyot4lUdkNd3V2kLhw==", + "version": "14.2.35", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.35.tgz", + "integrity": "sha512-Jw9A3ICz2183qSsqwi7fgq4SBPiNfmOLmTPXKvlnzstUwyvBrtySiY+8RXJweNAs9KThb1+bYhZh9XWcNOr2zQ==", "dev": true, "license": "MIT", "dependencies": { @@ -216,9 +216,9 @@ } }, "node_modules/@next/eslint-plugin-next/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -229,6 +229,7 @@ "version": "10.3.10", "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, "license": "ISC", "dependencies": { @@ -268,13 +269,13 @@ } }, "node_modules/@next/eslint-plugin-next/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -284,9 +285,9 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "14.2.20", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.20.tgz", - "integrity": "sha512-WDfq7bmROa5cIlk6ZNonNdVhKmbCv38XteVFYsxea1vDJt3SnYGgxLGMTXQNfs5OkFvAhmfKKrwe7Y0Hs+rWOg==", + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.33.tgz", + "integrity": "sha512-HqYnb6pxlsshoSTubdXKu15g3iivcbsMXg4bYpjL2iS/V6aQot+iyF4BUc2qA/J/n55YtvE4PHMKWBKGCF/+wA==", "cpu": [ "arm64" ], @@ -300,9 +301,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "14.2.20", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.20.tgz", - "integrity": "sha512-XIQlC+NAmJPfa2hruLvr1H1QJJeqOTDV+v7tl/jIdoFvqhoihvSNykLU/G6NMgoeo+e/H7p/VeWSOvMUHKtTIg==", + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.33.tgz", + "integrity": "sha512-8HGBeAE5rX3jzKvF593XTTFg3gxeU4f+UWnswa6JPhzaR6+zblO5+fjltJWIZc4aUalqTclvN2QtTC37LxvZAA==", "cpu": [ "x64" ], @@ -316,9 +317,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "14.2.20", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.20.tgz", - "integrity": "sha512-pnzBrHTPXIMm5QX3QC8XeMkpVuoAYOmyfsO4VlPn+0NrHraNuWjdhe+3xLq01xR++iCvX+uoeZmJDKcOxI201Q==", + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.33.tgz", + "integrity": "sha512-JXMBka6lNNmqbkvcTtaX8Gu5by9547bukHQvPoLe9VRBx1gHwzf5tdt4AaezW85HAB3pikcvyqBToRTDA4DeLw==", "cpu": [ "arm64" ], @@ -332,9 +333,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "14.2.20", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.20.tgz", - "integrity": "sha512-WhJJAFpi6yqmUx1momewSdcm/iRXFQS0HU2qlUGlGE/+98eu7JWLD5AAaP/tkK1mudS/rH2f9E3WCEF2iYDydQ==", + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.33.tgz", + "integrity": "sha512-Bm+QulsAItD/x6Ih8wGIMfRJy4G73tu1HJsrccPW6AfqdZd0Sfm5Imhgkgq2+kly065rYMnCOxTBvmvFY1BKfg==", "cpu": [ "arm64" ], @@ -348,9 +349,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "14.2.20", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.20.tgz", - "integrity": "sha512-ao5HCbw9+iG1Kxm8XsGa3X174Ahn17mSYBQlY6VGsdsYDAbz/ZP13wSLfvlYoIDn1Ger6uYA+yt/3Y9KTIupRg==", + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.33.tgz", + "integrity": "sha512-FnFn+ZBgsVMbGDsTqo8zsnRzydvsGV8vfiWwUo1LD8FTmPTdV+otGSWKc4LJec0oSexFnCYVO4hX8P8qQKaSlg==", "cpu": [ "x64" ], @@ -364,9 +365,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "14.2.20", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.20.tgz", - "integrity": "sha512-CXm/kpnltKTT7945np6Td3w7shj/92TMRPyI/VvveFe8+YE+/YOJ5hyAWK5rpx711XO1jBCgXl211TWaxOtkaA==", + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.33.tgz", + "integrity": "sha512-345tsIWMzoXaQndUTDv1qypDRiebFxGYx9pYkhwY4hBRaOLt8UGfiWKr9FSSHs25dFIf8ZqIFaPdy5MljdoawA==", "cpu": [ "x64" ], @@ -380,9 +381,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "14.2.20", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.20.tgz", - "integrity": "sha512-upJn2HGQgKNDbXVfIgmqT2BN8f3z/mX8ddoyi1I565FHbfowVK5pnMEwauvLvaJf4iijvuKq3kw/b6E9oIVRWA==", + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.33.tgz", + "integrity": "sha512-nscpt0G6UCTkrT2ppnJnFsYbPDQwmum4GNXYTeoTIdsmMydSKFz9Iny2jpaRupTb+Wl298+Rh82WKzt9LCcqSQ==", "cpu": [ "arm64" ], @@ -396,9 +397,9 @@ } }, "node_modules/@next/swc-win32-ia32-msvc": { - "version": "14.2.20", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.20.tgz", - "integrity": "sha512-igQW/JWciTGJwj3G1ipalD2V20Xfx3ywQy17IV0ciOUBbFhNfyU1DILWsTi32c8KmqgIDviUEulW/yPb2FF90w==", + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.33.tgz", + "integrity": "sha512-pc9LpGNKhJ0dXQhZ5QMmYxtARwwmWLpeocFmVG5Z0DzWq5Uf0izcI8tLc+qOpqxO1PWqZ5A7J1blrUIKrIFc7Q==", "cpu": [ "ia32" ], @@ -412,9 +413,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "14.2.20", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.20.tgz", - "integrity": "sha512-AFmqeLW6LtxeFTuoB+MXFeM5fm5052i3MU6xD0WzJDOwku6SkZaxb1bxjBaRC8uNqTRTSPl0yMFtjNowIVI67w==", + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.33.tgz", + "integrity": "sha512-nOjfZMy8B94MdisuzZo9/57xuFVLHJaDj5e/xrduJp9CV2/HrfxTRH2fbyLe+K9QT41WBLUd4iXX3R7jBp0EUg==", "cpu": [ "x64" ], @@ -542,6 +543,7 @@ "integrity": "sha512-opAQ5no6LqJNo9TqnxBKsgnkIYHozW9KSTlFVoSUJYh1Fl/sswkEoqIugRSm7tbh6pABtYjGAjW+GOS23j8qbw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -593,6 +595,7 @@ "integrity": "sha512-rBnTWHCdbYM2lh7hjyXqxk70wvon3p2FyaniZuey5TrcGBpfhVp0OxOa6gxr9Q9YhZFKyfbEnxc24ZnVbbUkCA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.18.1", "@typescript-eslint/types": "8.18.1", @@ -802,6 +805,7 @@ "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1188,6 +1192,7 @@ "url": "https://github.com/sponsors/ai" } ], + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001663", "electron-to-chromium": "^1.5.28", @@ -1749,6 +1754,7 @@ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -1800,13 +1806,13 @@ } }, "node_modules/eslint-config-next": { - "version": "14.2.20", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.2.20.tgz", - "integrity": "sha512-gHBvp4RDd51DAaDco7KiWFy731EwcItkDtGUaZH1EUXEnHCzsVRjMceT+b8aThjMLjOScz6Q27MGlePASvK4Aw==", + "version": "14.2.35", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.2.35.tgz", + "integrity": "sha512-BpLsv01UisH193WyT/1lpHqq5iJ/Orfz9h/NOOlAmTUq4GY349PextQ62K4XpnaM9supeiEn3TaOTeQO07gURg==", "dev": true, "license": "MIT", "dependencies": { - "@next/eslint-plugin-next": "14.2.20", + "@next/eslint-plugin-next": "14.2.35", "@rushstack/eslint-patch": "^1.3.3", "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", @@ -3515,12 +3521,12 @@ "dev": true }, "node_modules/next": { - "version": "14.2.20", - "resolved": "https://registry.npmjs.org/next/-/next-14.2.20.tgz", - "integrity": "sha512-yPvIiWsiyVYqJlSQxwmzMIReXn5HxFNq4+tlVQ812N1FbvhmE+fDpIAD7bcS2mGYQwPJ5vAsQouyme2eKsxaug==", + "version": "14.2.35", + "resolved": "https://registry.npmjs.org/next/-/next-14.2.35.tgz", + "integrity": "sha512-KhYd2Hjt/O1/1aZVX3dCwGXM1QmOV4eNM2UTacK5gipDdPN/oHHK/4oVGy7X8GMfPMsUTUEmGlsy0EY1YGAkig==", "license": "MIT", "dependencies": { - "@next/env": "14.2.20", + "@next/env": "14.2.35", "@swc/helpers": "0.5.5", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001579", @@ -3535,15 +3541,15 @@ "node": ">=18.17.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "14.2.20", - "@next/swc-darwin-x64": "14.2.20", - "@next/swc-linux-arm64-gnu": "14.2.20", - "@next/swc-linux-arm64-musl": "14.2.20", - "@next/swc-linux-x64-gnu": "14.2.20", - "@next/swc-linux-x64-musl": "14.2.20", - "@next/swc-win32-arm64-msvc": "14.2.20", - "@next/swc-win32-ia32-msvc": "14.2.20", - "@next/swc-win32-x64-msvc": "14.2.20" + "@next/swc-darwin-arm64": "14.2.33", + "@next/swc-darwin-x64": "14.2.33", + "@next/swc-linux-arm64-gnu": "14.2.33", + "@next/swc-linux-arm64-musl": "14.2.33", + "@next/swc-linux-x64-gnu": "14.2.33", + "@next/swc-linux-x64-musl": "14.2.33", + "@next/swc-win32-arm64-msvc": "14.2.33", + "@next/swc-win32-ia32-msvc": "14.2.33", + "@next/swc-win32-x64-msvc": "14.2.33" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", @@ -3939,6 +3945,7 @@ "url": "https://github.com/sponsors/ai" } ], + "peer": true, "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.1.0", @@ -4131,6 +4138,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -4143,6 +4151,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -5028,6 +5037,7 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "dev": true, + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/Basin/package.json b/Basin/package.json index 078f82f..415f3d8 100644 --- a/Basin/package.json +++ b/Basin/package.json @@ -9,11 +9,11 @@ "lint": "next lint" }, "dependencies": { - "next": "14.2.35", + "clsx": "^2.1.0", + "lucide-react": "^0.344.0", + "next": "^14.2.30", "react": "^18.3.1", "react-dom": "^18.3.1", - "lucide-react": "^0.344.0", - "clsx": "^2.1.0", "tailwind-merge": "^2.2.1" }, "devDependencies": { @@ -22,7 +22,7 @@ "@types/react-dom": "^18.3.0", "autoprefixer": "^10.4.18", "eslint": "^8.56.0", - "eslint-config-next": "^14.0.4", + "eslint-config-next": "^14.2.30", "postcss": "^8.4.35", "tailwindcss": "^3.4.1", "typescript": "^5.5.3" diff --git a/Basin/public/email-signature/index.html b/Basin/public/email-signature/index.html new file mode 100644 index 0000000..674cfbe --- /dev/null +++ b/Basin/public/email-signature/index.html @@ -0,0 +1,483 @@ + + + + + +Email Signature Generator — AuthZed + + + + + + +
+ + + +
+
+

Preview

+

Live preview — this is how it looks in email clients.

+
+
+
+
+
Signature Preview
+
White background mirrors the email client environment
+
+
+
Fill in your details to preview
+
+ + +
+

Gmail: Settings → Signature → Paste  ·  Outlook: Settings → Email signature → Paste

+
+
+
+
HTML Source
+ +
+
// enter your name to generate HTML
+
+
+ +
+
+ + + diff --git a/Basin/public/voronoi/index.html b/Basin/public/voronoi/index.html new file mode 100644 index 0000000..e1c31eb --- /dev/null +++ b/Basin/public/voronoi/index.html @@ -0,0 +1,2873 @@ + + + + +Voronoi Chromatic Aberration Explorer + + + + + +
+

Bad Lens Voronoi

+
+ Click canvas for full-size + +
+
+ +
+
+ +
+ + + + diff --git a/Basin/src/app/page.tsx b/Basin/src/app/page.tsx index eadf751..450ae7a 100644 --- a/Basin/src/app/page.tsx +++ b/Basin/src/app/page.tsx @@ -1,9 +1,29 @@ 'use client'; -import { Header } from '../components/Header' -import { ProjectGrid } from '../components/ProjectGrid' -import { ThemeToggle } from '../components/ThemeToggle' -import { projects } from '../data/projects' +import { ThemeToggle } from '../components/ThemeToggle'; +import { tools } from '../data/projects'; +import type { Tool } from '../types'; + +function ToolCard({ title, description, path, tag }: Tool) { + return ( + +
+

+ {title} +

+ + {tag} + +
+

+ {description} +

+
+ ); +} export default function Home() { return ( @@ -11,47 +31,30 @@ export default function Home() {
-
-
- A collection of tools born from our own design challenges, now shared to empower others. - Like a hidden desert basin, these resources have been uncovered, refined, and made accessible - to support thoughtful, scalable, and consistent design. -

- Basin is our way of giving back—helping teams everywhere innovate and create with ease. -

- Explore Basin and discover tools to support your journey. - - } - footnote={ - - Built by design at{' '} - - authzed - - , using{' '} - - bolt.new - - . - - } - /> +
+
+

+ Basin +

+

+ Internal tools built by design at{' '} + + AuthZed + . +

+
- +
+ {tools.map((tool) => ( + + ))} +
- ) + ); } diff --git a/Basin/src/components/CategoryFilter.tsx b/Basin/src/components/CategoryFilter.tsx deleted file mode 100644 index 5a23a30..0000000 --- a/Basin/src/components/CategoryFilter.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import React from 'react'; -import { Hash } from 'lucide-react'; - -interface CategoryFilterProps { - categories: string[]; - selectedCategory: string; - onSelectCategory: (category: string) => void; -} - -export function CategoryFilter({ - categories, - selectedCategory, - onSelectCategory -}: CategoryFilterProps) { - return ( - <> - - {categories.map((category) => ( - - ))} - - ); -} \ No newline at end of file diff --git a/Basin/src/components/Header.tsx b/Basin/src/components/Header.tsx deleted file mode 100644 index c9f2800..0000000 --- a/Basin/src/components/Header.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import React from 'react'; - -interface HeaderProps { - title: string; - description: React.ReactNode; - footnote?: React.ReactNode; -} - -export function Header({ title, description, footnote }: HeaderProps) { - return ( -
-

- {title} -

-
-
{description}
- {footnote} -
-
- ); -} \ No newline at end of file diff --git a/Basin/src/components/MobileFilters.tsx b/Basin/src/components/MobileFilters.tsx deleted file mode 100644 index dac4e9f..0000000 --- a/Basin/src/components/MobileFilters.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import React from 'react'; -import { ChevronDown } from 'lucide-react'; -import type { SortOption } from './SortSelect'; - -interface MobileFiltersProps { - categories: string[]; - selectedCategory: string; - onSelectCategory: (category: string) => void; - sortOptions: SortOption[]; - sortBy: string; - onSortChange: (value: string) => void; -} - -export function MobileFilters({ - categories, - selectedCategory, - onSelectCategory, - sortOptions, - sortBy, - onSortChange, -}: MobileFiltersProps) { - return ( -
-
- -
-
- -
-
- ); -} \ No newline at end of file diff --git a/Basin/src/components/ProjectCard.tsx b/Basin/src/components/ProjectCard.tsx deleted file mode 100644 index 7ba5eb8..0000000 --- a/Basin/src/components/ProjectCard.tsx +++ /dev/null @@ -1,178 +0,0 @@ -import React from 'react'; -import { ArrowRight, Github, ExternalLink, X } from 'lucide-react'; -import type { Project } from '../types'; -import { useProjectCard } from '../hooks/useProjectCard'; -import { cn } from '../utils/cn'; - -type ProjectCardProps = Project; - -export function ProjectCard(props: ProjectCardProps) { - const { - isExpanded, - containerRef, - contentRef, - toggleExpanded, - animationClass, - } = useProjectCard(); - - const { - icon: Icon, - title, - description, - technology, - color, - demoUrl, - sourceUrl, - category, - createdAt, - tags - } = props; - - return ( -
{ - if (e.key === 'Enter' || e.key === ' ') { - e.preventDefault(); - !isExpanded && toggleExpanded(); - } - if (e.key === 'Escape' && isExpanded) { - toggleExpanded(); - } - }} - aria-expanded={isExpanded} - > - {!isExpanded ? ( - // Collapsed View -
-
-
- -
-
-

- {title} -

-

{technology}

-
- -
-

{description}

-
- {category} - - {new Date(createdAt).toLocaleDateString()} - -
-
- ) : ( - // Expanded View -
-
-
- -
-

{title}

-

{technology}

-
-
- -
- -
-
-
- {`${title} -
-
-

About this project

-

{description}

- -

Development Process

-
    -
  • Initial planning and architecture design
  • -
  • Core functionality implementation
  • -
  • UI/UX refinement and testing
  • -
  • Performance optimization
  • -
- -

Key Challenges

-
    -
  • Optimizing performance for large datasets
  • -
  • Implementing real-time updates
  • -
  • Ensuring cross-browser compatibility
  • -
-
-
- -
-
-

Project Links

- -
- -
-

Project Details

-
-
- {tags.map((tag) => ( - - {tag} - - ))} -
-

Category: {category}

-

Created: {new Date(createdAt).toLocaleDateString()}

-

Technology: {technology}

-
-
-
-
-
- )} -
- ); -} \ No newline at end of file diff --git a/Basin/src/components/ProjectGrid.tsx b/Basin/src/components/ProjectGrid.tsx deleted file mode 100644 index b9d86a6..0000000 --- a/Basin/src/components/ProjectGrid.tsx +++ /dev/null @@ -1,108 +0,0 @@ -import React from 'react'; -import { Hash } from 'lucide-react'; -import { ProjectCard } from './ProjectCard'; -import { SortSelect, type SortOption } from './SortSelect'; -import type { Project } from '../types'; -import { SearchBar } from './SearchBar'; -import { CategoryFilter } from './CategoryFilter'; -import { useLocalStorage } from '../hooks/useLocalStorage'; -import { MobileFilters } from './MobileFilters'; - -const sortOptions: SortOption[] = [ - { label: 'Name (A-Z)', value: 'name-asc' }, - { label: 'Name (Z-A)', value: 'name-desc' }, - { label: 'Newest First', value: 'date-desc' }, - { label: 'Oldest First', value: 'date-asc' }, - { label: 'Category', value: 'category' }, -]; - -interface ProjectGridProps { - projects: Project[]; -} - -export function ProjectGrid({ projects }: ProjectGridProps) { - const [search, setSearch] = React.useState(''); - const [selectedCategory, setSelectedCategory] = React.useState('all'); - const [sortBy, setSortBy] = React.useState('name-asc'); - const [favorites, setFavorites] = useLocalStorage('favorites', []); - - const categories = React.useMemo(() => { - return Array.from(new Set(projects.map(p => p.category))); - }, [projects]); - - const filteredProjects = React.useMemo(() => { - return projects.filter(project => { - const matchesSearch = project.title.toLowerCase().includes(search.toLowerCase()) || - project.description.toLowerCase().includes(search.toLowerCase()) || - project.technology.toLowerCase().includes(search.toLowerCase()); - const matchesCategory = selectedCategory === 'all' || project.category === selectedCategory; - return matchesSearch && matchesCategory; - }); - }, [projects, search, selectedCategory]) - .sort((a, b) => { - switch (sortBy) { - case 'name-desc': - return b.title.localeCompare(a.title); - case 'date-desc': - return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(); - case 'date-asc': - return new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime(); - case 'category': - return a.category.localeCompare(b.category); - default: // name-asc - return a.title.localeCompare(b.title); - } - }); - - return ( -
-
- -
- -
-
- -
- -
-
- -
- -
- -
-
-
- -
- {filteredProjects.map((project) => ( - - ))} - {filteredProjects.length === 0 && ( -
-

- No projects found matching your criteria -

-
- )} -
-
- ); -} \ No newline at end of file diff --git a/Basin/src/components/ProjectList.tsx b/Basin/src/components/ProjectList.tsx deleted file mode 100644 index 2187ac4..0000000 --- a/Basin/src/components/ProjectList.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import React from 'react'; -import { ExternalLink, Github } from 'lucide-react'; -import type { Project } from '../types'; - -interface ProjectListProps { - projects: Project[]; -} - -export function ProjectList({ projects }: ProjectListProps) { - return ( -
- {projects.map((project) => ( -
-
- -
-
-
-

- {project.title} -

- -
-

- {project.description} -

-
- - {project.technology} - - - {project.category} - -
-
-
- ))} -
- ); -} \ No newline at end of file diff --git a/Basin/src/components/SearchBar.tsx b/Basin/src/components/SearchBar.tsx deleted file mode 100644 index 13ad8dd..0000000 --- a/Basin/src/components/SearchBar.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import React from 'react'; -import { Search } from 'lucide-react'; - -interface SearchBarProps { - value: string; - onChange: (value: string) => void; -} - -export function SearchBar({ value, onChange }: SearchBarProps) { - return ( -
-
- -
- onChange(e.target.value)} - className="w-[200px] pl-9 pr-3 py-2 bg-background text-foreground - placeholder-muted-foreground rounded-lg border border-input text-sm - focus:outline-none focus:ring-1 focus:ring-ring" - placeholder="Search projects..." - /> -
- ); -} \ No newline at end of file diff --git a/Basin/src/components/SortSelect.tsx b/Basin/src/components/SortSelect.tsx deleted file mode 100644 index de466b6..0000000 --- a/Basin/src/components/SortSelect.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import React from 'react'; -import { ArrowUpDown } from 'lucide-react'; - -export type SortOption = { - label: string; - value: string; -}; - -interface SortSelectProps { - value: string; - onChange: (value: string) => void; - options: SortOption[]; -} - -export function SortSelect({ value, onChange, options }: SortSelectProps) { - return ( -
- - -
- ); -} \ No newline at end of file diff --git a/Basin/src/components/ViewToggle.tsx b/Basin/src/components/ViewToggle.tsx deleted file mode 100644 index 1d714e4..0000000 --- a/Basin/src/components/ViewToggle.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import React from 'react'; -import { LayoutGrid, List } from 'lucide-react'; - -interface ViewToggleProps { - view: 'grid' | 'list'; - onViewChange: (view: 'grid' | 'list') => void; -} - -export function ViewToggle({ view, onViewChange }: ViewToggleProps) { - return ( -
- - -
- ); -} \ No newline at end of file diff --git a/Basin/src/data/projects.ts b/Basin/src/data/projects.ts index feffc07..e6ec30f 100644 --- a/Basin/src/data/projects.ts +++ b/Basin/src/data/projects.ts @@ -1,132 +1,16 @@ -import { - Palette, - Box, - Layers, - Sparkles, - Shapes, - Layout, - Paintbrush, - Component, - Pencil, -} from 'lucide-react'; -import type { Project } from '../types'; +import type { Tool } from '../types'; -export const projects: Project[] = [ +export const tools: Tool[] = [ { - icon: Palette, - title: 'Tailwind CSS', - technology: 'CSS Framework', - description: 'A utility-first CSS framework packed with classes that can be composed to build any design, directly in your markup.', - color: 'text-blue-600', - demoUrl: 'https://tailwindcss.com', - previewUrl: 'https://opengraph.githubassets.com/1/tailwindlabs/tailwindcss', - sourceUrl: 'https://github.com/tailwindlabs/tailwindcss', - category: 'CSS Framework', - tags: ['CSS', 'Utility-First', 'PostCSS', 'Design System'], - createdAt: '2024-03-15' + title: 'Email Signature', + description: 'Generate on-brand email signatures for Gmail and Outlook with live preview, drag-and-drop ordering, and one-click copy.', + path: '/email-signature', + tag: 'Brand', }, { - icon: Box, - title: 'Chakra UI', - technology: 'React Component Library', - description: 'A simple, modular and accessible component library that gives you the building blocks to build React applications.', - color: 'text-green-600', - demoUrl: 'https://chakra-ui.com', - previewUrl: 'https://opengraph.githubassets.com/1/chakra-ui/chakra-ui', - sourceUrl: 'https://github.com/chakra-ui/chakra-ui', - category: 'Component Library', - tags: ['React', 'Accessible', 'Themeable', 'Components'], - createdAt: '2024-03-10' + title: 'Voronoi Explorer', + description: 'Interactive Voronoi diagram generator with chromatic aberration, layered rendering, and preset management.', + path: '/voronoi', + tag: 'Generative', }, - { - icon: Layers, - title: 'Radix UI', - technology: 'Headless Components', - description: 'Unstyled, accessible components for building high‑quality design systems and web apps in React.', - color: 'text-purple-600', - demoUrl: 'https://www.radix-ui.com', - previewUrl: 'https://opengraph.githubassets.com/1/radix-ui/primitives', - sourceUrl: 'https://github.com/radix-ui/primitives', - category: 'Design System', - tags: ['Headless UI', 'Accessible', 'React', 'Primitives'], - createdAt: '2024-03-05' - }, - { - icon: Sparkles, - title: 'Framer Motion', - technology: 'Animation Library', - description: 'A production-ready motion library for React. Utilize the power of animation to create engaging user interfaces.', - color: 'text-orange-600', - demoUrl: 'https://www.framer.com/motion', - previewUrl: 'https://opengraph.githubassets.com/1/framer/motion', - sourceUrl: 'https://github.com/framer/motion', - category: 'Animation', - tags: ['Animation', 'React', 'Motion', 'Gestures'], - createdAt: '2024-03-01' - }, - { - icon: Shapes, - title: 'Storybook', - technology: 'Development Environment', - description: 'Build UI components and pages in isolation. It streamlines UI development, testing, and documentation.', - color: 'text-red-600', - demoUrl: 'https://storybook.js.org', - previewUrl: 'https://opengraph.githubassets.com/1/storybookjs/storybook', - sourceUrl: 'https://github.com/storybookjs/storybook', - category: 'Development Tools', - tags: ['Documentation', 'Testing', 'Components', 'Development'], - createdAt: '2024-02-28' - }, - { - icon: Layout, - title: 'shadcn/ui', - technology: 'React Components', - description: 'Beautifully designed components built with Radix UI and Tailwind CSS. Copy and paste into your apps.', - color: 'text-indigo-600', - demoUrl: 'https://ui.shadcn.com', - previewUrl: 'https://opengraph.githubassets.com/1/shadcn-ui/ui', - sourceUrl: 'https://github.com/shadcn-ui/ui', - category: 'Component Library', - tags: ['React', 'Tailwind CSS', 'Radix UI', 'Components'], - createdAt: '2024-02-25' - }, - { - icon: Paintbrush, - title: 'Material UI', - technology: 'React UI Framework', - description: 'A comprehensive suite of UI tools and components, implementing Google\'s Material Design.', - color: 'text-pink-600', - demoUrl: 'https://mui.com', - previewUrl: 'https://opengraph.githubassets.com/1/mui/material-ui', - sourceUrl: 'https://github.com/mui/material-ui', - category: 'Design System', - tags: ['Material Design', 'React', 'Components', 'Theme'], - createdAt: '2024-02-20' - }, - { - icon: Component, - title: 'Mantine', - technology: 'React Components', - description: 'A fully featured React components library with 100+ customizable components and hooks.', - color: 'text-cyan-600', - demoUrl: 'https://mantine.dev', - previewUrl: 'https://opengraph.githubassets.com/1/mantinedev/mantine', - sourceUrl: 'https://github.com/mantinedev/mantine', - category: 'Component Library', - tags: ['React', 'TypeScript', 'Hooks', 'Theming'], - createdAt: '2024-02-15' - }, - { - icon: Pencil, - title: 'Figma UI Kit', - technology: 'Design Resources', - description: 'Open-source UI kit for Figma with comprehensive design components and styles.', - color: 'text-yellow-600', - demoUrl: 'https://www.figma.com/community/file/768809027799962739', - previewUrl: 'https://opengraph.githubassets.com/1/figma/figma-api-demo', - sourceUrl: 'https://github.com/figma/figma-api-demo', - category: 'Design Tools', - tags: ['Figma', 'UI Kit', 'Design System', 'Resources'], - createdAt: '2024-02-10' - } -]; \ No newline at end of file +]; diff --git a/Basin/src/hooks/useLocalStorage.ts b/Basin/src/hooks/useLocalStorage.ts deleted file mode 100644 index 4516ea1..0000000 --- a/Basin/src/hooks/useLocalStorage.ts +++ /dev/null @@ -1,25 +0,0 @@ -'use client'; - -import { useState, useEffect } from 'react'; - -export function useLocalStorage(key: string, initialValue: T) { - const [storedValue, setStoredValue] = useState(() => { - try { - const item = window.localStorage.getItem(key); - return item ? JSON.parse(item) : initialValue; - } catch (error) { - console.error(error); - return initialValue; - } - }); - - useEffect(() => { - try { - window.localStorage.setItem(key, JSON.stringify(storedValue)); - } catch (error) { - console.error(error); - } - }, [key, storedValue]); - - return [storedValue, setStoredValue] as const; -} \ No newline at end of file diff --git a/Basin/src/hooks/useProjectCard.ts b/Basin/src/hooks/useProjectCard.ts deleted file mode 100644 index e32c7fa..0000000 --- a/Basin/src/hooks/useProjectCard.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { useRef, useState, useEffect } from 'react'; - -export function useProjectCard() { - const [isExpanded, setIsExpanded] = useState(false); - const [animationClass, setAnimationClass] = useState(''); - const containerRef = useRef(null); - const contentRef = useRef(null); - - useEffect(() => { - if (isExpanded) { - // Add overlay to other cards - const cards = document.querySelectorAll('.project-card'); - cards.forEach((card) => { - if (card !== containerRef.current) { - card.classList.add('opacity-50'); - } - }); - - // Animate content - if (contentRef.current) { - requestAnimationFrame(() => { - contentRef.current?.classList.remove('opacity-0'); - }); - } - - // Scroll into view if needed - containerRef.current?.scrollIntoView({ - behavior: 'smooth', - block: 'nearest', - }); - } else { - // Remove overlay from other cards - const cards = document.querySelectorAll('.project-card'); - cards.forEach((card) => { - card.classList.remove('opacity-50'); - }); - - // Hide content - if (contentRef.current) { - contentRef.current.classList.add('opacity-0'); - } - } - }, [isExpanded]); - - const toggleExpanded = () => { - if (!isExpanded) { - setAnimationClass('scale-[1.02]'); - setTimeout(() => setAnimationClass(''), 300); - } - setIsExpanded(!isExpanded); - }; - - return { - isExpanded, - containerRef, - contentRef, - toggleExpanded, - animationClass, - }; -} \ No newline at end of file diff --git a/Basin/src/hooks/useTheme.ts b/Basin/src/hooks/useTheme.ts deleted file mode 100644 index 0e90f91..0000000 --- a/Basin/src/hooks/useTheme.ts +++ /dev/null @@ -1,36 +0,0 @@ -'use client'; - -import { useEffect, useState } from 'react'; - -type Theme = 'light' | 'dark'; - -const getSystemTheme = (): Theme => { - if (typeof window === 'undefined') return 'light'; - return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; -}; - -export function useTheme() { - const [mounted, setMounted] = useState(false); - const [theme, setTheme] = useState(() => { - if (typeof window === 'undefined') return 'light'; - return (localStorage.getItem('theme') as Theme) || getSystemTheme(); - }); - - useEffect(() => { - setMounted(true); - }, []); - - useEffect(() => { - if (!mounted) return; - const root = window.document.documentElement; - root.classList.remove('light', 'dark'); - root.classList.add(theme); - localStorage.setItem('theme', theme); - }, [theme, mounted]); - - if (!mounted) { - return { theme: 'light', setTheme: () => {} }; - } - - return { theme, setTheme }; -} \ No newline at end of file diff --git a/Basin/src/types/index.ts b/Basin/src/types/index.ts index 083ad86..5f42a76 100644 --- a/Basin/src/types/index.ts +++ b/Basin/src/types/index.ts @@ -1,15 +1,6 @@ -import { LucideIcon } from 'lucide-react'; - -export interface Project { - icon: LucideIcon; +export interface Tool { title: string; - technology: string; description: string; - color: string; - demoUrl: string; - previewUrl: string; - sourceUrl: string; - category: string; - tags: string[]; - createdAt: string; // ISO date string -} \ No newline at end of file + path: string; + tag: string; +} diff --git a/Basin/src/utils/getOgImage.ts b/Basin/src/utils/getOgImage.ts deleted file mode 100644 index fd95a90..0000000 --- a/Basin/src/utils/getOgImage.ts +++ /dev/null @@ -1,12 +0,0 @@ -export function getOgImage(url: string): string { - // Remove trailing slash if present - const cleanUrl = url.replace(/\/$/, ''); - - // Known patterns for popular sites - if (cleanUrl.includes('github.com')) { - return `https://opengraph.githubassets.com/1/${cleanUrl.split('github.com/')[1]}`; - } - - // For other sites, use a reliable OG image service - return `https://og-image.vercel.app/${encodeURIComponent(cleanUrl)}`; -} \ No newline at end of file From ca165e7921b54258a15e63d0e1261931bf90e106 Mon Sep 17 00:00:00 2001 From: Corey Thomas <125082303+Corey-T1000@users.noreply.github.com> Date: Thu, 12 Mar 2026 18:00:05 -0400 Subject: [PATCH 2/4] feat(basin): add OG image generator tool Browser-based OpenGraph image generator using Canvas API with voronoi backgrounds, 5 theme presets, live preview, and PNG export. Replaces the Node.js CLI tool for interactive use. Co-Authored-By: Claude Opus 4.6 --- Basin/public/og-generator/index.html | 993 ++++++++++++++++++ .../og-generator/og-generator/index.html | 993 ++++++++++++++++++ Basin/src/data/projects.ts | 6 + 3 files changed, 1992 insertions(+) create mode 100644 Basin/public/og-generator/index.html create mode 100644 Basin/public/og-generator/og-generator/index.html diff --git a/Basin/public/og-generator/index.html b/Basin/public/og-generator/index.html new file mode 100644 index 0000000..e35a0ff --- /dev/null +++ b/Basin/public/og-generator/index.html @@ -0,0 +1,993 @@ + + + + + +OG Image Generator — AuthZed + + + + + + + + + + + +
+
+

Preview — 1200 × 630

+ Ready +
+
+
+ +
Rendering…
+
+
+
+ + + + diff --git a/Basin/public/og-generator/og-generator/index.html b/Basin/public/og-generator/og-generator/index.html new file mode 100644 index 0000000..e35a0ff --- /dev/null +++ b/Basin/public/og-generator/og-generator/index.html @@ -0,0 +1,993 @@ + + + + + +OG Image Generator — AuthZed + + + + + + + + + + + +
+
+

Preview — 1200 × 630

+ Ready +
+
+
+ +
Rendering…
+
+
+
+ + + + diff --git a/Basin/src/data/projects.ts b/Basin/src/data/projects.ts index e6ec30f..782e77f 100644 --- a/Basin/src/data/projects.ts +++ b/Basin/src/data/projects.ts @@ -7,6 +7,12 @@ export const tools: Tool[] = [ path: '/email-signature', tag: 'Brand', }, + { + title: 'OG Image Generator', + description: 'Create OpenGraph preview images for blog posts with voronoi backgrounds, theme presets, and PNG export.', + path: '/og-generator', + tag: 'Content', + }, { title: 'Voronoi Explorer', description: 'Interactive Voronoi diagram generator with chromatic aberration, layered rendering, and preset management.', From efde8f79154c61afe42de22750a5d0a1a3e710de Mon Sep 17 00:00:00 2001 From: Corey Thomas <125082303+Corey-T1000@users.noreply.github.com> Date: Thu, 12 Mar 2026 18:00:27 -0400 Subject: [PATCH 3/4] chore: remove duplicate nested og-generator directory Co-Authored-By: Claude Opus 4.6 --- .../og-generator/og-generator/index.html | 993 ------------------ 1 file changed, 993 deletions(-) delete mode 100644 Basin/public/og-generator/og-generator/index.html diff --git a/Basin/public/og-generator/og-generator/index.html b/Basin/public/og-generator/og-generator/index.html deleted file mode 100644 index e35a0ff..0000000 --- a/Basin/public/og-generator/og-generator/index.html +++ /dev/null @@ -1,993 +0,0 @@ - - - - - -OG Image Generator — AuthZed - - - - - - - - - - - -
-
-

Preview — 1200 × 630

- Ready -
-
-
- -
Rendering…
-
-
-
- - - - From 2d7e5be2919011be5114267dae7f5a7a1b4ef6d1 Mon Sep 17 00:00:00 2001 From: Corey Thomas <125082303+Corey-T1000@users.noreply.github.com> Date: Thu, 12 Mar 2026 18:04:00 -0400 Subject: [PATCH 4/4] revert: remove OG generator from Basin Browser version can't match the CLI tool's multi-layer voronoi renderer quality. Keeping OG generation as CLI-only via /og skill. Co-Authored-By: Claude Opus 4.6 --- Basin/public/og-generator/index.html | 993 --------------------------- Basin/src/data/projects.ts | 8 +- 2 files changed, 1 insertion(+), 1000 deletions(-) delete mode 100644 Basin/public/og-generator/index.html diff --git a/Basin/public/og-generator/index.html b/Basin/public/og-generator/index.html deleted file mode 100644 index e35a0ff..0000000 --- a/Basin/public/og-generator/index.html +++ /dev/null @@ -1,993 +0,0 @@ - - - - - -OG Image Generator — AuthZed - - - - - - - - - - - -
-
-

Preview — 1200 × 630

- Ready -
-
-
- -
Rendering…
-
-
-
- - - - diff --git a/Basin/src/data/projects.ts b/Basin/src/data/projects.ts index 782e77f..895a2e8 100644 --- a/Basin/src/data/projects.ts +++ b/Basin/src/data/projects.ts @@ -7,13 +7,7 @@ export const tools: Tool[] = [ path: '/email-signature', tag: 'Brand', }, - { - title: 'OG Image Generator', - description: 'Create OpenGraph preview images for blog posts with voronoi backgrounds, theme presets, and PNG export.', - path: '/og-generator', - tag: 'Content', - }, - { +{ title: 'Voronoi Explorer', description: 'Interactive Voronoi diagram generator with chromatic aberration, layered rendering, and preset management.', path: '/voronoi',