Major redesign: Enhanced card display with particle effects, improved filters, and search functionality

- Redesigned card display with 2.5:3.5 aspect ratio and image-only view
- Added infinite scroll to replace pagination
- Implemented authentic card back placeholders for MTG, Pokemon, and Lorcana
- Added rarity-based particle effects with tiered intensity (mythic/enchanted/rare/uncommon)
- Enhanced hover details panel with structured card information
- Fixed search functionality with debouncing and Enter key support
- Improved filter system with working TCG, rarity, set, and price filters
- Added favorite system for cards in both hover and detail views
- Updated card detail page with comprehensive metadata and actions
- Fixed API filtering with proper Vercel Postgres implementation
- Added particle animations and rarity glow effects
- Improved overall UX with better visual hierarchy and interactions
This commit is contained in:
Randall Stillwell 2025-07-23 21:26:54 -05:00
parent c218dd53ac
commit e75a4a6649
184 changed files with 14431 additions and 10491 deletions

38
.next/build-manifest.json Normal file
View file

@ -0,0 +1,38 @@
{
"polyfillFiles": [
"static/chunks/polyfills.js"
],
"devFiles": [
"static/chunks/react-refresh.js"
],
"ampDevFiles": [],
"lowPriorityFiles": [
"static/development/_buildManifest.js",
"static/development/_ssgManifest.js"
],
"rootMainFiles": [],
"rootMainFilesTree": {},
"pages": {
"/_app": [
"static/chunks/webpack.js",
"static/chunks/main.js",
"static/chunks/pages/_app.js"
],
"/_error": [
"static/chunks/webpack.js",
"static/chunks/main.js",
"static/chunks/pages/_error.js"
],
"/admin/card-import": [
"static/chunks/webpack.js",
"static/chunks/main.js",
"static/chunks/pages/admin/card-import.js"
],
"/cards": [
"static/chunks/webpack.js",
"static/chunks/main.js",
"static/chunks/pages/cards.js"
]
},
"ampFirstPages": []
}

1
.next/cache/.rscinfo vendored Normal file
View file

@ -0,0 +1 @@
{"encryption.key":"o/3/KjisNjAoqH8UnTw+YIJZ5yKpbxNOeTedTrWeK48=","encryption.expire_at":1754507955052}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

1
.next/package.json Normal file
View file

@ -0,0 +1 @@
{"type": "commonjs"}

View file

@ -0,0 +1,11 @@
{
"version": 4,
"routes": {},
"dynamicRoutes": {},
"notFoundRoutes": [],
"preview": {
"previewModeId": "ac69d87d469cfc0883867cbac62985a1",
"previewModeSigningKey": "f42e8072c0ccf0a25b633a0cca347d2ff35cf4136bc15882d176886cd9588e37",
"previewModeEncryptionKey": "c73779c91ac71021885e2cccce8a37ae8601cfca2f618e58f8dea7b27938b2a3"
}
}

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1 @@
{"version":3,"caseSensitive":false,"basePath":"","rewrites":{"beforeFiles":[],"afterFiles":[],"fallback":[]},"redirects":[{"source":"/:path+/","destination":"/:path+","permanent":true,"internal":true,"regex":"^(?:\\/((?:[^\\/]+?)(?:\\/(?:[^\\/]+?))*))\\/$"}],"headers":[]}

211
.next/server/_error.js Normal file

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
self.__INTERCEPTION_ROUTE_REWRITE_MANIFEST="[]"

View file

@ -0,0 +1,40 @@
globalThis.__BUILD_MANIFEST = {
"polyfillFiles": [
"static/chunks/polyfills.js"
],
"devFiles": [
"static/chunks/react-refresh.js"
],
"ampDevFiles": [],
"lowPriorityFiles": [],
"rootMainFiles": [],
"rootMainFilesTree": {},
"pages": {
"/_app": [
"static/chunks/webpack.js",
"static/chunks/main.js",
"static/chunks/pages/_app.js"
],
"/_error": [
"static/chunks/webpack.js",
"static/chunks/main.js",
"static/chunks/pages/_error.js"
],
"/admin/card-import": [
"static/chunks/webpack.js",
"static/chunks/main.js",
"static/chunks/pages/admin/card-import.js"
],
"/cards": [
"static/chunks/webpack.js",
"static/chunks/main.js",
"static/chunks/pages/cards.js"
]
},
"ampFirstPages": []
};
globalThis.__BUILD_MANIFEST.lowPriorityFiles = [
"/static/" + process.env.__NEXT_BUILD_ID + "/_buildManifest.js",
,"/static/" + process.env.__NEXT_BUILD_ID + "/_ssgManifest.js",
];

View file

@ -0,0 +1,6 @@
{
"version": 3,
"middleware": {},
"functions": {},
"sortedMiddleware": []
}

View file

@ -0,0 +1 @@
self.__REACT_LOADABLE_MANIFEST="{}"

View file

@ -0,0 +1 @@
self.__NEXT_FONT_MANIFEST="{\"pages\":{},\"app\":{},\"appUsingSizeAdjust\":false,\"pagesUsingSizeAdjust\":false}"

View file

@ -0,0 +1 @@
{"pages":{},"app":{},"appUsingSizeAdjust":false,"pagesUsingSizeAdjust":false}

View file

@ -0,0 +1,8 @@
{
"/_app": "pages/_app.js",
"/_error": "pages/_error.js",
"/_document": "pages/_document.js",
"/admin/card-import": "pages/admin/card-import.js",
"/api/cards/import-pokemon": "pages/api/cards/import-pokemon.js",
"/cards": "pages/cards.js"
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,66 @@
"use strict";
/*
* ATTENTION: An "eval-source-map" devtool has been used.
* This devtool is neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/
(() => {
var exports = {};
exports.id = "pages/_document";
exports.ids = ["pages/_document"];
exports.modules = {
/***/ "next/dist/compiled/next-server/pages.runtime.dev.js":
/*!**********************************************************************!*\
!*** external "next/dist/compiled/next-server/pages.runtime.dev.js" ***!
\**********************************************************************/
/***/ ((module) => {
module.exports = require("next/dist/compiled/next-server/pages.runtime.dev.js");
/***/ }),
/***/ "path":
/*!***********************!*\
!*** external "path" ***!
\***********************/
/***/ ((module) => {
module.exports = require("path");
/***/ }),
/***/ "react":
/*!************************!*\
!*** external "react" ***!
\************************/
/***/ ((module) => {
module.exports = require("react");
/***/ }),
/***/ "react/jsx-runtime":
/*!************************************!*\
!*** external "react/jsx-runtime" ***!
\************************************/
/***/ ((module) => {
module.exports = require("react/jsx-runtime");
/***/ })
};
;
// load runtime
var __webpack_require__ = require("../webpack-runtime.js");
__webpack_require__.C(exports);
var __webpack_exec__ = (moduleId) => (__webpack_require__(__webpack_require__.s = moduleId))
var __webpack_exports__ = __webpack_require__.X(0, ["vendor-chunks/next","vendor-chunks/@swc"], () => (__webpack_exec__("(pages-dir-node)/./node_modules/next/dist/pages/_document.js")));
module.exports = __webpack_exports__;
})();

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

277
.next/server/pages/cards.js Normal file

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,35 @@
"use strict";
/*
* ATTENTION: An "eval-source-map" devtool has been used.
* This devtool is neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/
exports.id = "vendor-chunks/@swc";
exports.ids = ["vendor-chunks/@swc"];
exports.modules = {
/***/ "(pages-dir-node)/./node_modules/@swc/helpers/cjs/_interop_require_default.cjs":
/*!********************************************************************!*\
!*** ./node_modules/@swc/helpers/cjs/_interop_require_default.cjs ***!
\********************************************************************/
/***/ ((__unused_webpack_module, exports) => {
eval("\n\nfunction _interop_require_default(obj) {\n return obj && obj.__esModule ? obj : { default: obj };\n}\nexports._ = _interop_require_default;\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKHBhZ2VzLWRpci1ub2RlKS8uL25vZGVfbW9kdWxlcy9Ac3djL2hlbHBlcnMvY2pzL19pbnRlcm9wX3JlcXVpcmVfZGVmYXVsdC5janMiLCJtYXBwaW5ncyI6IkFBQWE7O0FBRWI7QUFDQSwyQ0FBMkM7QUFDM0M7QUFDQSxTQUFTIiwic291cmNlcyI6WyIvVXNlcnMvcnN0aWxsdy9Eb2N1bWVudHMvdGNnLXZhdWx0L25vZGVfbW9kdWxlcy9Ac3djL2hlbHBlcnMvY2pzL19pbnRlcm9wX3JlcXVpcmVfZGVmYXVsdC5janMiXSwic291cmNlc0NvbnRlbnQiOlsiXCJ1c2Ugc3RyaWN0XCI7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wX3JlcXVpcmVfZGVmYXVsdChvYmopIHtcbiAgICByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyBkZWZhdWx0OiBvYmogfTtcbn1cbmV4cG9ydHMuXyA9IF9pbnRlcm9wX3JlcXVpcmVfZGVmYXVsdDtcbiJdLCJuYW1lcyI6W10sImlnbm9yZUxpc3QiOlswXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///(pages-dir-node)/./node_modules/@swc/helpers/cjs/_interop_require_default.cjs\n");
/***/ }),
/***/ "(pages-dir-node)/./node_modules/@swc/helpers/cjs/_interop_require_wildcard.cjs":
/*!*********************************************************************!*\
!*** ./node_modules/@swc/helpers/cjs/_interop_require_wildcard.cjs ***!
\*********************************************************************/
/***/ ((__unused_webpack_module, exports) => {
eval("\n\nfunction _getRequireWildcardCache(nodeInterop) {\n if (typeof WeakMap !== \"function\") return null;\n\n var cacheBabelInterop = new WeakMap();\n var cacheNodeInterop = new WeakMap();\n\n return (_getRequireWildcardCache = function(nodeInterop) {\n return nodeInterop ? cacheNodeInterop : cacheBabelInterop;\n })(nodeInterop);\n}\nfunction _interop_require_wildcard(obj, nodeInterop) {\n if (!nodeInterop && obj && obj.__esModule) return obj;\n if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") return { default: obj };\n\n var cache = _getRequireWildcardCache(nodeInterop);\n\n if (cache && cache.has(obj)) return cache.get(obj);\n\n var newObj = { __proto__: null };\n var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;\n\n for (var key in obj) {\n if (key !== \"default\" && Object.prototype.hasOwnProperty.call(obj, key)) {\n var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;\n if (desc && (desc.get || desc.set)) Object.defineProperty(newObj, key, desc);\n else newObj[key] = obj[key];\n }\n }\n\n newObj.default = obj;\n\n if (cache) cache.set(obj, newObj);\n\n return newObj;\n}\nexports._ = _interop_require_wildcard;\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKHBhZ2VzLWRpci1ub2RlKS8uL25vZGVfbW9kdWxlcy9Ac3djL2hlbHBlcnMvY2pzL19pbnRlcm9wX3JlcXVpcmVfd2lsZGNhcmQuY2pzIiwibWFwcGluZ3MiOiJBQUFhOztBQUViO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLHVGQUF1Rjs7QUFFdkY7O0FBRUE7O0FBRUEsbUJBQW1CO0FBQ25COztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxTQUFTIiwic291cmNlcyI6WyIvVXNlcnMvcnN0aWxsdy9Eb2N1bWVudHMvdGNnLXZhdWx0L25vZGVfbW9kdWxlcy9Ac3djL2hlbHBlcnMvY2pzL19pbnRlcm9wX3JlcXVpcmVfd2lsZGNhcmQuY2pzIl0sInNvdXJjZXNDb250ZW50IjpbIlwidXNlIHN0cmljdFwiO1xuXG5mdW5jdGlvbiBfZ2V0UmVxdWlyZVdpbGRjYXJkQ2FjaGUobm9kZUludGVyb3ApIHtcbiAgICBpZiAodHlwZW9mIFdlYWtNYXAgIT09IFwiZnVuY3Rpb25cIikgcmV0dXJuIG51bGw7XG5cbiAgICB2YXIgY2FjaGVCYWJlbEludGVyb3AgPSBuZXcgV2Vha01hcCgpO1xuICAgIHZhciBjYWNoZU5vZGVJbnRlcm9wID0gbmV3IFdlYWtNYXAoKTtcblxuICAgIHJldHVybiAoX2dldFJlcXVpcmVXaWxkY2FyZENhY2hlID0gZnVuY3Rpb24obm9kZUludGVyb3ApIHtcbiAgICAgICAgcmV0dXJuIG5vZGVJbnRlcm9wID8gY2FjaGVOb2RlSW50ZXJvcCA6IGNhY2hlQmFiZWxJbnRlcm9wO1xuICAgIH0pKG5vZGVJbnRlcm9wKTtcbn1cbmZ1bmN0aW9uIF9pbnRlcm9wX3JlcXVpcmVfd2lsZGNhcmQob2JqLCBub2RlSW50ZXJvcCkge1xuICAgIGlmICghbm9kZUludGVyb3AgJiYgb2JqICYmIG9iai5fX2VzTW9kdWxlKSByZXR1cm4gb2JqO1xuICAgIGlmIChvYmogPT09IG51bGwgfHwgdHlwZW9mIG9iaiAhPT0gXCJvYmplY3RcIiAmJiB0eXBlb2Ygb2JqICE9PSBcImZ1bmN0aW9uXCIpIHJldHVybiB7IGRlZmF1bHQ6IG9iaiB9O1xuXG4gICAgdmFyIGNhY2hlID0gX2dldFJlcXVpcmVXaWxkY2FyZENhY2hlKG5vZGVJbnRlcm9wKTtcblxuICAgIGlmIChjYWNoZSAmJiBjYWNoZS5oYXMob2JqKSkgcmV0dXJuIGNhY2hlLmdldChvYmopO1xuXG4gICAgdmFyIG5ld09iaiA9IHsgX19wcm90b19fOiBudWxsIH07XG4gICAgdmFyIGhhc1Byb3BlcnR5RGVzY3JpcHRvciA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSAmJiBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yO1xuXG4gICAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgICAgICBpZiAoa2V5ICE9PSBcImRlZmF1bHRcIiAmJiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBrZXkpKSB7XG4gICAgICAgICAgICB2YXIgZGVzYyA9IGhhc1Byb3BlcnR5RGVzY3JpcHRvciA/IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Iob2JqLCBrZXkpIDogbnVsbDtcbiAgICAgICAgICAgIGlmIChkZXNjICYmIChkZXNjLmdldCB8fCBkZXNjLnNldCkpIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShuZXdPYmosIGtleSwgZGVzYyk7XG4gICAgICAgICAgICBlbHNlIG5ld09ialtrZXldID0gb2JqW2tleV07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBuZXdPYmouZGVmYXVsdCA9IG9iajtcblxuICAgIGlmIChjYWNoZSkgY2FjaGUuc2V0KG9iaiwgbmV3T2JqKTtcblxuICAgIHJldHVybiBuZXdPYmo7XG59XG5leHBvcnRzLl8gPSBfaW50ZXJvcF9yZXF1aXJlX3dpbGRjYXJkO1xuIl0sIm5hbWVzIjpbXSwiaWdub3JlTGlzdCI6WzBdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///(pages-dir-node)/./node_modules/@swc/helpers/cjs/_interop_require_wildcard.cjs\n");
/***/ })
};
;

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,237 @@
/*
* ATTENTION: An "eval-source-map" devtool has been used.
* This devtool is neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/
/******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({});
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ var threw = true;
/******/ try {
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/ threw = false;
/******/ } finally {
/******/ if(threw) delete __webpack_module_cache__[moduleId];
/******/ }
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = __webpack_modules__;
/******/
/************************************************************************/
/******/ /* webpack/runtime/async module */
/******/ (() => {
/******/ var webpackQueues = typeof Symbol === "function" ? Symbol("webpack queues") : "__webpack_queues__";
/******/ var webpackExports = typeof Symbol === "function" ? Symbol("webpack exports") : "__webpack_exports__";
/******/ var webpackError = typeof Symbol === "function" ? Symbol("webpack error") : "__webpack_error__";
/******/ var resolveQueue = (queue) => {
/******/ if(queue && queue.d < 1) {
/******/ queue.d = 1;
/******/ queue.forEach((fn) => (fn.r--));
/******/ queue.forEach((fn) => (fn.r-- ? fn.r++ : fn()));
/******/ }
/******/ }
/******/ var wrapDeps = (deps) => (deps.map((dep) => {
/******/ if(dep !== null && typeof dep === "object") {
/******/ if(dep[webpackQueues]) return dep;
/******/ if(dep.then) {
/******/ var queue = [];
/******/ queue.d = 0;
/******/ dep.then((r) => {
/******/ obj[webpackExports] = r;
/******/ resolveQueue(queue);
/******/ }, (e) => {
/******/ obj[webpackError] = e;
/******/ resolveQueue(queue);
/******/ });
/******/ var obj = {};
/******/ obj[webpackQueues] = (fn) => (fn(queue));
/******/ return obj;
/******/ }
/******/ }
/******/ var ret = {};
/******/ ret[webpackQueues] = x => {};
/******/ ret[webpackExports] = dep;
/******/ return ret;
/******/ }));
/******/ __webpack_require__.a = (module, body, hasAwait) => {
/******/ var queue;
/******/ hasAwait && ((queue = []).d = -1);
/******/ var depQueues = new Set();
/******/ var exports = module.exports;
/******/ var currentDeps;
/******/ var outerResolve;
/******/ var reject;
/******/ var promise = new Promise((resolve, rej) => {
/******/ reject = rej;
/******/ outerResolve = resolve;
/******/ });
/******/ promise[webpackExports] = exports;
/******/ promise[webpackQueues] = (fn) => (queue && fn(queue), depQueues.forEach(fn), promise["catch"](x => {}));
/******/ module.exports = promise;
/******/ body((deps) => {
/******/ currentDeps = wrapDeps(deps);
/******/ var fn;
/******/ var getResult = () => (currentDeps.map((d) => {
/******/ if(d[webpackError]) throw d[webpackError];
/******/ return d[webpackExports];
/******/ }))
/******/ var promise = new Promise((resolve) => {
/******/ fn = () => (resolve(getResult));
/******/ fn.r = 0;
/******/ var fnQueue = (q) => (q !== queue && !depQueues.has(q) && (depQueues.add(q), q && !q.d && (fn.r++, q.push(fn))));
/******/ currentDeps.map((dep) => (dep[webpackQueues](fnQueue)));
/******/ });
/******/ return fn.r ? promise : getResult();
/******/ }, (err) => ((err ? reject(promise[webpackError] = err) : outerResolve(exports)), resolveQueue(queue)));
/******/ queue && queue.d < 0 && (queue.d = 0);
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/compat get default export */
/******/ (() => {
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = (module) => {
/******/ var getter = module && module.__esModule ?
/******/ () => (module['default']) :
/******/ () => (module);
/******/ __webpack_require__.d(getter, { a: getter });
/******/ return getter;
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/ensure chunk */
/******/ (() => {
/******/ __webpack_require__.f = {};
/******/ // This file contains only the entry chunk.
/******/ // The chunk loading function for additional chunks
/******/ __webpack_require__.e = (chunkId) => {
/******/ return Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => {
/******/ __webpack_require__.f[key](chunkId, promises);
/******/ return promises;
/******/ }, []));
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/get javascript chunk filename */
/******/ (() => {
/******/ // This function allow to reference async chunks and sibling chunks for the entrypoint
/******/ __webpack_require__.u = (chunkId) => {
/******/ // return url for filenames based on template
/******/ return "" + chunkId + ".js";
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ (() => {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = (exports) => {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/startup entrypoint */
/******/ (() => {
/******/ __webpack_require__.X = (result, chunkIds, fn) => {
/******/ // arguments: chunkIds, moduleId are deprecated
/******/ var moduleId = chunkIds;
/******/ if(!fn) chunkIds = result, fn = () => (__webpack_require__(__webpack_require__.s = moduleId));
/******/ chunkIds.map(__webpack_require__.e, __webpack_require__)
/******/ var r = fn();
/******/ return r === undefined ? result : r;
/******/ }
/******/ })();
/******/
/******/ /* webpack/runtime/require chunk loading */
/******/ (() => {
/******/ // no baseURI
/******/
/******/ // object to store loaded chunks
/******/ // "1" means "loaded", otherwise not loaded yet
/******/ var installedChunks = {
/******/ "webpack-api-runtime": 1
/******/ };
/******/
/******/ // no on chunks loaded
/******/
/******/ var installChunk = (chunk) => {
/******/ var moreModules = chunk.modules, chunkIds = chunk.ids, runtime = chunk.runtime;
/******/ for(var moduleId in moreModules) {
/******/ if(__webpack_require__.o(moreModules, moduleId)) {
/******/ __webpack_require__.m[moduleId] = moreModules[moduleId];
/******/ }
/******/ }
/******/ if(runtime) runtime(__webpack_require__);
/******/ for(var i = 0; i < chunkIds.length; i++)
/******/ installedChunks[chunkIds[i]] = 1;
/******/
/******/ };
/******/
/******/ // require() chunk loading for javascript
/******/ __webpack_require__.f.require = (chunkId, promises) => {
/******/ // "1" is the signal for "already loaded"
/******/ if(!installedChunks[chunkId]) {
/******/ if("webpack-api-runtime" != chunkId) {
/******/ installChunk(require("./" + __webpack_require__.u(chunkId)));
/******/ } else installedChunks[chunkId] = 1;
/******/ }
/******/ };
/******/
/******/ module.exports = __webpack_require__;
/******/ __webpack_require__.C = installChunk;
/******/
/******/ // no HMR
/******/
/******/ // no HMR manifest
/******/ })();
/******/
/************************************************************************/
/******/
/******/
/******/ })()
;

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,28 @@
/*
* ATTENTION: An "eval-source-map" devtool has been used.
* This devtool is neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/
(self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([["/_error"],{
/***/ "(pages-dir-browser)/./node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?absolutePagePath=%2FUsers%2Frstillw%2FDocuments%2Ftcg-vault%2Fnode_modules%2Fnext%2Fdist%2Fpages%2F_error.js&page=%2F_error!":
/*!***************************************************************************************************************************************************************************************************************!*\
!*** ./node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?absolutePagePath=%2FUsers%2Frstillw%2FDocuments%2Ftcg-vault%2Fnode_modules%2Fnext%2Fdist%2Fpages%2F_error.js&page=%2F_error! ***!
\***************************************************************************************************************************************************************************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
eval(__webpack_require__.ts("\n (window.__NEXT_P = window.__NEXT_P || []).push([\n \"/_error\",\n function () {\n return __webpack_require__(/*! ./node_modules/next/dist/pages/_error.js */ \"(pages-dir-browser)/./node_modules/next/dist/pages/_error.js\");\n }\n ]);\n if(true) {\n module.hot.dispose(function () {\n window.__NEXT_P.push([\"/_error\"])\n });\n }\n //# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKHBhZ2VzLWRpci1icm93c2VyKS8uL25vZGVfbW9kdWxlcy9uZXh0L2Rpc3QvYnVpbGQvd2VicGFjay9sb2FkZXJzL25leHQtY2xpZW50LXBhZ2VzLWxvYWRlci5qcz9hYnNvbHV0ZVBhZ2VQYXRoPSUyRlVzZXJzJTJGcnN0aWxsdyUyRkRvY3VtZW50cyUyRnRjZy12YXVsdCUyRm5vZGVfbW9kdWxlcyUyRm5leHQlMkZkaXN0JTJGcGFnZXMlMkZfZXJyb3IuanMmcGFnZT0lMkZfZXJyb3IhIiwibWFwcGluZ3MiOiI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLG1CQUFPLENBQUMsOEdBQTBDO0FBQ2pFO0FBQ0E7QUFDQSxPQUFPLElBQVU7QUFDakIsTUFBTSxVQUFVO0FBQ2hCO0FBQ0EsT0FBTztBQUNQO0FBQ0EiLCJzb3VyY2VzIjpbIiJdLCJzb3VyY2VzQ29udGVudCI6WyJcbiAgICAod2luZG93Ll9fTkVYVF9QID0gd2luZG93Ll9fTkVYVF9QIHx8IFtdKS5wdXNoKFtcbiAgICAgIFwiL19lcnJvclwiLFxuICAgICAgZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gcmVxdWlyZShcIi4vbm9kZV9tb2R1bGVzL25leHQvZGlzdC9wYWdlcy9fZXJyb3IuanNcIik7XG4gICAgICB9XG4gICAgXSk7XG4gICAgaWYobW9kdWxlLmhvdCkge1xuICAgICAgbW9kdWxlLmhvdC5kaXNwb3NlKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgd2luZG93Ll9fTkVYVF9QLnB1c2goW1wiL19lcnJvclwiXSlcbiAgICAgIH0pO1xuICAgIH1cbiAgIl0sIm5hbWVzIjpbXSwiaWdub3JlTGlzdCI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///(pages-dir-browser)/./node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?absolutePagePath=%2FUsers%2Frstillw%2FDocuments%2Ftcg-vault%2Fnode_modules%2Fnext%2Fdist%2Fpages%2F_error.js&page=%2F_error!\n"));
/***/ })
},
/******/ __webpack_require__ => { // webpackRuntimeModules
/******/ var __webpack_exec__ = (moduleId) => (__webpack_require__(__webpack_require__.s = moduleId))
/******/ __webpack_require__.O(0, ["main"], () => (__webpack_exec__("(pages-dir-browser)/./node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?absolutePagePath=%2FUsers%2Frstillw%2FDocuments%2Ftcg-vault%2Fnode_modules%2Fnext%2Fdist%2Fpages%2F_error.js&page=%2F_error!")));
/******/ var __webpack_exports__ = __webpack_require__.O();
/******/ _N_E = __webpack_exports__;
/******/ }
]);

1562
.next/static/chunks/main.js Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,28 @@
/*
* ATTENTION: An "eval-source-map" devtool has been used.
* This devtool is neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/
(self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([["pages/_error"],{
/***/ "(pages-dir-browser)/./node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?absolutePagePath=private-next-pages%2F_error&page=%2F_error!":
/*!***********************************************************************************************************************************************!*\
!*** ./node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?absolutePagePath=private-next-pages%2F_error&page=%2F_error! ***!
\***********************************************************************************************************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
eval(__webpack_require__.ts("\n (window.__NEXT_P = window.__NEXT_P || []).push([\n \"/_error\",\n function () {\n return __webpack_require__(/*! private-next-pages/_error */ \"(pages-dir-browser)/./node_modules/next/dist/pages/_error.js\");\n }\n ]);\n if(true) {\n module.hot.dispose(function () {\n window.__NEXT_P.push([\"/_error\"])\n });\n }\n //# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKHBhZ2VzLWRpci1icm93c2VyKS8uL25vZGVfbW9kdWxlcy9uZXh0L2Rpc3QvYnVpbGQvd2VicGFjay9sb2FkZXJzL25leHQtY2xpZW50LXBhZ2VzLWxvYWRlci5qcz9hYnNvbHV0ZVBhZ2VQYXRoPXByaXZhdGUtbmV4dC1wYWdlcyUyRl9lcnJvciZwYWdlPSUyRl9lcnJvciEiLCJtYXBwaW5ncyI6IjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsbUJBQU8sQ0FBQywrRkFBMkI7QUFDbEQ7QUFDQTtBQUNBLE9BQU8sSUFBVTtBQUNqQixNQUFNLFVBQVU7QUFDaEI7QUFDQSxPQUFPO0FBQ1A7QUFDQSIsInNvdXJjZXMiOlsiIl0sInNvdXJjZXNDb250ZW50IjpbIlxuICAgICh3aW5kb3cuX19ORVhUX1AgPSB3aW5kb3cuX19ORVhUX1AgfHwgW10pLnB1c2goW1xuICAgICAgXCIvX2Vycm9yXCIsXG4gICAgICBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiByZXF1aXJlKFwicHJpdmF0ZS1uZXh0LXBhZ2VzL19lcnJvclwiKTtcbiAgICAgIH1cbiAgICBdKTtcbiAgICBpZihtb2R1bGUuaG90KSB7XG4gICAgICBtb2R1bGUuaG90LmRpc3Bvc2UoZnVuY3Rpb24gKCkge1xuICAgICAgICB3aW5kb3cuX19ORVhUX1AucHVzaChbXCIvX2Vycm9yXCJdKVxuICAgICAgfSk7XG4gICAgfVxuICAiXSwibmFtZXMiOltdLCJpZ25vcmVMaXN0IjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///(pages-dir-browser)/./node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?absolutePagePath=private-next-pages%2F_error&page=%2F_error!\n"));
/***/ })
},
/******/ __webpack_require__ => { // webpackRuntimeModules
/******/ var __webpack_exec__ = (moduleId) => (__webpack_require__(__webpack_require__.s = moduleId))
/******/ __webpack_require__.O(0, ["pages/_app","main"], () => (__webpack_exec__("(pages-dir-browser)/./node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?absolutePagePath=private-next-pages%2F_error&page=%2F_error!")));
/******/ var __webpack_exports__ = __webpack_require__.O();
/******/ _N_E = __webpack_exports__;
/******/ }
]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

62
.next/static/chunks/react-refresh.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
self.__BUILD_MANIFEST = (function(a){return {__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},__routerFilterStatic:a,__routerFilterDynamic:a,"/_error":["static\u002Fchunks\u002Fpages\u002F_error.js"],"/admin/card-import":["static\u002Fchunks\u002Fpages\u002Fadmin\u002Fcard-import.js"],"/cards":["static\u002Fchunks\u002Fpages\u002Fcards.js"],sortedPages:["\u002F_app","\u002F_error","\u002Fadmin\u002Fcard-import","\u002Fcards"]}}(void 0));self.__BUILD_MANIFEST_CB && self.__BUILD_MANIFEST_CB()

View file

@ -0,0 +1 @@
self.__SSG_MANIFEST=new Set;self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB()

View file

@ -0,0 +1 @@
{"c":["webpack"],"r":[],"m":[]}

View file

@ -0,0 +1 @@
{"c":["webpack"],"r":["/_error"],"m":["(pages-dir-browser)/./node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?absolutePagePath=%2FUsers%2Frstillw%2FDocuments%2Ftcg-vault%2Fnode_modules%2Fnext%2Fdist%2Fpages%2F_error.js&page=%2F_error!"]}

View file

@ -0,0 +1 @@
{"c":[],"r":[],"m":[]}

View file

@ -0,0 +1 @@
{"c":["webpack"],"r":[],"m":[]}

View file

@ -0,0 +1,12 @@
"use strict";
self["webpackHotUpdate_N_E"]("webpack",{},
/******/ function(__webpack_require__) { // webpackRuntimeModules
/******/ /* webpack/runtime/getFullHash */
/******/ (() => {
/******/ __webpack_require__.h = () => ("dc2d66e9190850cf")
/******/ })();
/******/
/******/ }
)
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJpZ25vcmVMaXN0IjpbMF0sIm1hcHBpbmdzIjoiQUFBQSIsInNvdXJjZXMiOlsid2VicGFjay1pbnRlcm5hbDovL25leHRqcy93ZWJwYWNrLmpzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIFRoaXMgc291cmNlIHdhcyBnZW5lcmF0ZWQgYnkgTmV4dC5qcyBiYXNlZCBvZmYgb2YgdGhlIGdlbmVyYXRlZCBXZWJwYWNrIHJ1bnRpbWUuXG4vLyBUaGUgbWFwcGluZ3MgYXJlIGluY29ycmVjdC5cbi8vIFRvIGdldCB0aGUgY29ycmVjdCBsaW5lL2NvbHVtbiBtYXBwaW5ncywgdHVybiBvZmYgc291cmNlbWFwcyBpbiB5b3VyIGRlYnVnZ2VyLlxuXG5zZWxmW1wid2VicGFja0hvdFVwZGF0ZV9OX0VcIl0oXCJ3ZWJwYWNrXCIse30sXG4vKioqKioqLyBmdW5jdGlvbihfX3dlYnBhY2tfcmVxdWlyZV9fKSB7IC8vIHdlYnBhY2tSdW50aW1lTW9kdWxlc1xuLyoqKioqKi8gLyogd2VicGFjay9ydW50aW1lL2dldEZ1bGxIYXNoICovXG4vKioqKioqLyAoKCkgPT4ge1xuLyoqKioqKi8gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmggPSAoKSA9PiAoXCJkYzJkNjZlOTE5MDg1MGNmXCIpXG4vKioqKioqLyB9KSgpO1xuLyoqKioqKi8gXG4vKioqKioqLyB9XG4pIl19
;

View file

@ -0,0 +1,12 @@
"use strict";
self["webpackHotUpdate_N_E"]("webpack",{},
/******/ function(__webpack_require__) { // webpackRuntimeModules
/******/ /* webpack/runtime/getFullHash */
/******/ (() => {
/******/ __webpack_require__.h = () => ("f07f85cab969fc85")
/******/ })();
/******/
/******/ }
)
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJpZ25vcmVMaXN0IjpbMF0sIm1hcHBpbmdzIjoiQUFBQSIsInNvdXJjZXMiOlsid2VicGFjay1pbnRlcm5hbDovL25leHRqcy93ZWJwYWNrLmpzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIFRoaXMgc291cmNlIHdhcyBnZW5lcmF0ZWQgYnkgTmV4dC5qcyBiYXNlZCBvZmYgb2YgdGhlIGdlbmVyYXRlZCBXZWJwYWNrIHJ1bnRpbWUuXG4vLyBUaGUgbWFwcGluZ3MgYXJlIGluY29ycmVjdC5cbi8vIFRvIGdldCB0aGUgY29ycmVjdCBsaW5lL2NvbHVtbiBtYXBwaW5ncywgdHVybiBvZmYgc291cmNlbWFwcyBpbiB5b3VyIGRlYnVnZ2VyLlxuXG5zZWxmW1wid2VicGFja0hvdFVwZGF0ZV9OX0VcIl0oXCJ3ZWJwYWNrXCIse30sXG4vKioqKioqLyBmdW5jdGlvbihfX3dlYnBhY2tfcmVxdWlyZV9fKSB7IC8vIHdlYnBhY2tSdW50aW1lTW9kdWxlc1xuLyoqKioqKi8gLyogd2VicGFjay9ydW50aW1lL2dldEZ1bGxIYXNoICovXG4vKioqKioqLyAoKCkgPT4ge1xuLyoqKioqKi8gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmggPSAoKSA9PiAoXCJmMDdmODVjYWI5NjlmYzg1XCIpXG4vKioqKioqLyB9KSgpO1xuLyoqKioqKi8gXG4vKioqKioqLyB9XG4pIl19
;

View file

@ -0,0 +1,12 @@
"use strict";
self["webpackHotUpdate_N_E"]("webpack",{},
/******/ function(__webpack_require__) { // webpackRuntimeModules
/******/ /* webpack/runtime/getFullHash */
/******/ (() => {
/******/ __webpack_require__.h = () => ("1a81ca931ae87a2d")
/******/ })();
/******/
/******/ }
)
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJpZ25vcmVMaXN0IjpbMF0sIm1hcHBpbmdzIjoiQUFBQSIsInNvdXJjZXMiOlsid2VicGFjay1pbnRlcm5hbDovL25leHRqcy93ZWJwYWNrLmpzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIFRoaXMgc291cmNlIHdhcyBnZW5lcmF0ZWQgYnkgTmV4dC5qcyBiYXNlZCBvZmYgb2YgdGhlIGdlbmVyYXRlZCBXZWJwYWNrIHJ1bnRpbWUuXG4vLyBUaGUgbWFwcGluZ3MgYXJlIGluY29ycmVjdC5cbi8vIFRvIGdldCB0aGUgY29ycmVjdCBsaW5lL2NvbHVtbiBtYXBwaW5ncywgdHVybiBvZmYgc291cmNlbWFwcyBpbiB5b3VyIGRlYnVnZ2VyLlxuXG5zZWxmW1wid2VicGFja0hvdFVwZGF0ZV9OX0VcIl0oXCJ3ZWJwYWNrXCIse30sXG4vKioqKioqLyBmdW5jdGlvbihfX3dlYnBhY2tfcmVxdWlyZV9fKSB7IC8vIHdlYnBhY2tSdW50aW1lTW9kdWxlc1xuLyoqKioqKi8gLyogd2VicGFjay9ydW50aW1lL2dldEZ1bGxIYXNoICovXG4vKioqKioqLyAoKCkgPT4ge1xuLyoqKioqKi8gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmggPSAoKSA9PiAoXCIxYTgxY2E5MzFhZTg3YTJkXCIpXG4vKioqKioqLyB9KSgpO1xuLyoqKioqKi8gXG4vKioqKioqLyB9XG4pIl19
;

12
.next/trace Normal file

File diff suppressed because one or more lines are too long

View file

@ -1,167 +0,0 @@
# 🎉 All-Vercel TCG Vault Setup Complete!
## ✅ What We've Built
Your TCG Vault is now **completely self-contained on Vercel Pro** with no external dependencies!
### **🏗️ Architecture:**
- **Frontend**: React app with OCR scanner and visual effects
- **Backend**: Vercel Functions (TypeScript) replacing FastAPI
- **Database**: JSON file with your card data (12 cards exported)
- **Deployment**: Single Vercel project
### **📁 File Structure:**
```
frontend/
├── api/ # Vercel Functions (Backend)
│ ├── health.ts # Health check endpoint
│ └── v1/cards/
│ ├── index.ts # GET /api/v1/cards/ (with search, filters)
│ └── [id].ts # GET /api/v1/cards/:id
├── src/
│ ├── data/cards.json # Card database (exported from SQLite)
│ ├── config/api.ts # Updated for local API routes
│ └── ... (all your React components)
├── vercel.json # Vercel configuration
└── deploy-vercel-all.sh # Deployment script
```
---
## 🚀 **Deployment Process**
### **1. Push to GitHub:**
```bash
cd frontend
git init
git add .
git commit -m "TCG Vault - All Vercel Setup"
git branch -M main
# Create new GitHub repo and push
git remote add origin YOUR_GITHUB_REPO_URL
git push -u origin main
```
### **2. Deploy to Vercel Pro:**
1. Go to [vercel.com/dashboard](https://vercel.com/dashboard)
2. **"Import Project"** → Choose your GitHub repo
3. **Framework**: React (auto-detected)
4. **Root Directory**: Leave blank (uses frontend as root)
5. **Build Settings**: Auto-detected
6. **Deploy!**
### **3. Done!**
Your TCG Vault will be live at `https://your-app.vercel.app`
---
## 🎯 **What Works:**
### **✅ All Current Features:**
- 📸 **Camera OCR scanning** with Tesseract.js
- 🎨 **Beautiful visual effects** (glowing cards, animations)
- 🃏 **Card database** (12 cards from your SQLite export)
- 📱 **Mobile responsive** design
- 🔍 **Search and filtering**
- 🌟 **Card matching** for OCR results
### **✅ API Endpoints:**
- `GET /api/v1/cards/` - List cards with search/filters
- `GET /api/v1/cards/:id` - Get specific card
- `GET /api/health` - Health check
---
## 💰 **Cost Analysis:**
### **With Vercel Pro:**
- **Your existing Vercel Pro**: $20/month (already paying)
- **Additional cost**: $0/month 🎉
- **Included with Pro**:
- 10M requests/month
- 1TB data transfer
- Serverless functions
- Global CDN
- Advanced monitoring
### **vs. Alternatives:**
- Railway: $5/month minimum + Vercel Pro
- Render + Vercel Pro: Still need two platforms
- **All-Vercel: Simplest and most cost-effective!**
---
## 🔥 **Benefits of All-Vercel Setup:**
### **🎯 Simplicity:**
- **One codebase** - Everything in one repository
- **One platform** - Vercel handles everything
- **One deployment** - Push code, auto-deploy
- **One dashboard** - Monitor everything in Vercel
### **⚡ Performance:**
- **Edge functions** - API runs globally close to users
- **Static files** - Frontend cached at 40+ edge locations
- **Fast cold starts** - Vercel Functions optimized for speed
- **Integrated CDN** - Everything accelerated
### **🛡️ Enterprise Features:**
- **Advanced WAF** - DDoS protection, bot management
- **Observability** - Built-in monitoring and analytics
- **Security headers** - Automatically configured
- **SSL certificates** - Managed automatically
---
## 🛠️ **Development Workflow:**
### **Local Development:**
```bash
npm start # React app runs on http://localhost:3000
# API functions available at http://localhost:3000/api/*
```
### **Production Deployment:**
1. **Push to GitHub** - Automatic deployment triggered
2. **Preview deployments** - Every branch gets preview URL
3. **Instant rollbacks** - One-click revert if needed
---
## 📊 **Monitoring & Analytics:**
### **Built-in with Vercel Pro:**
- **Real-time analytics** - Track page views, performance
- **Function logs** - Debug API issues
- **Performance insights** - Core Web Vitals monitoring
- **Error tracking** - Automatic error reporting
---
## 🎉 **Next Steps:**
### **Immediate:**
1. **Deploy to Vercel** using the process above
2. **Test all features** in production
3. **Set up custom domain** (optional)
### **Future Enhancements:**
1. **Add more cards** - Update `src/data/cards.json`
2. **User authentication** - Add Vercel KV for user data
3. **Live pricing** - Integrate pricing APIs
4. **Advanced features** - Collections, decks, etc.
---
## 🎯 **Expected Results:**
After deployment, you'll have:
- ⚡ **Blazing fast worldwide** - 40+ edge locations
- 📱 **Perfect mobile OCR** - Camera scanning works flawlessly
- 🛡️ **Enterprise security** - WAF protection, DDoS mitigation
- 📊 **Professional monitoring** - Built-in observability
- 🔄 **Automatic deployments** - Push to Git, instantly live
- ✨ **All visual effects** - Enhanced with edge optimization
- 🌍 **Global scalability** - Handles any traffic automatically
**Your TCG Vault is now professional-grade and costs $0 extra!** 🚀

View file

@ -1,251 +0,0 @@
# Card Data Sources Guide
This guide explains how to build out your card database using external APIs and data sources.
## 🎯 **Recommended Data Sources**
### **1. Scryfall API (Magic: The Gathering)**
**Best for MTG cards**
- **URL**: https://api.scryfall.com
- **Free**: No API key required
- **Rate Limit**: 10 requests/second
- **Coverage**: All MTG cards with images, prices, rulings
**Example Usage**:
```javascript
// Search for a card
const response = await fetch('https://api.scryfall.com/cards/named?fuzzy=lightning+bolt');
const card = await response.json();
// Search multiple cards
const searchResponse = await fetch('https://api.scryfall.com/cards/search?q=game:paper+type:creature');
const cards = await searchResponse.json();
```
### **2. Pokémon TCG API**
**Best for Pokémon cards**
- **URL**: https://api.pokemontcg.io/v2
- **Free**: No authentication required
- **Rate Limit**: Generous limits
- **Coverage**: All Pokémon cards with images
**Example Usage**:
```javascript
// Search for a card
const response = await fetch('https://api.pokemontcg.io/v2/cards?q=name:pikachu');
const cards = await response.json();
```
### **3. Yu-Gi-Oh! API**
**Best for Yu-Gi-Oh! cards**
- **URL**: https://db.ygoprodeck.com/api/v7
- **Free**: Open source API
- **Coverage**: All Yu-Gi-Oh! cards
**Example Usage**:
```javascript
// Search for a card
const response = await fetch('https://db.ygoprodeck.com/api/v7/cardinfo.php?fname=Blue-Eyes%20White%20Dragon');
const cards = await response.json();
```
### **4. Disney Lorcana (Lorcast API)**
**Best for Lorcana cards**
- **URL**: https://api.lorcast.com/v0
- **Free**: No API key required
- **Rate Limit**: 10 requests/second (50-100ms delay recommended)
- **Coverage**: All Lorcana cards with images and pricing
- **Status**: Beta API (v0) - production safe
**Example Usage**:
```javascript
// Search for a card
const response = await fetch('https://api.lorcast.com/v0/cards?q=name:Mickey%20Mouse');
const data = await response.json();
const cards = data.cards;
```
## 🚀 **Implementation Strategy**
### **Phase 1: Core Integration**
1. **Set up rate limiting** for each API
2. **Create unified search interface** that queries all sources
3. **Implement caching** to avoid repeated requests
4. **Add error handling** for API failures
### **Phase 2: Database Population**
1. **Fetch popular cards** from each game
2. **Store in local database** with proper metadata
3. **Update pricing** regularly
4. **Add image caching** for better performance
### **Phase 3: Advanced Features**
1. **Real-time pricing** from multiple sources
2. **Set completion tracking**
3. **Market trend analysis**
4. **Deck building suggestions**
## 📊 **Data Mapping**
### **Universal Fields**
| Field | Description | Source |
|-------|-------------|--------|
| `name` | Card name | All APIs |
| `game` | Game identifier | All APIs |
| `set_name` | Set/expansion name | All APIs |
| `set_code` | Set abbreviation | All APIs |
| `card_number` | Collector number | All APIs |
| `rarity` | Rarity level | All APIs |
| `image_url` | Card image URL | All APIs |
| `current_price` | Market price | MTG, Pokémon |
### **Game-Specific Fields**
#### **Magic: The Gathering**
- `mana_cost`: Mana symbols `{W}{U}{B}{R}{G}{C}`
- `cmc`: Converted mana cost
- `card_type`: Full type line
- `colors`: Color identity
- `oracle_text`: Rules text
- `power`/`toughness`: Creature stats
#### **Pokémon**
- `mana_cost`: Energy requirements
- `cmc`: Total energy cost
- `card_type`: Card type + stage
- `colors`: Energy types
- `power`: HP value
- `oracle_text`: Effect text
#### **Yu-Gi-Oh!**
- `mana_cost`: Level/rank
- `cmc`: Level value
- `card_type`: Card type
- `colors`: Attribute
- `oracle_text`: Effect text
- `power`/`toughness`: ATK/DEF
#### **Disney Lorcana**
- `mana_cost`: Ink cost
- `cmc`: Ink cost value
- `card_type`: Card type
- `colors`: Ink colors
- `oracle_text`: Card text
- `power`/`toughness`: Strength/Willpower
## 🛠️ **Usage Examples**
### **Search Cards from External APIs**
```javascript
import cardDataService from '../services/cardDataSources';
// Search across all games
const cards = await cardDataService.searchCards('dragon');
// Search specific game
const mtgCards = await cardDataService.searchCards('lightning', 'MTG');
```
### **Add Cards to Database**
```javascript
// Fetch card from external API
const card = await mtgService.getCardByName('Lightning Bolt');
// Add to local database
const result = await databaseAPI.addCard(card);
```
### **Populate Database with Popular Cards**
```bash
# Run the population script
node scripts/populate-card-database.js
```
## 📈 **Performance Considerations**
### **Rate Limiting**
- **Scryfall**: 10 requests/second
- **Pokémon API**: 5 requests/second
- **Yu-Gi-Oh! API**: No strict limits
- **Lorcast (Lorcana)**: 10 requests/second (50-100ms delay)
### **Caching Strategy**
- **Search results**: Cache for 5 minutes
- **Card details**: Cache for 1 hour
- **Images**: Cache indefinitely
- **Pricing**: Update every 24 hours
### **Error Handling**
- **API failures**: Retry with exponential backoff
- **Rate limits**: Implement proper queuing
- **Network issues**: Graceful degradation
## 🔧 **Setup Instructions**
### **1. Install Dependencies**
```bash
npm install node-fetch
```
### **2. Set Environment Variables**
```bash
# .env
REACT_APP_API_URL=http://localhost:8000
TCG_VAULT_TOKEN=your_auth_token_here
```
### **3. Run Database Population**
```bash
# Populate with popular cards
node scripts/populate-card-database.js
# Or use the web interface
# Navigate to Cards page → "Browse Database" button
```
### **4. Test the Integration**
```javascript
// Test external API search
const cards = await cardDataService.searchCards('pikachu', 'POKEMON');
console.log('Found cards:', cards.length);
// Test database addition
const card = await mtgService.getCardByName('Lightning Bolt');
if (card) {
await databaseAPI.addCard(card);
console.log('Card added to database');
}
```
## 🎯 **Next Steps**
### **Immediate Actions**
1. **Test the APIs** with the provided services
2. **Populate your database** with popular cards
3. **Integrate the browser component** into your app
4. **Set up regular updates** for pricing data
### **Future Enhancements**
1. **Add more games** (Lorcana, Flesh and Blood, etc.)
2. **Implement price tracking** with alerts
3. **Add set completion tracking**
4. **Create deck building suggestions**
5. **Add market analysis tools**
## 📚 **Additional Resources**
- **Scryfall API Docs**: https://scryfall.com/docs/api
- **Pokémon TCG API**: https://dev.pokemontcg.io/
- **Yu-Gi-Oh! API**: https://ygoprodeck.com/api-guide/
- **Lorcast API**: https://lorcast.com/docs/api
- **TCGPlayer API**: https://docs.tcgplayer.com/
## 🚨 **Important Notes**
1. **Respect rate limits** - Implement proper throttling
2. **Cache responses** - Avoid unnecessary API calls
3. **Handle errors gracefully** - APIs can be unreliable
4. **Update pricing regularly** - Card values change frequently
5. **Verify card data** - Cross-reference with official sources
This implementation provides a solid foundation for building a comprehensive card database that can grow with your application's needs!

View file

@ -1,188 +0,0 @@
# 🚀 TCG Vault Deployment Guide
## 🏆 **OPTION 1: Vercel Pro + Railway - BEST CHOICE**
### ✅ **Perfect for You (Already Have Vercel Pro!):**
- **Frontend** → Your existing Vercel Pro account ($20/month already paying)
- **Backend** → Railway cloud service (free tier)
- **Total additional cost: $0/month** 🎉
- **Enterprise-grade performance** that crushes shared hosting
### **🔥 Why Vercel Pro Is Superior:**
- **10M edge requests/month** included (10x more than Hobby)
- **1TB data transfer/month** (vs 100GB DreamHost shared)
- **Global CDN with 40+ locations** (instant worldwide loading)
- **4-CPU build machines** (2x faster builds than Hobby)
- **Advanced WAF protection** (enterprise security)
- **Observability & monitoring** (performance insights)
- **Zero-downtime deployments** (professional reliability)
---
## 🚀 **Step 1: Deploy Backend to Railway (5 minutes)**
### 1. **Create Railway Account**
- Visit [railway.app](https://railway.app)
- Sign up with GitHub (free)
### 2. **Push Backend to GitHub**
```bash
# In your tcg-vault directory
cd backend
git init
git add .
git commit -m "TCG Vault backend for deployment"
git branch -M main
# Create a new GitHub repo and push
git remote add origin YOUR_GITHUB_REPO_URL
git push -u origin main
```
### 3. **Deploy to Railway**
1. In Railway dashboard: **"New Project"**
2. **"Deploy from GitHub repo"**
3. Select your backend repository
4. Railway auto-detects Python and uses our `railway.toml` config
5. **Deployment starts automatically!**
### 4. **Set Environment Variables (Important!)**
In Railway dashboard, add environment variable:
```
ALLOWED_ORIGINS=https://your-vercel-domain.vercel.app
```
### 5. **Get Your API URL**
- Copy your Railway app URL (e.g., `https://tcg-vault-backend-production-xyz.up.railway.app`)
---
## 🌟 **Step 2: Deploy Frontend to Vercel Pro (3 minutes)**
### 1. **Connect GitHub to Vercel**
```bash
# In your tcg-vault directory
cd frontend
git init
git add .
git commit -m "TCG Vault frontend for Vercel"
git branch -M main
# Create GitHub repo for frontend
git remote add origin YOUR_FRONTEND_GITHUB_REPO_URL
git push -u origin main
```
### 2. **Deploy to Vercel**
1. Go to [vercel.com/dashboard](https://vercel.com/dashboard)
2. **"Import Project"** → Choose your frontend GitHub repo
3. **Framework**: React (auto-detected)
4. **Build Settings**: Use defaults
5. **Environment Variables** → Add:
```
REACT_APP_API_URL=https://your-railway-backend-url.up.railway.app/api/v1
```
6. **Deploy!**
### 3. **Custom Domain (Optional)**
- Use your existing domain or get a new one
- Vercel Pro includes SSL certificates automatically
---
## 🎯 **Alternative Options** (If you want to compare)
### **Option 2: DreamHost (Frontend) + Railway (Backend)**
- **Cost**: $0/month (uses existing DreamHost)
- **Performance**: Good, but not as fast as Vercel Pro
- **Setup**: Manual file uploads vs automatic Git deployments
### **Option 3: DreamHost VPS ($12/month)**
- **Full Python support** - Deploy everything together
- **More expensive** than using your existing Vercel Pro
### **Option 4: All Railway**
- **Frontend + Backend** both on Railway
- **Cost**: ~$5-10/month for frontend hosting
---
## 📋 **Quick Deployment Checklist**
### ✅ Backend (Railway):
- [ ] Push backend code to GitHub
- [ ] Connect Railway to repository
- [ ] Set ALLOWED_ORIGINS environment variable
- [ ] Verify deployment success
- [ ] Copy API URL
### ✅ Frontend (Vercel Pro):
- [ ] Push frontend code to GitHub
- [ ] Import project in Vercel dashboard
- [ ] Set REACT_APP_API_URL environment variable
- [ ] Deploy and verify
- [ ] Optional: Set up custom domain
---
## 🛠️ **Troubleshooting**
### **Common Issues:**
**1. CORS Errors**
- Ensure ALLOWED_ORIGINS in Railway includes your Vercel domain
**2. API Not Found**
- Double-check REACT_APP_API_URL in Vercel environment variables
- Ensure Railway backend is running (check Railway logs)
**3. Build Failures**
- Check Vercel build logs in dashboard
- Verify all dependencies are in package.json
**4. OCR Not Working**
- OCR runs client-side with Vercel's edge computing - should work great!
- Check browser console for any errors
---
## 🎯 **Expected Results with Vercel Pro**
After deployment, you'll have **enterprise-grade hosting**:
- ⚡ **Blazing fast worldwide** - 40+ edge locations
- 📱 **Perfect mobile performance** - OCR scanning works flawlessly
- 🛡️ **Advanced security** - WAF protection included
- 📊 **Performance monitoring** - Built-in observability tools
- 🔄 **Automatic deployments** - Push to Git, instantly live
- ✨ **All visual effects** - Enhanced with edge optimization
- 🌍 **Global scalability** - Handles traffic spikes automatically
---
## 💡 **Pro Tips for Vercel Pro Users**
### **Performance Optimization:**
- Your **1TB transfer limit** easily handles high-traffic
- **Cold start prevention** keeps your app instantly responsive
- **Advanced caching** speeds up repeat visits
### **Development Workflow:**
- **Preview deployments** for every Git branch
- **Automatic PR previews** for testing features
- **Instant rollbacks** if anything goes wrong
### **Monitoring:**
- Use **Observability tools** to track performance
- **Web Analytics** to see user behavior
- **Speed Insights** to optimize further
---
## 🎉 **Your TCG Vault Will Be Professional-Grade!**
With Vercel Pro + Railway, you get:
- **Netflix-level performance** for your card scanner
- **$0 additional cost** (using existing Vercel Pro)
- **Enterprise security** and reliability
- **Automatic scaling** to handle any traffic
- **Professional deployment pipeline**
**Ready to deploy to your Vercel Pro account?** This will be significantly better than any shared hosting option! 🚀

View file

@ -1,113 +0,0 @@
# Dual View System & Image Handling
## 🎨 **View Modes**
TCG Vault now supports two distinct viewing modes for your card collection:
### 🃏 **Card View**
- **Image-focused** display showing card artwork prominently
- **Responsive grid** that adapts from 1 column (mobile) to 5 columns (ultra-wide)
- **Large card images** with automatic fallbacks to game-themed placeholders
- **Clean, minimal information** focusing on visual identification
### 📊 **Table View**
- **Data-focused** tabular display for detailed card information
- **Small thumbnail** images alongside comprehensive card data
- **Sortable columns** for quick data analysis
- **Compact format** ideal for managing large collections
## 🖼️ **Dual Image System**
### Stock Images (Official Reference)
- **Purpose**: Clean, official card images for consistent presentation
- **Usage**: Primary display in both view modes
- **Features**:
- High-quality scans from official sources
- Artwork cropping coordinates for thumbnails
- Consistent lighting and framing
### User Card Photos
- **Purpose**: Photos of your actual physical cards
- **Usage**: Quality assessment and condition documentation
- **Features**:
- Multiple photos per card copy
- Condition-specific documentation
- Quality comparison with stock images
## 🔄 **Image Display Features**
### Smart Fallbacks
When card images aren't available, the system displays:
- **Game-themed gradients** (Orange for MTG, Yellow for Pokemon, Purple for Lorcana)
- **Card name** abbreviated for readability
- **Game identifier** for quick recognition
- **Consistent sizing** maintaining layout integrity
### Interactive Controls
- **📸/📋 Toggle**: Switch between stock and user photos
- **◄/► Navigation**: Browse multiple user photos
- **👤/✓ Indicators**: Visual cues for image type
- **Photo counters**: Show current photo index (e.g., "2/3")
## 📁 **Image Storage Structure**
```
frontend/public/images/cards/
├── mtg/ # Magic: The Gathering
│ ├── lightning-bolt-alpha.jpg
│ └── black-lotus-alpha.jpg
├── pokemon/ # Pokémon
│ └── pikachu-base-set.jpg
└── lorcana/ # Disney Lorcana
├── mickey-brave-tailor-tfc.jpg
├── elsa-snow-queen-tfc.jpg
├── be-prepared-tfc.jpg
└── mickey-steamboat-pilot-tfc.jpg
```
## 🛠️ **Database Schema**
### Cards Table (New Fields)
- `stock_image_url`: Official card image path
- `artwork_crop_coords`: JSON with cropping coordinates `{x, y, width, height}`
- `image_url`: Legacy field for backward compatibility
### Collection Cards Table (New Fields)
- `user_images`: JSON array of user photo paths
- `condition_notes`: Detailed condition descriptions
## 🎯 **Usage Examples**
### Card Identification
- **Card View**: Visual browsing and identification
- **Stock Images**: Official reference for card verification
- **Game badges**: Quick game identification
### Collection Management
- **Table View**: Data analysis and bulk operations
- **User Photos**: Document card conditions and variations
- **Pricing**: Track market values alongside visual condition
### Quality Assessment
- **Side-by-side comparison**: Stock image vs. your card photos
- **Multiple angles**: Document different aspects of card condition
- **Condition notes**: Detailed written condition descriptions
## 🚀 **Future Enhancements**
### Image Processing
- **Automatic cropping**: Extract artwork from card images
- **Quality scoring**: AI-based condition assessment
- **OCR integration**: Extract text from user photos
### Advanced Views
- **Gallery mode**: Large image browsing
- **Comparison mode**: Side-by-side stock vs. user photos
- **3D card view**: Interactive card rotation
### Collection Features
- **Image upload**: Drag-and-drop card photo upload
- **Batch processing**: Upload multiple card photos at once
- **Cloud storage**: Backup and sync card photos across devices
This dual-view system provides the foundation for professional-grade collection management while maintaining ease of use for casual collectors.

View file

@ -1,95 +0,0 @@
# Game-Specific Features Guide
## Supported Trading Card Games
### Magic: The Gathering (MTG)
**Game Code**: `MTG`
**Key Features**:
- Mana costs with colored symbols `{W}{U}{B}{R}{G}{C}`
- Converted Mana Cost (CMC)
- Card types: Creature, Instant, Sorcery, Artifact, Enchantment, Planeswalker, Land
- Power/Toughness for creatures
- Loyalty for planeswalkers
- Colors: White, Blue, Black, Red, Green, Colorless
- Rarities: Common, Uncommon, Rare, Mythic Rare
**Sample Cards Added**:
- Lightning Bolt (Red Instant)
- Black Lotus (Artifact)
### Pokémon
**Game Code**: `POKEMON`
**Key Features**:
- Energy costs (Fighting, Fire, Water, Lightning, Psychic, Grass, Darkness, Metal, Fairy, Colorless)
- HP for Pokémon
- Attack damage
- Weakness/Resistance
- Card types: Pokémon, Trainer, Energy
- Pokémon stages: Basic, Stage 1, Stage 2, EX, GX, V, VMAX
- Rarities: Common, Uncommon, Rare, Ultra Rare, Secret Rare
**Sample Cards Added**:
- Pikachu (Basic Lightning Pokémon)
### Disney Lorcana
**Game Code**: `LORCANA`
**Key Features**:
- Ink costs (single number)
- Characters have Strength and Willpower
- Card types: Character, Action, Item, Location
- Character classifications: Storyborn, Dreamborn, Floodborn
- Ink colors: Amber, Amethyst, Emerald, Ruby, Sapphire, Steel
- Abilities: Evasive, Ward, Bodyguard, Challenger, Rush, Shift, Support
- Songs can be sung by characters
- Rarities: Common, Uncommon, Rare, Super Rare, Legendary, Enchanted
**Sample Cards Added**:
- Mickey Mouse - Brave Little Tailor (Legendary Amber Character)
- Elsa - Snow Queen (Super Rare Sapphire Character)
- Be Prepared (Rare Emerald Action/Song)
- Mickey Mouse - Steamboat Pilot (Common Amber Character)
## Database Field Mapping
### Universal Fields
- `name`: Card name
- `game`: Game code (MTG/POKEMON/LORCANA)
- `set_name`: Set/expansion name
- `set_code`: Set abbreviation
- `card_number`: Collector number
- `rarity`: Rarity level
- `current_price`: Market price
- `image_url`: Card image URL
### Game-Specific Field Usage
| Field | MTG | Pokemon | Lorcana |
|-------|-----|---------|---------|
| `mana_cost` | Mana symbols | Energy requirements | Ink cost |
| `cmc` | Converted mana cost | Total energy cost | Ink cost |
| `card_type` | Full type line | Card type + stage | Character classification |
| `colors` | Color identity | Energy types | Ink colors |
| `power` | Creature power | Attack damage | Character strength |
| `toughness` | Creature toughness | HP | Character willpower |
| `loyalty` | Planeswalker loyalty | - | - |
| `oracle_text` | Rules text | Effect text | Ability text |
## Future Implementation Ideas
### OCR Recognition Patterns
- **MTG**: Recognize mana symbols, card frames, set symbols
- **Pokemon**: Identify energy symbols, HP values, stage indicators
- **Lorcana**: Detect ink costs, character stats, Disney artwork style
### Deck Building Rules
- **MTG**: 60-card minimum, 4-of limit, format restrictions
- **Pokemon**: 60-card decks, prize cards, energy requirements
- **Lorcana**: 60-card decks, ink system, character limits
### Pricing Sources
- **MTG**: TCGPlayer, MTG Goldfish, EDHREC
- **Pokemon**: TCGPlayer, PTCGO prices, PokeBeach
- **Lorcana**: TCGPlayer, eBay sold listings (newer game)

View file

@ -1,191 +0,0 @@
# Gradient Border System with Mouse-Tracking Glow
## 🌈 **Overview**
TCG Vault now features stunning gradient borders that replace the old solid borders with dynamic, multi-colored gradients that respond to mouse movement with localized glow effects.
---
## ✨ **Gradient Border Features**
### **Multi-Layer Gradient Design**
- **Dual-background technique**: Uses CSS `padding-box` and `border-box` to create clean content areas with gradient borders
- **Progressive intensity**: Higher rarity cards get more complex, multi-stop gradients
- **Color harmony**: Each rarity uses a carefully crafted color palette that transitions smoothly
### **Rarity-Specific Gradients**
| Rarity | Gradient Colors | Effect Intensity |
|--------|----------------|------------------|
| **Common** | Gray (`#6B7280` → `#9CA3AF``#6B7280`) | Subtle 2-stop gradient |
| **Uncommon** | Green (`#22C55E` → `#4ADE80``#22C55E`) | Medium 2-stop gradient |
| **Rare** | Blue (`#3B82F6` → `#6366F1``#3B82F6`) | Bright 2-stop gradient |
| **Super Rare** | Purple (`#9333EA` → `#A855F7``#C4B5FD``#A855F7``#9333EA`) | Complex 5-stop gradient |
| **Legendary** | Gold (`#F59E0B` → `#FBBF24``#FEF08A``#FBBF24``#F59E0B`) | Intense 5-stop gradient |
| **Mythic** | Red (`#EF4444` → `#F87171``#FECACA``#F87171``#EF4444`) | Maximum 5-stop gradient |
---
## 🎯 **Mouse-Tracking Glow System**
### **Dynamic Glow Effect**
- **Real-time tracking**: Mouse position is tracked at 60fps with throttling for performance
- **Radial glow**: 150px radius circular glow that follows the cursor within card boundaries
- **Progressive opacity**: Glow fades from center to edges with multiple intensity stops
- **Blur enhancement**: 2px blur filter creates a soft, professional glow effect
### **Technical Implementation**
#### **Custom Hook: `useMouseGlow`**
```typescript
const { ref, glowStyles, isHovering } = useMouseGlow({
glowIntensity: 0.8, // Brightness of the glow (0-1)
glowRadius: 150, // Size of the glow circle in pixels
updateThrottle: 16 // Update frequency (~60fps)
});
```
#### **CSS Custom Properties**
```css
--glow-x: 50%; /* Horizontal glow position */
--glow-y: 50%; /* Vertical glow position */
--glow-intensity: 0.8; /* Glow brightness */
--rarity-shadow-color: rgba(...); /* Rarity-specific shadow color */
```
---
## 🎨 **Visual Enhancement Effects**
### **Hover Animations**
- **Scale transform**: Cards scale up 2-3% on hover based on rarity
- **Brightness filter**: Enhanced brightness (1.1× - 1.2×) for premium feel
- **Saturation boost**: Higher rarity cards get increased color saturation
- **Pulse animation**: Super Rare+ cards get a breathing glow effect
### **Performance Optimizations**
- **Hardware acceleration**: Uses `transform3d()` and `will-change`
- **Throttled updates**: Mouse tracking limited to 60fps
- **Event cleanup**: Proper cleanup on component unmount
- **CSS-only animations**: Smooth 60fps animations without JavaScript
---
## 🛠️ **Component Architecture**
### **GlowingCard Component**
```typescript
<GlowingCard rarity={card.rarity} className="card-container">
{/* Card content */}
</GlowingCard>
```
**Features:**
- Automatic rarity detection and intensity adjustment
- Built-in mouse tracking and glow effects
- Seamless integration with existing card components
- Responsive glow radius and intensity
### **Rarity-Specific Intensities**
- **Common**: 0.4 intensity - Subtle glow
- **Uncommon**: 0.5 intensity - Light glow
- **Rare**: 0.6 intensity - Medium glow
- **Super Rare**: 0.7 intensity - Strong glow
- **Legendary**: 0.8 intensity - Intense glow
- **Mythic**: 0.8 intensity - Maximum glow
---
## 💫 **Advanced Effects**
### **Pulse Animation for Premium Cards**
Super Rare, Legendary, and Mythic cards feature a continuous pulse animation:
- **Shadow expansion**: Box shadow grows and contracts rhythmically
- **2-second cycle**: Smooth, non-intrusive breathing effect
- **Rarity-specific colors**: Each rarity pulses with its signature color
- **Hover enhancement**: Pulse becomes more pronounced on hover
### **Multi-Layer Shadow System**
```css
box-shadow:
0 0 30px var(--rarity-shadow-color), /* Inner glow */
0 0 60px var(--rarity-shadow-color); /* Outer glow */
```
---
## 🎮 **Interactive Behavior**
### **Mouse Enter/Leave**
1. **Mouse Enter**: Glow effect activates and begins tracking cursor
2. **Mouse Move**: Glow position updates in real-time following cursor
3. **Mouse Leave**: Glow fades out and resets to center position
### **Smooth Transitions**
- **0.2s opacity transitions**: Glow fades in/out smoothly
- **0.3s transform transitions**: Hover scaling with easing
- **Continuous tracking**: No lag between mouse movement and glow position
---
## 📱 **Responsive Design**
### **Screen Size Adaptations**
- **Desktop**: Full 150px glow radius with maximum intensity
- **Tablet**: Scaled glow effects for touch interaction
- **Mobile**: Reduced complexity while maintaining visual appeal
### **Performance Considerations**
- **Reduced motion support**: Respects `prefers-reduced-motion` settings
- **Battery optimization**: Effects pause when not visible
- **GPU acceleration**: Smooth 60fps on all supported devices
---
## 🎯 **Integration Examples**
### **Card View Mode**
```typescript
// Large cards with prominent gradient borders and mouse tracking
<GlowingCard rarity="Legendary" className="card-large">
<CardImageDisplay card={card} size="large" />
{/* Card content */}
</GlowingCard>
```
### **Table View Mode**
```typescript
// Table rows with subtle left-border gradient accents
<tr style={{borderLeftColor: getRarityColor(card.rarity)}}>
{/* Table content */}
</tr>
```
---
## 🚀 **Future Enhancements**
### **Planned Features**
- **Gesture support**: Touch-based glow interactions for mobile
- **Particle effects**: Floating sparkles for Mythic+ cards
- **Color animation**: Shifting gradient hues over time
- **3D depth**: Layered glow effects with perspective
### **Performance Improvements**
- **WebGL acceleration**: GPU-based glow rendering
- **Intersection observer**: Only animate visible cards
- **Worker threads**: Offload calculations from main thread
---
## 🎨 **Design Philosophy**
**Visual Hierarchy**: Gradient intensity reflects card rarity and importance
**Performance First**: All effects maintain 60fps with hardware acceleration
**Accessibility Aware**: Respects motion preferences and maintains readability
**Progressive Enhancement**: Works gracefully across all device capabilities
This gradient border system elevates the visual experience while maintaining the clean, professional aesthetic that makes TCG Vault feel premium and modern! ✨🌈🎮

160
README.md
View file

@ -1,99 +1,121 @@
# TCG Vault - Trading Card Collection Manager
# TCG Vault
A comprehensive trading card database system with OCR scanning, AI-powered deck building, and real-time pricing.
A modern trading card game collection manager built with Next.js and Neon Database.
## Features
## 🚀 Features
🃏 **Complete Card Database**
- Store and organize your entire trading card collection
- Track card conditions, quantities, and locations
- Support for multiple TCG formats (Magic: The Gathering, Pokémon, Yu-Gi-Oh!, etc.)
- **Card Management**: Track your MTG, Pokémon, and Lorcana cards
- **Collection Organization**: Create and manage card collections
- **Deck Building**: Build and share decks
- **Authentication**: Secure user accounts with JWT
- **Admin Panel**: Manage cards and users
- **Real-time Pricing**: Track card values
📸 **OCR Card Scanning**
- Scan physical cards using your camera or smartphone
- Automatic card recognition and data extraction
- Bulk scanning support for efficient collection entry
## 🛠️ Tech Stack
🤖 **AI-Powered Features**
- Intelligent deck building recommendations based on your collection
- Natural language queries for searching your database
- Meta analysis and card synergy suggestions
- **Frontend**: Next.js 15, React 18, TypeScript
- **Backend**: Next.js API Routes
- **Database**: Neon PostgreSQL (serverless)
- **Authentication**: JWT with bcrypt
- **Styling**: Tailwind CSS
- **Deployment**: Vercel
💰 **Real-time Pricing**
- Live price tracking from multiple sources
- Collection valuation and price alerts
- Historical price charts and market trends
## 📦 Installation
🎨 **Modern Web Interface**
- Responsive design for desktop and mobile
- Drag-and-drop deck building
- Advanced filtering and search capabilities
## Tech Stack
- **Backend**: Python FastAPI with SQLAlchemy ORM
- **Database**: SQLite (production-ready, can scale to PostgreSQL)
- **Frontend**: React with TypeScript and Tailwind CSS
- **OCR**: OpenCV + Tesseract with cloud vision APIs
- **AI**: OpenAI GPT integration for intelligent features
- **Pricing**: TCGPlayer and MTGJSON API integration
## Quick Start
1. **Backend Setup**:
1. **Clone the repository**
```bash
cd backend
pip install -r requirements.txt
uvicorn main:app --reload
git clone <repository-url>
cd tcg-vault
```
2. **Frontend Setup**:
2. **Install dependencies**
```bash
cd frontend
npm install
npm start
```
3. **Database Initialize**:
3. **Set up environment variables**
```bash
python backend/init_db.py
cp .env.example .env.local
```
Update `.env.local` with your Neon database URL:
```env
POSTGRES_URL="postgresql://your-username:your-password@your-host/your-database"
JWT_SECRET="your-super-secret-jwt-key"
```
## Project Structure
4. **Set up the database**
```bash
npm run setup-db
```
5. **Start development server**
```bash
npm run dev
```
## 🗄️ Database Schema
The application uses the following tables:
- `users` - User accounts and authentication
- `cards` - Card information and metadata
- `user_cards` - User's card collections
- `collections` - Named card collections
- `collection_cards` - Cards in collections
- `decks` - Deck definitions
- `deck_cards` - Cards in decks
## 🔧 API Endpoints
### Authentication
- `POST /api/auth/register` - User registration
- `POST /api/auth/login` - User login
### Admin
- `GET /api/admin` - Admin panel data
### Health Check
- `GET /api/health` - Application health
- `GET /api/test-db` - Database connection test
## 🚀 Deployment
This app is configured for deployment on Vercel:
1. **Connect your repository** to Vercel
2. **Set environment variables** in Vercel dashboard
3. **Deploy automatically** on push to main branch
## 📁 Project Structure
```
tcg-vault/
├── backend/ # FastAPI backend
│ ├── app/
│ │ ├── models/ # SQLAlchemy models
│ │ ├── routers/ # API route handlers
│ │ ├── services/ # Business logic
│ │ └── utils/ # Utilities (OCR, AI, pricing)
│ ├── tests/ # Backend tests
│ └── requirements.txt
├── frontend/ # React frontend
│ ├── src/
│ │ ├── components/
│ │ ├── pages/
│ │ ├── services/ # API clients
│ │ └── utils/
│ └── package.json
├── docs/ # Documentation
└── docker-compose.yml # Container orchestration
├── pages/ # Next.js pages and API routes
│ ├── api/ # API endpoints
│ │ ├── auth/ # Authentication routes
│ │ └── admin/ # Admin routes
│ ├── _app.js # App wrapper
│ └── index.js # Home page
├── lib/ # Utility libraries
│ └── database.js # Database adapter
├── scripts/ # Database setup scripts
├── public/ # Static assets
└── .env.local # Environment variables
```
## Development
## 🔐 Default Admin Account
This project is designed for easy development and deployment. See the individual README files in `backend/` and `frontend/` for detailed setup instructions.
After running the database setup:
- **Email**: admin@tcgvault.com
- **Password**: admin123
## Contributing
## 🤝 Contributing
1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests
5. Submit a pull request
4. Submit a pull request
## License
## 📄 License
MIT License - feel free to use this project for your own collection management needs!
MIT License - see LICENSE file for details

View file

@ -1,220 +0,0 @@
# Visual Effects & 3D Card System
## 🎨 **Overview**
TCG Vault now features stunning visual effects that bring your trading cards to life with premium 3D interactions, foil shimmer effects, and rarity-based visual flair.
---
## ✨ **3D Card Tilt Effects**
### **Interactive Mouse Tracking**
- **Real-time 3D rotation** based on cursor position within card areas
- **Perspective-correct transforms** that create realistic depth
- **Smooth animations** with customizable easing curves
- **Performance optimized** with `will-change` and `transform3d` acceleration
### **Configuration**
```typescript
// Configurable tilt settings with smooth expansion
{
maxTilt: 15, // Maximum rotation degrees
perspective: 1000, // 3D perspective depth
scale: 1.06, // Hover scale factor (increased for premium feel)
speed: 700, // Animation speed in ms (slower for elegance)
reset: true, // Auto-reset on mouse leave
easing: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)' // Smooth organic easing
}
```
### **Size-Responsive Behavior**
- **Large cards**: 15° max tilt, 1.06× scale
- **Medium cards**: 10° max tilt, 1.03× scale
- **Small cards**: 10° max tilt, 1.03× scale
### **Smooth Expansion System**
- **Organic Timing**: 0.6s → 0.8s gradual expansion with elegant easing curves
- **Premium Rarities**: Ultra-smooth 0.8s → 1.2s expansion for Legendary/Mythic cards
- **Mythic Enhancement**: Special 1.4s breathe-like expansion for maximum premium feel
- **Layered Animation**: Different card elements animate with subtle 0.05s delays
---
## 🌟 **Foil & Shimmer Effects**
### **Foil Cards**
Applied to: **Super Rare**, **Legendary**, and **Mythic** cards
- **Sweep shimmer**: Elegant light sweep on hover
- **Semi-transparent overlay**: Maintains card visibility
- **Performance optimized**: CSS-only animations
### **Holographic Effect**
Applied to: **Legendary** and **Mythic** cards only
- **Rainbow gradient animation**: Continuously shifting spectrum
- **Multi-layer composition**: Background holo with content preservation
- **Subtle transparency**: Maintains readability while adding premium feel
### **Foil Types by Rarity**
- **Super Rare**: Basic foil shimmer
- **Legendary**: Holographic rainbow + foil shimmer
- **Mythic**: Holographic rainbow + foil shimmer
---
## 🌈 **Rarity Border System**
### **Color-Coded Glows**
Each rarity gets a distinctive border color and glow effect:
| Rarity | Border Color | Glow Effect | Usage |
|--------|--------------|-------------|-------|
| **Common** | Gray (`#6B7280`) | Subtle glow | Everyday cards |
| **Uncommon** | Green (`#22C55E`) | Medium glow | Notable cards |
| **Rare** | Blue (`#3B82F6`) | Bright glow | Special cards |
| **Super Rare** | Purple (`#9333EA`) | Strong glow + foil | Premium cards |
| **Legendary** | Gold (`#F59E0B`) | Intense glow + holo | Ultra-rare cards |
| **Mythic** | Red (`#EF4444`) | Max glow + holo | Legendary cards |
### **Progressive Enhancement**
- **Static**: Subtle border with light glow
- **Hover**: Enhanced glow and border brightness
- **Animation**: Breathing glow effect for premium rarities
### **Contextual Application**
- **Card View**: Full border glow on card containers
- **Table View**: Subtle left-border accent in rows
- **Image Placeholders**: Integrated with game-themed gradients
---
## 🎮 **Interactive Behavior**
### **Mouse Events**
1. **Mouse Enter**: Activate 3D tilt tracking
2. **Mouse Move**: Update tilt angles in real-time
3. **Mouse Leave**: Smooth reset to neutral position
4. **Hover**: Enhance border glow and trigger foil effects
### **Touch Support**
- **Mobile optimized**: Reduced tilt angles for touch devices
- **Performance aware**: Smooth 60fps animations on mobile
- **Fallback graceful**: Standard hover effects where 3D isn't supported
---
## 🛠️ **Technical Implementation**
### **Custom Hook: `use3DTilt`**
```typescript
const { ref, tiltStyles, tiltState } = use3DTilt({
maxTilt: 15,
scale: 1.05,
speed: 300
});
```
### **CSS Classes**
```css
/* 3D Effects */
.card-3d // 3D container setup
.card-3d-inner // Inner element transforms
.card-transition // Smooth transitions
/* Foil Effects */
.foil-card // Basic shimmer sweep
.foil-rainbow // Rainbow gradient animation
.holographic // Full holographic effect
/* Rarity Borders */
.rarity-border-{rarity} // Color-specific borders
.rarity-border-glow // Breathing glow animation
```
### **Performance Features**
- **Hardware acceleration**: Uses `transform3d()` and `will-change`
- **Optimized animations**: 60fps with CSS transitions
- **Memory efficient**: Event cleanup on unmount
- **Battery friendly**: Animation only during interaction
---
## 🎯 **Visual Hierarchy**
### **Information Priority**
1. **3D Tilt**: Primary interaction feedback
2. **Rarity Borders**: Secondary visual classification
3. **Foil Effects**: Premium card enhancement
4. **Holographic**: Ultra-rare card distinction
### **Accessibility**
- **Reduced motion support**: Respects `prefers-reduced-motion`
- **High contrast**: All effects maintain text readability
- **Focus indicators**: Clear keyboard navigation support
- **Screen reader**: Effects don't interfere with content
---
## 🚀 **Card Collection Experience**
### **Card View Mode**
- **Large 3D cards** with prominent tilt effects
- **Rarity glow borders** surrounding each card container
- **Foil shimmer** on premium cards during hover
- **Holographic animation** for legendary/mythic cards
### **Table View Mode**
- **Small thumbnails** with subtle 3D tilt
- **Border accent** on table rows matching rarity
- **Consistent effects** scaled appropriately for compact view
### **Placeholder Cards**
- **Game-themed gradients** as fallback for missing images
- **Full effect integration** - borders, foil, and 3D work on placeholders
- **Rarity-appropriate styling** even without card images
---
## 📊 **Effect Combinations**
### **Common Cards**
- ✅ 3D Tilt Effect
- ✅ Gray Border Glow
- ❌ No Foil Effects
### **Rare Cards**
- ✅ 3D Tilt Effect
- ✅ Blue Border Glow
- ❌ No Foil Effects
### **Super Rare Cards**
- ✅ 3D Tilt Effect
- ✅ Purple Border Glow
- ✅ Foil Shimmer Effect
### **Legendary Cards**
- ✅ 3D Tilt Effect
- ✅ Gold Border Glow
- ✅ Foil Shimmer Effect
- ✅ Holographic Animation
### **Mythic Cards**
- ✅ 3D Tilt Effect
- ✅ Red Border Glow
- ✅ Foil Shimmer Effect
- ✅ Holographic Animation
---
## 🎨 **Design Philosophy**
**Progressive Enhancement**: Effects enhance the experience without overwhelming content
**Performance First**: All animations target 60fps with hardware acceleration
**Accessibility Aware**: Visual effects complement rather than replace core functionality
**Mobile Optimized**: Reduced complexity on touch devices while maintaining premium feel
**Contextually Appropriate**: Effect intensity matches card rarity and importance
This visual effects system transforms TCG Vault from a simple database into a premium, interactive collection experience that honors the beauty and rarity of your trading cards! ✨🃏

Some files were not shown because too many files have changed in this diff Show more