Compare commits

...

10 Commits

Author SHA1 Message Date
39faa7a98c description page 2025-03-23 19:24:33 +05:30
e6b8f267b9 aimodel.beanstalkedu.com 2025-03-23 18:54:38 +05:30
71b400f7da build issue solved 2025-03-22 19:42:54 +05:30
1168bfd709 logo 2025-03-22 19:09:19 +05:30
967386869f preview allowedHosts 2025-03-22 18:33:50 +05:30
03dacd76d2 domains 2025-03-22 18:16:46 +05:30
8a859e9d4a server 2025-03-22 17:45:42 +05:30
208d245ec9 rect 2025-03-22 17:30:13 +05:30
c5876941bb preview host added 2025-03-22 17:22:14 +05:30
316aa09148 vite config on astro.config add all for yarn dev 2025-03-22 17:19:12 +05:30
13 changed files with 4884 additions and 62 deletions

View File

@@ -6,38 +6,54 @@ import { chunkSplitPlugin } from 'vite-plugin-chunk-split';
// https://astro.build/config
export default defineConfig({
output: 'static',
// Use client:only for all React components
// Simplified React integration - fully client-side
integrations: [
react({ ssr: false }), // Disable SSR for React components
react({
include: ['**/*.tsx'],
ssr: false, // Disable SSR completely
experimentalReactChildren: false
}),
tailwind()
],
vite: {
server: {
allowedHosts: ['chat-with-ai.s38.siliconpin.com','chat-with-ai.s38.siliconpin.com','chat.siliconpin.com','aimodel.beanstalkedu.com']
},
preview: {
allowedHosts: ['chat-with-ai.s38.siliconpin.com','chat-with-ai.s38.siliconpin.com','chat.siliconpin.com','aimodel.beanstalkedu.com']
},
// Simplified plugins - focus on critical functionality
plugins: [
chunkSplitPlugin({
strategy: 'default',
customSplitting: {
'ui-components': [/src\/components\/ui\/.*/],
'contexts': [/src\/contexts\/.*/],
'utils': [/src\/utils\/.*/],
'document-extraction': [/src\/utils\/documentExtraction.ts/],
'mongo-sync': [/src\/utils\/mongoSync.ts/],
'react-vendor': ['react', 'react-dom']
}
})
],
// Avoid hydration issues with different Node.js environments
// Avoid hydration issues with external packages
ssr: {
noExternal: ['@radix-ui/*', 'class-variance-authority']
},
build: {
chunkSizeWarningLimit: 1000,
chunkSizeWarningLimit: 5000,
// Simplified bundling - focus on React
rollupOptions: {
output: {
manualChunks: {
'pdf-lib': ['pdfjs-dist']
'react-vendor': ['react', 'react-dom']
}
}
}
},
minify: 'esbuild', // Use esbuild for faster and simpler minification
},
// Deduplicate React packages to prevent multiple instances
resolve: {
dedupe: ['react', 'react-dom']
},
// Make sure React is optimized properly
optimizeDeps: {
include: ['react', 'react-dom', '@radix-ui/react-dialog', '@radix-ui/react-dropdown-menu']
}
}
});

View File

@@ -15,6 +15,8 @@
"file-type": "^20.4.1",
"mammoth": "^1.9.0",
"pdfjs-dist": "^5.0.375",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.54.2",
},
"devDependencies": {
@@ -30,10 +32,9 @@
"clsx": "^2.1.1",
"lucide-react": "^0.483.0",
"postcss": "^8.5.3",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"tailwind-merge": "^3.0.2",
"tailwindcss": "3",
"terser": "^5.39.0",
"vite-plugin-chunk-split": "^0.5.0",
},
},
@@ -205,6 +206,8 @@
"@jridgewell/set-array": ["@jridgewell/set-array@1.2.1", "", {}, "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A=="],
"@jridgewell/source-map": ["@jridgewell/source-map@0.3.6", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" } }, "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ=="],
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="],
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.25", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ=="],
@@ -485,6 +488,8 @@
"buffer-fill": ["buffer-fill@1.0.0", "", {}, "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ=="],
"buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
"camelcase": ["camelcase@8.0.0", "", {}, "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA=="],
"camelcase-css": ["camelcase-css@2.0.1", "", {}, "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="],
@@ -523,7 +528,7 @@
"comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="],
"commander": ["commander@4.1.1", "", {}, "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="],
"commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="],
"common-ancestor-path": ["common-ancestor-path@1.0.1", "", {}, "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w=="],
@@ -759,6 +764,8 @@
"longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="],
"loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="],
"lop": ["lop@0.4.2", "", { "dependencies": { "duck": "^0.1.12", "option": "~0.2.1", "underscore": "^1.13.1" } }, "sha512-RefILVDQ4DKoRZsJ4Pj22TxE3omDO47yFpkIBoDKzkqPRISs5U1cnAdg/5583YPkWPaLIYHOKRMQSvjFsO26cw=="],
"lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
@@ -979,9 +986,9 @@
"radix3": ["radix3@1.1.2", "", {}, "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA=="],
"react": ["react@19.0.0", "", {}, "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="],
"react": ["react@18.3.1", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ=="],
"react-dom": ["react-dom@19.0.0", "", { "dependencies": { "scheduler": "^0.25.0" }, "peerDependencies": { "react": "^19.0.0" } }, "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ=="],
"react-dom": ["react-dom@18.3.1", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" }, "peerDependencies": { "react": "^18.3.1" } }, "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw=="],
"react-hook-form": ["react-hook-form@7.54.2", "", { "peerDependencies": { "react": "^16.8.0 || ^17 || ^18 || ^19" } }, "sha512-eHpAUgUjWbZocoQYUHposymRb4ZP6d0uwUnooL2uOybA9/3tPUvoAKqEWK1WaSiTxxOfTpffNZP7QwlnM3/gEg=="],
@@ -1045,7 +1052,7 @@
"safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
"scheduler": ["scheduler@0.25.0", "", {}, "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA=="],
"scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="],
"seek-bzip": ["seek-bzip@1.0.6", "", { "dependencies": { "commander": "^2.8.1" }, "bin": { "seek-bunzip": "bin/seek-bunzip", "seek-table": "bin/seek-bzip-table" } }, "sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ=="],
@@ -1069,8 +1076,12 @@
"smol-toml": ["smol-toml@1.3.1", "", {}, "sha512-tEYNll18pPKHroYSmLLrksq233j021G0giwW7P3D24jC54pQ5W5BXMsQ/Mvw1OJCmEYDgY+lrzT+3nNUtoNfXQ=="],
"source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
"source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="],
"space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="],
"sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="],
@@ -1103,6 +1114,8 @@
"tar-stream": ["tar-stream@1.6.2", "", { "dependencies": { "bl": "^1.0.0", "buffer-alloc": "^1.2.0", "end-of-stream": "^1.0.0", "fs-constants": "^1.0.0", "readable-stream": "^2.3.0", "to-buffer": "^1.1.1", "xtend": "^4.0.0" } }, "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A=="],
"terser": ["terser@5.39.0", "", { "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "bin": { "terser": "bin/terser" } }, "sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw=="],
"thenify": ["thenify@3.3.1", "", { "dependencies": { "any-promise": "^1.0.0" } }, "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw=="],
"thenify-all": ["thenify-all@1.6.0", "", { "dependencies": { "thenify": ">= 3.1.0 < 4" } }, "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA=="],
@@ -1277,14 +1290,14 @@
"readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
"seek-bzip/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="],
"string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
"string-width-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
"strip-ansi-cjs/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
"sucrase/commander": ["commander@4.1.1", "", {}, "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="],
"unstorage/chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],
"wrap-ansi-cjs/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],

View File

@@ -6,8 +6,10 @@
"dev": "astro dev --host --port 2008",
"start": "astro preview --host --port 2008",
"build": "astro build",
"build:prod": "ASTRO_TELEMETRY_DISABLED=1 astro build",
"preview": "astro preview",
"astro": "astro"
"astro": "astro",
"check": "astro check"
},
"dependencies": {
"@astrojs/netlify": "^6.2.3",
@@ -21,6 +23,8 @@
"file-type": "^20.4.1",
"mammoth": "^1.9.0",
"pdfjs-dist": "^5.0.375",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.54.2"
},
"devDependencies": {
@@ -36,10 +40,9 @@
"clsx": "^2.1.1",
"lucide-react": "^0.483.0",
"postcss": "^8.5.3",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"tailwind-merge": "^3.0.2",
"tailwindcss": "3",
"terser": "^5.39.0",
"vite-plugin-chunk-split": "^0.5.0"
},
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -1,9 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 128 128">
<path d="M50.4 78.5a75.1 75.1 0 0 0-28.5 6.9l24.2-65.7c.7-2 1.9-3.2 3.4-3.2h29c1.5 0 2.7 1.2 3.4 3.2l24.2 65.7s-11.6-7-28.5-7L67 45.5c-.4-1.7-1.6-2.8-2.9-2.8-1.3 0-2.5 1.1-2.9 2.7L50.4 78.5Zm-1.1 28.2Zm-4.2-20.2c-2 6.6-.6 15.8 4.2 20.2a17.5 17.5 0 0 1 .2-.7 5.5 5.5 0 0 1 5.7-4.5c2.8.1 4.3 1.5 4.7 4.7.2 1.1.2 2.3.2 3.5v.4c0 2.7.7 5.2 2.2 7.4a13 13 0 0 0 5.7 4.9v-.3l-.2-.3c-1.8-5.6-.5-9.5 4.4-12.8l1.5-1a73 73 0 0 0 3.2-2.2 16 16 0 0 0 6.8-11.4c.3-2 .1-4-.6-6l-.8.6-1.6 1a37 37 0 0 1-22.4 2.7c-5-.7-9.7-2-13.2-6.2Z" />
<style>
path { fill: #000; }
@media (prefers-color-scheme: dark) {
path { fill: #FFF; }
}
</style>
<svg width="60" height="60" viewBox="0 0 150 150" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="50" height="50" fill="#FF0000"/>
<rect y="100" width="50" height="50" fill="#0000FF"/>
<rect x="100" width="50" height="50" fill="#FF0000"/>
<rect x="100" y="100" width="50" height="50" fill="#0000FF"/>
<rect x="50" y="50" width="50" height="50" fill="#008000"/>
</svg>

Before

Width:  |  Height:  |  Size: 749 B

After

Width:  |  Height:  |  Size: 401 B

7
public/logo.svg Normal file
View File

@@ -0,0 +1,7 @@
<svg width="60" height="60" viewBox="0 0 150 150" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="50" height="50" fill="#FF0000"/>
<rect y="100" width="50" height="50" fill="#0000FF"/>
<rect x="100" width="50" height="50" fill="#FF0000"/>
<rect x="100" y="100" width="50" height="50" fill="#0000FF"/>
<rect x="50" y="50" width="50" height="50" fill="#008000"/>
</svg>

After

Width:  |  Height:  |  Size: 401 B

56
public/react-patch.js vendored Normal file
View File

@@ -0,0 +1,56 @@
/**
* React Hydration Error Patch
*
* This script patches common React hydration errors by:
* 1. Providing a global React object to prevent "React is not defined" errors
* 2. Polyfilling useLayoutEffect to prevent hydration mismatches
* 3. Adding error tracking for hydration errors
*/
(function() {
console.log('Applying React hydration patch...');
// Track hydration errors
window.__REACT_HYDRATION_ERRORS = [];
// Create a console error interceptor to catch React errors
const originalConsoleError = console.error;
console.error = function(...args) {
// Check if this is a React hydration error
const errorString = args.join(' ');
if (
errorString.includes('hydrat') ||
errorString.includes('useLayoutEffect') ||
errorString.includes('expected server HTML')
) {
window.__REACT_HYDRATION_ERRORS.push({
message: errorString,
timestamp: new Date().toISOString()
});
// Don't show hydration errors to users
return;
}
// Pass through other errors
originalConsoleError.apply(console, args);
};
// Add some recovery mechanisms
window.addEventListener('error', function(event) {
if (event.error && (
event.error.message.includes('React') ||
event.error.message.includes('hydrat') ||
event.error.message.includes('useLayoutEffect')
)) {
console.log('Caught React-related error:', event.error.message);
// If too many errors occur, offer to refresh the page
if (window.__REACT_HYDRATION_ERRORS.length > 5) {
if (confirm('The application encountered an error. Would you like to reload the page?')) {
window.location.reload();
}
}
}
});
})();

View File

@@ -6,16 +6,58 @@ import { SyncProvider } from '../contexts/SyncContext';
import { ChatInterface } from './ChatInterface';
import { Toaster } from './ui/toaster';
// Simple error boundary component to catch React errors
class ErrorBoundary extends React.Component<
{ children: React.ReactNode },
{ hasError: boolean, error: Error | null }
> {
constructor(props: { children: React.ReactNode }) {
super(props);
this.state = { hasError: false, error: null };
}
static getDerivedStateFromError(error: Error) {
return { hasError: true, error };
}
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
console.error("React error caught:", error, errorInfo);
}
render() {
if (this.state.hasError) {
return (
<div className="h-screen flex items-center justify-center bg-background text-foreground">
<div className="max-w-md p-6 border rounded-lg shadow-lg bg-white dark:bg-gray-800">
<h2 className="text-xl font-bold mb-4">Something went wrong</h2>
<p className="mb-4 text-red-600 dark:text-red-400">
{this.state.error?.message || "An unknown error occurred"}
</p>
<button
className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700"
onClick={() => window.location.reload()}
>
Refresh Page
</button>
</div>
</div>
);
}
return this.props.children;
}
}
export function AppRoot() {
// Use client-side only rendering for components that depend on browser APIs
const [isMounted, setIsMounted] = useState(false);
useEffect(() => {
// This effect runs only in the browser, not during SSR
// This effect runs only in the browser
setIsMounted(true);
}, []);
// Return a minimal loading state until client-side code can take over
// Important: Return a minimal loading state until client-side code can take over
if (!isMounted) {
return (
<div className="h-screen flex items-center justify-center bg-background text-foreground">
@@ -29,17 +71,19 @@ export function AppRoot() {
// Actual component rendering only happens client-side
return (
<div id="app-root" className="h-screen">
<ThemeProvider>
<ConfigProvider>
<ChatProvider>
<SyncProvider>
<ChatInterface />
</SyncProvider>
</ChatProvider>
<Toaster />
</ConfigProvider>
</ThemeProvider>
</div>
<ErrorBoundary>
<div id="app-root" className="h-screen">
<ThemeProvider>
<ConfigProvider>
<ChatProvider>
<SyncProvider>
<ChatInterface />
</SyncProvider>
</ChatProvider>
<Toaster />
</ConfigProvider>
</ThemeProvider>
</div>
</ErrorBoundary>
);
}

View File

@@ -16,16 +16,11 @@ const { title } = Astro.props;
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="generator" content={Astro.generator} />
<title>{title}</title>
<script is:inline src="/react-patch.js"></script>
</head>
<body>
<main class="min-h-screen">
<slot />
</main>
<script>
// Make sure React has initialized before rendering components
document.addEventListener('DOMContentLoaded', () => {
console.log('DOM fully loaded and parsed');
});
</script>
</body>
</html>

115
src/pages/description.astro Normal file
View File

@@ -0,0 +1,115 @@
---
import Layout from '../layouts/Layout.astro';
---
<Layout title="AI Chat - Home">
<div class="container mx-auto py-8 px-4">
<section class="text-center py-16 md:py-24">
<div class="animate-in fade-in slide-in-from-bottom-10 duration-700">
<h1 class="text-4xl md:text-5xl lg:text-6xl font-bold mb-6 bg-clip-text text-transparent bg-gradient-to-r from-primary to-purple-600">
Welcome to AI Chat
</h1>
<p class="text-xl text-muted-foreground max-w-3xl mx-auto mb-8">
A powerful interface for conversing with AI models with flexible provider options.
</p>
<a href="/tools/chat-with-ai" class="inline-block px-6 py-3 bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-all-normal hover-lift shadow-md hover:shadow-lg">
Start Chatting
<span class="inline-block ml-2 transition-transform group-hover:translate-x-1">→</span>
</a>
</div>
</section>
<section class="py-12 grid md:grid-cols-3 gap-8">
<div class="bg-card text-card-foreground rounded-lg p-6 shadow-md card-elevation animate-in fade-in slide-in-from-bottom-10 duration-500 delay-100">
<div class="w-12 h-12 bg-primary/10 rounded-full flex items-center justify-center mb-4 transition-transform-bounce hover:scale-110">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6 text-primary">
<path stroke-linecap="round" stroke-linejoin="round" d="M7.5 8.25h9m-9 3H12m-9.75 1.51c0 1.6 1.123 2.994 2.707 3.227 1.129.166 2.27.293 3.423.379.35.026.67.21.865.501L12 21l2.755-4.133a1.14 1.14 0 01.865-.501 48.172 48.172 0 003.423-.379c1.584-.233 2.707-1.626 2.707-3.228V6.741c0-1.602-1.123-2.995-2.707-3.228A48.394 48.394 0 0012 3c-2.392 0-4.744.175-7.043.513C3.373 3.746 2.25 5.14 2.25 6.741v6.018z" />
</svg>
</div>
<h2 class="text-xl font-semibold mb-2">Multiple AI Providers</h2>
<p class="text-muted-foreground">Connect to various AI providers including OpenAI, Anthropic, and more, or run models directly in your browser.</p>
</div>
<div class="bg-card text-card-foreground rounded-lg p-6 shadow-md card-elevation animate-in fade-in slide-in-from-bottom-10 duration-500 delay-200">
<div class="w-12 h-12 bg-primary/10 rounded-full flex items-center justify-center mb-4 transition-transform-bounce hover:scale-110">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6 text-primary">
<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m6.75 12l-3-3m0 0l-3 3m3-3v6m-1.5-15H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z" />
</svg>
</div>
<h2 class="text-xl font-semibold mb-2">File Upload Support</h2>
<p class="text-muted-foreground">Upload and analyze documents with AI assistance. Supports various file formats for enhanced context in conversations.</p>
</div>
<div class="bg-card text-card-foreground rounded-lg p-6 shadow-md card-elevation animate-in fade-in slide-in-from-bottom-10 duration-500 delay-300">
<div class="w-12 h-12 bg-primary/10 rounded-full flex items-center justify-center mb-4 transition-transform-bounce hover:scale-110">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6 text-primary">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75M21 12c0 1.268-.63 2.39-1.593 3.068a3.745 3.745 0 01-1.043 3.296 3.745 3.745 0 01-3.296 1.043A3.745 3.745 0 0112 21c-1.268 0-2.39-.63-3.068-1.593a3.746 3.746 0 01-3.296-1.043 3.745 3.745 0 01-1.043-3.296A3.745 3.745 0 013 12c0-1.268.63-2.39 1.593-3.068a3.745 3.745 0 011.043-3.296 3.746 3.746 0 013.296-1.043A3.746 3.746 0 0112 3c1.268 0 2.39.63 3.068 1.593a3.746 3.746 0 013.296 1.043 3.746 3.746 0 011.043 3.296A3.745 3.745 0 0121 12z" />
</svg>
</div>
<h2 class="text-xl font-semibold mb-2">Secure & Private</h2>
<p class="text-muted-foreground">Option to use browser-based models for complete privacy, or connect securely to external providers with your own API keys.</p>
</div>
</section>
<section class="py-12 border-t">
<div class="max-w-3xl mx-auto text-center animate-in fade-in slide-in-from-bottom-10 duration-500 delay-300">
<h2 class="text-2xl font-bold mb-6">About This Project</h2>
<p class="mb-4 text-muted-foreground">
This AI chat interface is designed to provide a flexible and powerful way to interact with various AI models.
It supports multiple providers, file uploads for context, and can even run models directly in your browser for complete privacy.
</p>
<p class="text-muted-foreground">
Use the navigation to explore the application and start chatting with AI assistants.
</p>
</div>
</section>
<section class="py-16 border-t">
<div class="max-w-4xl mx-auto">
<h2 class="text-2xl font-bold mb-8 text-center">Frequently Asked Questions</h2>
<div class="space-y-6 animate-in fade-in slide-in-from-bottom-10 duration-500 delay-400">
<div class="p-5 border rounded-lg shadow-sm hover:shadow-md transition-all-normal">
<h3 class="text-lg font-medium mb-2">What AI models can I use?</h3>
<p class="text-muted-foreground">You can connect to various providers like OpenAI (ChatGPT), Anthropic (Claude), or run models directly in your browser with WebLLM for complete privacy.</p>
</div>
<div class="p-5 border rounded-lg shadow-sm hover:shadow-md transition-all-normal">
<h3 class="text-lg font-medium mb-2">Do I need an API key?</h3>
<p class="text-muted-foreground">For cloud-based providers like OpenAI or Anthropic, you'll need your own API key. For browser-based models using WebLLM, no API key is required as everything runs locally.</p>
</div>
<div class="p-5 border rounded-lg shadow-sm hover:shadow-md transition-all-normal">
<h3 class="text-lg font-medium mb-2">What files can I upload?</h3>
<p class="text-muted-foreground">The system supports various document formats including PDF, DOCX, TXT and more to provide context for your conversations with AI.</p>
</div>
<div class="p-5 border rounded-lg shadow-sm hover:shadow-md transition-all-normal">
<h3 class="text-lg font-medium mb-2">How secure is my data?</h3>
<p class="text-muted-foreground">When using WebLLM, all processing happens in your browser and data never leaves your device. For cloud providers, data is sent to their APIs according to their privacy policies.</p>
</div>
</div>
</div>
</section>
</div>
</Layout>
<script>
// Add intersection observer for scroll animations
document.addEventListener('DOMContentLoaded', () => {
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('animate-in');
observer.unobserve(entry.target);
}
});
}, observerOptions);
// Select all sections
document.querySelectorAll('section').forEach(section => {
observer.observe(section);
});
});
</script>

View File

@@ -1,15 +1,42 @@
---
import Layout from '../layouts/Layout.astro';
import { AppRoot } from '../components/AppRoot';
---
<Layout title="AI Chat Interface">
<AppRoot client:only="react" />
<div id="react-root"></div>
</Layout>
<script>
// Handle any client-side initialization here
document.addEventListener('astro:page-load', () => {
console.log('Page loaded and ready for interaction');
// Simple approach to load React components after DOM is ready
document.addEventListener('DOMContentLoaded', async () => {
try {
// Dynamically import the AppRoot component and React
const React = await import('react');
const ReactDOM = await import('react-dom/client');
const { AppRoot } = await import('../components/AppRoot');
// Mount the React app to the div
const container = document.getElementById('react-root');
if (container) {
const root = ReactDOM.createRoot(container);
root.render(React.createElement(AppRoot));
console.log('React app mounted successfully');
} else {
console.error('Could not find react-root element');
}
} catch (error) {
console.error('Error loading React app:', error);
// Show error to user
const container = document.getElementById('react-root');
if (container) {
container.innerHTML = `
<div style="padding: 2rem; text-align: center;">
<h2>Error Loading Application</h2>
<p>There was a problem loading the application. Please refresh the page.</p>
<button onclick="window.location.reload()">Refresh</button>
</div>
`;
}
}
});
</script>

View File

@@ -1,7 +0,0 @@
import { defineConfig } from 'vite';
export default defineConfig({
preview: {
allowedHosts: ['chat-with-ai.s38.siliconpin.com']
}
});

4555
yarn.lock Normal file

File diff suppressed because it is too large Load Diff