Skip to content

Commit 7bd825b

Browse files
fixed configurations with db types
1 parent 8776337 commit 7bd825b

File tree

11 files changed

+723
-734
lines changed

11 files changed

+723
-734
lines changed

app/api/subscription/usage/route.ts

Lines changed: 0 additions & 60 deletions
This file was deleted.

app/page.tsx

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,12 @@ import { AuthDialog } from '@/components/auth-dialog';
55
import { Chat } from '@/components/chat';
66
import { PromptInputBox } from '@/components/ui/ai-prompt-box';
77
import { NavBar } from '@/components/navbar';
8-
import { Preview } from '@/components/preview';
9-
import { Sidebar } from '@/components/sidebar';
10-
import { PricingModal } from '@/components/pricing';
118
import { useAuth } from '@/lib/auth';
9+
import dynamic from 'next/dynamic';
1210
import { Project, createProject, saveMessage, getProjectMessages, generateProjectTitle, getProject } from '@/lib/database';
1311
import { Message, toAISDKMessages, toMessageImage } from '@/lib/messages';
1412
import { LLMModelConfig } from '@/lib/models';
15-
import modelsList from '@/lib/models.json';
13+
import { loadModels } from '@/lib/models-loader';
1614
import { FragmentSchema, fragmentSchema as schema } from '@/lib/schema';
1715
import { createSupabaseBrowserClient } from '@/lib/supabase-browser';
1816
import templates, { TemplateId } from '@/lib/templates';
@@ -28,6 +26,18 @@ import { HeroPillSecond } from '@/components/announcement';
2826
import { useAnalytics } from '@/lib/analytics-service';
2927
import { SupabaseClient } from '@supabase/supabase-js';
3028

29+
const PricingModal = dynamic(() => import('@/components/pricing').then(mod => ({ default: mod.PricingModal })), {
30+
ssr: false,
31+
});
32+
33+
const Sidebar = dynamic(() => import('@/components/sidebar').then(mod => ({ default: mod.Sidebar })), {
34+
ssr: false,
35+
});
36+
37+
const Preview = dynamic(() => import('@/components/preview').then(mod => ({ default: mod.Preview })), {
38+
ssr: false,
39+
});
40+
3141
export default function Home() {
3242
const supabase = createSupabaseBrowserClient()
3343
const [selectedTemplate, setSelectedTemplate] = useState<'auto' | TemplateId>('auto')
@@ -37,6 +47,7 @@ export default function Home() {
3747
model: 'claude-3-5-sonnet-latest',
3848
},
3949
)
50+
const [modelsList, setModelsList] = useState<any>(null)
4051

4152
const posthog = usePostHog()
4253
const analytics = useAnalytics()
@@ -71,6 +82,11 @@ export default function Home() {
7182
const { session } = useAuth(setAuthDialogCallback, setAuthViewCallback)
7283
const { userTeam } = useUserTeam()
7384

85+
// Load models list asynchronously
86+
useEffect(() => {
87+
loadModels().then(setModelsList)
88+
}, [])
89+
7490

7591
const handleChatSelected = async (chatId: string) => {
7692
const project = await getProject(supabase, chatId);
@@ -79,15 +95,15 @@ export default function Home() {
7995
}
8096
};
8197

82-
const filteredModels = modelsList.models.filter((model) => {
98+
const filteredModels = modelsList?.models?.filter((model: any) => {
8399
if (process.env.NEXT_PUBLIC_HIDE_LOCAL_MODELS) {
84100
return model.providerId !== 'ollama'
85101
}
86102
return true
87-
})
103+
}) || []
88104

89105
const currentModel = filteredModels.find(
90-
(model) => model.id === languageModel.model,
106+
(model: any) => model.id === languageModel.model,
91107
);
92108

93109

components/chat.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export function Chat({
2222
if (chatContainer) {
2323
chatContainer.scrollTop = chatContainer.scrollHeight
2424
}
25+
// eslint-disable-next-line react-hooks/exhaustive-deps
2526
}, [JSON.stringify(messages)])
2627

2728
return (
@@ -40,6 +41,7 @@ export function Chat({
4041
}
4142
if (content.type === 'image') {
4243
return (
44+
// eslint-disable-next-line @next/next/no-img-element
4345
<img
4446
key={id}
4547
src={content.image}

components/help-center.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// File: components/help-modal.tsx
21
"use client"
32

43
import { Badge } from '@/components/ui/badge'

components/logo.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export default function Logo(
1515
<Image
1616
src={src}
1717
alt="Logo"
18+
priority
1819
{...props}
1920
style={{ ...style, width, height: 'auto' }}
2021
/>

components/ui/ai-prompt-box.tsx

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import * as TooltipPrimitive from "@radix-ui/react-tooltip";
33
import * as DialogPrimitive from "@radix-ui/react-dialog";
44
import { ArrowUp, Paperclip, Square, X, StopCircle, Mic, Globe, BrainCog, FolderCog } from "lucide-react";
55
import { motion, AnimatePresence } from "framer-motion";
6+
import Image from "next/image";
67
import { ChatSettings } from '../chat-settings'
78
import { ChatPicker } from '../chat-picker'
89
import { LLMModel, LLMModelConfig } from '@/lib/models'
@@ -182,13 +183,17 @@ const VoiceRecorder: React.FC<VoiceRecorderProps> = ({
182183
clearInterval(timerRef.current);
183184
timerRef.current = null;
184185
}
185-
onStopRecording(time);
186-
setTime(0);
186+
setTime(currentTime => {
187+
if (currentTime > 0) {
188+
onStopRecording(currentTime);
189+
}
190+
return 0;
191+
});
187192
}
188193
return () => {
189194
if (timerRef.current) clearInterval(timerRef.current);
190195
};
191-
}, [isRecording, time, onStartRecording, onStopRecording]);
196+
}, [isRecording, onStartRecording, onStopRecording]);
192197

193198
const formatTime = (seconds: number) => {
194199
const mins = Math.floor(seconds / 60);
@@ -242,10 +247,12 @@ const ImageViewDialog: React.FC<ImageViewDialogProps> = ({ imageUrl, onClose })
242247
transition={{ duration: 0.2, ease: "easeOut" }}
243248
className="relative bg-background rounded-2xl overflow-hidden shadow-2xl"
244249
>
245-
<img
250+
<Image
246251
src={imageUrl}
247252
alt="Full preview"
248-
className="w-full max-h-[80vh] object-contain rounded-2xl"
253+
fill
254+
className="object-contain rounded-2xl"
255+
sizes="(max-width: 768px) 95vw, (max-width: 1200px) 80vw, 70vw"
249256
/>
250257
</motion.div>
251258
</DialogContent>
@@ -479,11 +486,11 @@ export const PromptInputBox = React.forwardRef((props: PromptInputBoxProps, ref:
479486
}
480487
};
481488

482-
const handleCanvasToggle = () => setShowCanvas((prev) => !prev);
489+
const handleCanvasToggle = () => setShowCanvas(prev => !prev);
483490

484491
const isImageFile = (file: File) => file.type.startsWith("image/");
485492

486-
const processFile = (file: File) => {
493+
const processFile = React.useCallback((file: File) => {
487494
if (!isImageFile(file)) {
488495
console.log("Only image files are allowed");
489496
return;
@@ -496,7 +503,7 @@ export const PromptInputBox = React.forwardRef((props: PromptInputBoxProps, ref:
496503
const reader = new FileReader();
497504
reader.onload = (e) => setFilePreviews({ [file.name]: e.target?.result as string });
498505
reader.readAsDataURL(file);
499-
};
506+
}, []);
500507

501508
const handleDragOver = React.useCallback((e: React.DragEvent) => {
502509
e.preventDefault();
@@ -514,7 +521,7 @@ export const PromptInputBox = React.forwardRef((props: PromptInputBoxProps, ref:
514521
const files = Array.from(e.dataTransfer.files);
515522
const imageFiles = files.filter((file) => isImageFile(file));
516523
if (imageFiles.length > 0) processFile(imageFiles[0]);
517-
}, []);
524+
}, [processFile]);
518525

519526
const handleRemoveFile = (index: number) => {
520527
const fileToRemove = files[index];
@@ -537,7 +544,7 @@ export const PromptInputBox = React.forwardRef((props: PromptInputBoxProps, ref:
537544
}
538545
}
539546
}
540-
}, []);
547+
}, [processFile]);
541548

542549
React.useEffect(() => {
543550
document.addEventListener("paste", handlePaste);
@@ -608,13 +615,15 @@ export const PromptInputBox = React.forwardRef((props: PromptInputBoxProps, ref:
608615
<div key={index} className="relative group">
609616
{file.type.startsWith("image/") && filePreviews[file.name] && (
610617
<div
611-
className="w-16 h-16 rounded-xl overflow-hidden cursor-pointer transition-all duration-300"
618+
className="relative w-16 h-16 rounded-xl overflow-hidden cursor-pointer transition-all duration-300"
612619
onClick={() => openImageModal(filePreviews[file.name])}
613620
>
614-
<img
621+
<Image
615622
src={filePreviews[file.name]}
616623
alt={file.name}
617-
className="h-full w-full object-cover"
624+
fill
625+
className="object-cover"
626+
sizes="64px"
618627
/>
619628
<button
620629
onClick={(e) => {

lib/models-loader.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Lazy loader for models.json to reduce initial bundle size
2+
let modelsCache: any = null;
3+
4+
export async function loadModels() {
5+
if (modelsCache) {
6+
return modelsCache;
7+
}
8+
9+
const models = await import('./models.json');
10+
modelsCache = models.default;
11+
return modelsCache;
12+
}
13+
14+
export function getModelsSync() {
15+
if (!modelsCache) {
16+
// Fallback for synchronous access - will be replaced with async loading
17+
const models = require('./models.json');
18+
modelsCache = models;
19+
}
20+
return modelsCache;
21+
}

next.config.mjs

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,40 @@ const nextConfig = {
33
eslint: {
44
ignoreDuringBuilds: true
55
},
6-
webpack: (config, { dev }) => {
7-
// Optimize caching for large JSON files
8-
if (!dev) {
9-
config.cache = {
10-
...config.cache,
11-
maxMemoryGenerations: 1,
12-
};
13-
}
14-
return config;
15-
}
6+
experimental: {
7+
optimizePackageImports: ['lucide-react', '@radix-ui/react-icons'],
8+
},
9+
async headers() {
10+
return [
11+
{
12+
source: '/_next/static/:path*',
13+
headers: [
14+
{
15+
key: 'Cache-Control',
16+
value: 'public, max-age=31536000, immutable',
17+
},
18+
],
19+
},
20+
{
21+
source: '/logo.png',
22+
headers: [
23+
{
24+
key: 'Cache-Control',
25+
value: 'public, max-age=86400',
26+
},
27+
],
28+
},
29+
{
30+
source: '/logo-dark.png',
31+
headers: [
32+
{
33+
key: 'Cache-Control',
34+
value: 'public, max-age=86400',
35+
},
36+
],
37+
},
38+
];
39+
},
1640
}
1741

1842
export default nextConfig

package.json

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"private": false,
55
"scripts": {
66
"dev": "next dev --turbo",
7+
"dev:webpack": "next dev",
78
"build": "next build",
89
"start": "next start",
910
"lint": "next lint"
@@ -58,7 +59,6 @@
5859
"flags": "^4.0.1",
5960
"framer-motion": "^12.23.22",
6061
"geist": "^1.5.1",
61-
"group-by.js": "link:core-js/features/object/group-by.js",
6262
"js-cookie": "^3.0.5",
6363
"lru-cache": "^11.2.2",
6464
"lucide-react": "^0.396.0",
@@ -94,6 +94,11 @@
9494
"path-to-regexp": "^6.3.0",
9595
"esbuild": "^0.25.9"
9696
},
97+
"pnpm": {
98+
"overrides": {
99+
"zod": "^3.25.76"
100+
}
101+
},
97102
"devDependencies": {
98103
"@swc/cli": "^0.7.8",
99104
"@swc/core": "^1.13.20",
@@ -106,12 +111,22 @@
106111
"@types/react-dom": "^18.3.7",
107112
"@types/react-syntax-highlighter": "^15.5.13",
108113
"@types/uuid": "^10.0.0",
114+
"@typescript-eslint/eslint-plugin": "^8.44.1",
115+
"@typescript-eslint/parser": "^8.44.1",
109116
"@vercel/node": "^2.15.10",
110117
"autoprefixer": "^10.4.21",
111-
"eslint": "^8.57.1",
112-
"eslint-config-next": "14.2.4",
118+
"eslint": "^9.15.0",
119+
"eslint-config-next": "15.1.1",
113120
"postcss": "^8.5.6",
114121
"tailwindcss": "^3.4.17",
115122
"typescript": "^5.9.2"
116-
}
123+
},
124+
"packageManager": "[email protected]",
125+
"browserslist": [
126+
"> 0.5%",
127+
"last 2 versions",
128+
"Firefox ESR",
129+
"not dead",
130+
"not IE 11"
131+
]
117132
}

0 commit comments

Comments
 (0)