diff --git a/index.html b/index.html
index 2c102fc..d734ca1 100644
--- a/index.html
+++ b/index.html
@@ -9,8 +9,13 @@
+
+
+
+
+
diff --git a/nginx.conf b/nginx.conf
index 6577200..8b35a69 100644
--- a/nginx.conf
+++ b/nginx.conf
@@ -4,12 +4,25 @@ server {
root /usr/share/nginx/html;
index index.html;
- # Gzip compression
+ # Gzip compression (fallback for clients that don't support Brotli)
gzip on;
gzip_vary on;
- gzip_min_length 1024;
- gzip_proxied expired no-cache no-store private auth;
- gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml application/javascript application/json;
+ gzip_comp_level 6;
+ gzip_min_length 256;
+ gzip_proxied any;
+ gzip_types
+ text/plain
+ text/css
+ text/xml
+ text/javascript
+ application/javascript
+ application/x-javascript
+ application/json
+ application/xml
+ application/wasm
+ application/octet-stream
+ image/svg+xml
+ font/woff2;
gzip_disable "MSIE [1-6]\.";
# Security headers
diff --git a/vite.config.ts b/vite.config.ts
index dc42f59..71c4a46 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -128,30 +128,71 @@ export default defineConfig(({ mode }) => {
rollupOptions: {
output: {
// Manual chunk splitting for large libraries to improve load times
- manualChunks: {
- // Core React libraries
- 'react-vendor': ['react', 'react-dom', 'react-router-dom'],
+ manualChunks(id) {
+ // Core React libraries - load first
+ if (id.includes('node_modules/react') ||
+ id.includes('node_modules/react-dom') ||
+ id.includes('node_modules/react-router')) {
+ return 'react-vendor';
+ }
- // tldraw - large drawing library (split into separate chunk)
- 'tldraw': ['tldraw', '@tldraw/tldraw', '@tldraw/tlschema'],
+ // tldraw core - split from shapes
+ if (id.includes('node_modules/tldraw') ||
+ id.includes('node_modules/@tldraw')) {
+ return 'tldraw';
+ }
// Automerge - CRDT sync library
- 'automerge': [
- '@automerge/automerge',
- '@automerge/automerge-repo',
- '@automerge/automerge-repo-react-hooks'
- ],
+ if (id.includes('node_modules/@automerge')) {
+ return 'automerge';
+ }
// AI SDKs (lazy load)
- 'ai-sdks': ['@anthropic-ai/sdk', 'openai', 'ai'],
+ if (id.includes('node_modules/@anthropic-ai') ||
+ id.includes('node_modules/openai') ||
+ id.includes('node_modules/ai/')) {
+ return 'ai-sdks';
+ }
// ML/transformers (VERY large, lazy loaded)
- 'ml-libs': ['@xenova/transformers'],
+ if (id.includes('node_modules/@xenova')) {
+ return 'ml-libs';
+ }
// Markdown editors
- 'markdown': ['@uiw/react-md-editor', 'cherry-markdown', 'marked', 'react-markdown'],
+ if (id.includes('node_modules/@uiw/react-md-editor') ||
+ id.includes('node_modules/cherry-markdown') ||
+ id.includes('node_modules/marked') ||
+ id.includes('node_modules/react-markdown')) {
+ return 'markdown';
+ }
- // Note: gun, webnative, holosphere removed - stubbed for future Nostr integration
+ // CodeMirror (used by markdown editors)
+ if (id.includes('node_modules/@codemirror') ||
+ id.includes('node_modules/codemirror')) {
+ return 'codemirror';
+ }
+
+ // Daily video chat
+ if (id.includes('node_modules/@daily-co')) {
+ return 'daily-video';
+ }
+
+ // html2canvas (screenshots)
+ if (id.includes('node_modules/html2canvas')) {
+ return 'html2canvas';
+ }
+
+ // ONNX runtime (ML inference)
+ if (id.includes('node_modules/onnxruntime')) {
+ return 'onnx';
+ }
+
+ // DOMPurify and sanitizers
+ if (id.includes('node_modules/dompurify') ||
+ id.includes('node_modules/isomorphic-dompurify')) {
+ return 'sanitizers';
+ }
},
},
},