Compare commits
No commits in common. "d468ecca7485fbab512266910c14cca5daf45c2d" and "186bd3c2ccfc916ef63041ab323ac795caa3ebc7" have entirely different histories.
d468ecca74
...
186bd3c2cc
29
.env.example
29
.env.example
@ -1,28 +1,5 @@
|
|||||||
# Strictly Server side Env variables
|
ANTHROPIC_API_KEY=sk-ant-api****
|
||||||
XAI_API_KEY=
|
|
||||||
UPSTASH_REDIS_REST_URL=
|
|
||||||
UPSTASH_REDIS_REST_TOKEN=
|
|
||||||
AVIATION_STACK_API_KEY=
|
|
||||||
SANDBOX_TEMPLATE_ID=
|
|
||||||
TMDB_API_KEY=
|
|
||||||
YT_ENDPOINT=
|
|
||||||
EXA_API_KEY=
|
|
||||||
TRIPADVISOR_API_KEY=
|
|
||||||
BLOB_READ_WRITE_TOKEN=
|
|
||||||
ELEVENLABS_API_KEY=
|
|
||||||
AZURE_TRANSLATOR_LOCATION=
|
|
||||||
AZURE_TRANSLATOR_KEY=
|
|
||||||
AZURE_RESOURCE_NAME=
|
|
||||||
AZURE_API_KEY=
|
|
||||||
MAPBOX_ACCESS_TOKEN=
|
|
||||||
FIRECRAWL_API_KEY=
|
|
||||||
TAVILY_API_KEY=tvly-****
|
TAVILY_API_KEY=tvly-****
|
||||||
OPENWEATHER_API_KEY=
|
GROQ_API_KEY=gsk_****
|
||||||
|
OPENWEATHER_API_KEY=***
|
||||||
E2B_API_KEY=e2b_****
|
E2B_API_KEY=e2b_****
|
||||||
GOOGLE_MAPS_API_KEY=
|
|
||||||
|
|
||||||
# Client side Env variables
|
|
||||||
NEXT_PUBLIC_POSTHOG_KEY=
|
|
||||||
NEXT_PUBLIC_POSTHOG_HOST=
|
|
||||||
NEXT_PUBLIC_MAPBOX_TOKEN=
|
|
||||||
NEXT_PUBLIC_GOOGLE_MAPS_API_KEY=
|
|
||||||
@ -1,4 +1,3 @@
|
|||||||
import { serverEnv } from '@/env/server';
|
|
||||||
import { del, list, ListBlobResult } from '@vercel/blob';
|
import { del, list, ListBlobResult } from '@vercel/blob';
|
||||||
import { NextRequest, NextResponse } from 'next/server';
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { NextResponse } from 'next/server';
|
import { NextResponse } from 'next/server';
|
||||||
import { generateObject } from 'ai';
|
import { generateObject } from 'ai';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
import { geolocation } from '@vercel/functions';
|
||||||
import { xai } from '@ai-sdk/xai';
|
import { xai } from '@ai-sdk/xai';
|
||||||
|
|
||||||
export interface TrendingQuery {
|
export interface TrendingQuery {
|
||||||
@ -15,7 +16,7 @@ interface RedditPost {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchGoogleTrends(): Promise<TrendingQuery[]> {
|
async function fetchGoogleTrends(countryCode: string = 'US'): Promise<TrendingQuery[]> {
|
||||||
const fetchTrends = async (geo: string): Promise<TrendingQuery[]> => {
|
const fetchTrends = async (geo: string): Promise<TrendingQuery[]> => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`https://trends.google.com/trends/trendingsearches/daily/rss?geo=${geo}`, {
|
const response = await fetch(`https://trends.google.com/trends/trendingsearches/daily/rss?geo=${geo}`, {
|
||||||
@ -61,7 +62,7 @@ async function fetchGoogleTrends(): Promise<TrendingQuery[]> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const trends = await fetchTrends("US");
|
const trends = await fetchTrends(countryCode);
|
||||||
|
|
||||||
return [ ...trends];
|
return [ ...trends];
|
||||||
}
|
}
|
||||||
@ -94,11 +95,11 @@ async function fetchRedditQuestions(): Promise<TrendingQuery[]> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchFromMultipleSources() {
|
async function fetchFromMultipleSources(countryCode: string) {
|
||||||
const [googleTrends,
|
const [googleTrends,
|
||||||
// redditQuestions
|
// redditQuestions
|
||||||
] = await Promise.all([
|
] = await Promise.all([
|
||||||
fetchGoogleTrends(),
|
fetchGoogleTrends(countryCode),
|
||||||
// fetchRedditQuestions(),
|
// fetchRedditQuestions(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -111,11 +112,11 @@ async function fetchFromMultipleSources() {
|
|||||||
|
|
||||||
export async function GET(req: Request) {
|
export async function GET(req: Request) {
|
||||||
try {
|
try {
|
||||||
const trends = await fetchFromMultipleSources();
|
const countryCode = geolocation(req).countryRegion ?? 'US';
|
||||||
|
const trends = await fetchFromMultipleSources(countryCode);
|
||||||
|
|
||||||
if (trends.length === 0) {
|
if (trends.length === 0) {
|
||||||
// Fallback queries if both sources fail
|
// Fallback queries if both sources fail
|
||||||
console.error('Both sources failed to fetch trends, returning fallback queries');
|
|
||||||
return NextResponse.json([
|
return NextResponse.json([
|
||||||
{
|
{
|
||||||
icon: 'sparkles',
|
icon: 'sparkles',
|
||||||
|
|||||||
@ -1,7 +1,16 @@
|
|||||||
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Instrument+Serif:wght@400&display=swap');
|
||||||
@tailwind base;
|
@tailwind base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--font-serif: "Instrument Serif", serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: var(--font-sans), sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
.homeBtn {
|
.homeBtn {
|
||||||
box-shadow: rgba(0, 0, 0, 0.4) 0px 2px 4px,
|
box-shadow: rgba(0, 0, 0, 0.4) 0px 2px 4px,
|
||||||
rgba(0, 0, 0, 0.3) 0px 7px 13px -3px, rgba(0, 0, 0, 0.2) 0px -3px 0px inset,
|
rgba(0, 0, 0, 0.3) 0px 7px 13px -3px, rgba(0, 0, 0, 0.2) 0px -3px 0px inset,
|
||||||
|
|||||||
@ -1,13 +1,12 @@
|
|||||||
import { Analytics } from "@vercel/analytics/react";
|
import "./globals.css";
|
||||||
import { GeistSans } from 'geist/font/sans';
|
|
||||||
import 'katex/dist/katex.min.css';
|
import 'katex/dist/katex.min.css';
|
||||||
import 'mapbox-gl/dist/mapbox-gl.css';
|
import 'mapbox-gl/dist/mapbox-gl.css';
|
||||||
import { Metadata, Viewport } from "next";
|
import { Metadata, Viewport } from "next";
|
||||||
import { Instrument_Serif } from 'next/font/google';
|
|
||||||
import { NuqsAdapter } from 'nuqs/adapters/next/app';
|
|
||||||
import { Toaster } from "sonner";
|
import { Toaster } from "sonner";
|
||||||
import "./globals.css";
|
import { Instrument_Serif } from 'next/font/google';
|
||||||
import { Providers } from './providers';
|
import { Analytics } from "@vercel/analytics/react";
|
||||||
|
import { Providers } from './providers'
|
||||||
|
import { GeistSans } from 'geist/font/sans';
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
metadataBase: new URL("https://mplx.run"),
|
metadataBase: new URL("https://mplx.run"),
|
||||||
@ -44,11 +43,7 @@ export const viewport: Viewport = {
|
|||||||
const instrumentSerif = Instrument_Serif({
|
const instrumentSerif = Instrument_Serif({
|
||||||
weight: "400",
|
weight: "400",
|
||||||
subsets: ["latin"],
|
subsets: ["latin"],
|
||||||
style: ['normal', 'italic'],
|
variable: "--font-serif"
|
||||||
variable: "--font-serif",
|
|
||||||
preload: true,
|
|
||||||
display: 'swap',
|
|
||||||
fallback: ['sans-serif'],
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export default function RootLayout({
|
export default function RootLayout({
|
||||||
@ -58,13 +53,11 @@ export default function RootLayout({
|
|||||||
}>) {
|
}>) {
|
||||||
return (
|
return (
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<body className={`${GeistSans.variable} ${instrumentSerif.variable} font-sans antialiased`}>
|
<body className={` ${GeistSans.className} ${instrumentSerif.className}`}>
|
||||||
<NuqsAdapter>
|
<Providers>
|
||||||
<Providers>
|
<Toaster position="top-center" richColors />
|
||||||
<Toaster position="top-center" richColors />
|
{children}
|
||||||
{children}
|
</Providers>
|
||||||
</Providers>
|
|
||||||
</NuqsAdapter>
|
|
||||||
<Analytics />
|
<Analytics />
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
264
app/page.tsx
264
app/page.tsx
@ -2,133 +2,137 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import 'katex/dist/katex.min.css';
|
import 'katex/dist/katex.min.css';
|
||||||
|
|
||||||
import { BorderTrail } from '@/components/core/border-trail';
|
import
|
||||||
import { TextShimmer } from '@/components/core/text-shimmer';
|
React,
|
||||||
import { FlightTracker } from '@/components/flight-tracker';
|
{
|
||||||
import { InstallPrompt } from '@/components/InstallPrompt';
|
useRef,
|
||||||
|
useCallback,
|
||||||
|
useState,
|
||||||
|
useEffect,
|
||||||
|
useMemo,
|
||||||
|
Suspense
|
||||||
|
} from 'react';
|
||||||
|
import ReactMarkdown from 'react-markdown';
|
||||||
|
import { useTheme } from 'next-themes';
|
||||||
|
import Marked, { ReactRenderer } from 'marked-react';
|
||||||
|
import Latex from 'react-latex-next';
|
||||||
|
import { useSearchParams } from 'next/navigation';
|
||||||
|
import { useChat } from 'ai/react';
|
||||||
|
import { ToolInvocation } from 'ai';
|
||||||
|
import { toast } from 'sonner';
|
||||||
|
import { motion, AnimatePresence } from 'framer-motion';
|
||||||
|
import Image from 'next/image';
|
||||||
|
import {
|
||||||
|
fetchMetadata,
|
||||||
|
generateSpeech,
|
||||||
|
suggestQuestions
|
||||||
|
} from './actions';
|
||||||
|
import { Wave } from "@foobar404/wave";
|
||||||
|
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
|
||||||
|
import { oneLight, oneDark } from 'react-syntax-highlighter/dist/esm/styles/prism';
|
||||||
|
import {
|
||||||
|
Sparkles,
|
||||||
|
ArrowRight,
|
||||||
|
Globe,
|
||||||
|
AlignLeft,
|
||||||
|
Copy,
|
||||||
|
Cloud,
|
||||||
|
Code,
|
||||||
|
Check,
|
||||||
|
Loader2,
|
||||||
|
User2,
|
||||||
|
Heart,
|
||||||
|
X,
|
||||||
|
MapPin,
|
||||||
|
Plus,
|
||||||
|
Download,
|
||||||
|
Flame,
|
||||||
|
Sun,
|
||||||
|
Pause,
|
||||||
|
Play,
|
||||||
|
TrendingUpIcon,
|
||||||
|
Calendar,
|
||||||
|
Calculator,
|
||||||
|
ChevronDown,
|
||||||
|
Edit2,
|
||||||
|
ChevronUp,
|
||||||
|
Moon,
|
||||||
|
Star,
|
||||||
|
YoutubeIcon,
|
||||||
|
LucideIcon,
|
||||||
|
FileText,
|
||||||
|
Book,
|
||||||
|
ExternalLink,
|
||||||
|
Building,
|
||||||
|
Users,
|
||||||
|
Brain,
|
||||||
|
TrendingUp,
|
||||||
|
Plane,
|
||||||
|
Film,
|
||||||
|
Tv,
|
||||||
|
ListTodo
|
||||||
|
} from 'lucide-react';
|
||||||
|
import {
|
||||||
|
HoverCard,
|
||||||
|
HoverCardContent,
|
||||||
|
HoverCardTrigger,
|
||||||
|
} from "@/components/ui/hover-card";
|
||||||
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
|
||||||
|
import {
|
||||||
|
Accordion,
|
||||||
|
AccordionContent,
|
||||||
|
AccordionItem,
|
||||||
|
AccordionTrigger,
|
||||||
|
} from "@/components/ui/accordion";
|
||||||
|
import {
|
||||||
|
Tooltip,
|
||||||
|
TooltipContent,
|
||||||
|
TooltipProvider,
|
||||||
|
TooltipTrigger,
|
||||||
|
} from "@/components/ui/tooltip"
|
||||||
|
import { Input } from '@/components/ui/input';
|
||||||
|
import { Button } from '@/components/ui/button';
|
||||||
|
import { Badge } from '@/components/ui/badge';
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/components/ui/card";
|
||||||
|
import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from "@/components/ui/sheet";
|
||||||
|
import { Drawer, DrawerContent, DrawerHeader, DrawerTitle, DrawerTrigger } from "@/components/ui/drawer";
|
||||||
|
import { GitHubLogoIcon, TextIcon } from '@radix-ui/react-icons';
|
||||||
|
import Link from 'next/link';
|
||||||
|
import { Dialog, DialogContent } from "@/components/ui/dialog";
|
||||||
|
import { Carousel, CarouselContent, CarouselItem } from "@/components/ui/carousel";
|
||||||
|
import { cn, SearchGroupId } from '@/lib/utils';
|
||||||
|
import {
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableRow,
|
||||||
|
} from "@/components/ui/table";
|
||||||
|
import Autoplay from 'embla-carousel-autoplay';
|
||||||
|
import FormComponent from '@/components/ui/form-component';
|
||||||
|
import WeatherChart from '@/components/weather-chart';
|
||||||
import InteractiveChart from '@/components/interactive-charts';
|
import InteractiveChart from '@/components/interactive-charts';
|
||||||
import { MapComponent, MapContainer } from '@/components/map-components';
|
import { MapComponent, MapContainer } from '@/components/map-components';
|
||||||
import TMDBResult from '@/components/movie-info';
|
|
||||||
import MultiSearch from '@/components/multi-search';
|
import MultiSearch from '@/components/multi-search';
|
||||||
import NearbySearchMapView from '@/components/nearby-search-map-view';
|
|
||||||
import TrendingResults from '@/components/trending-tv-movies-results';
|
|
||||||
import {
|
|
||||||
Accordion,
|
|
||||||
AccordionContent,
|
|
||||||
AccordionItem,
|
|
||||||
AccordionTrigger,
|
|
||||||
} from "@/components/ui/accordion";
|
|
||||||
import { Badge } from '@/components/ui/badge';
|
|
||||||
import { Button } from '@/components/ui/button';
|
|
||||||
import {
|
|
||||||
Card,
|
|
||||||
CardContent,
|
|
||||||
CardHeader,
|
|
||||||
CardTitle,
|
|
||||||
} from "@/components/ui/card";
|
|
||||||
import { Carousel, CarouselContent, CarouselItem } from "@/components/ui/carousel";
|
|
||||||
import { Dialog, DialogContent } from "@/components/ui/dialog";
|
|
||||||
import { Drawer, DrawerContent, DrawerHeader, DrawerTitle, DrawerTrigger } from "@/components/ui/drawer";
|
|
||||||
import FormComponent from '@/components/ui/form-component';
|
|
||||||
import {
|
|
||||||
HoverCard,
|
|
||||||
HoverCardContent,
|
|
||||||
HoverCardTrigger,
|
|
||||||
} from "@/components/ui/hover-card";
|
|
||||||
import { Input } from '@/components/ui/input';
|
|
||||||
import { Separator } from '@/components/ui/separator';
|
|
||||||
import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from "@/components/ui/sheet";
|
|
||||||
import {
|
|
||||||
Table,
|
|
||||||
TableBody,
|
|
||||||
TableCell,
|
|
||||||
TableRow,
|
|
||||||
} from "@/components/ui/table";
|
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
|
||||||
import {
|
|
||||||
Tooltip,
|
|
||||||
TooltipContent,
|
|
||||||
TooltipProvider,
|
|
||||||
TooltipTrigger,
|
|
||||||
} from "@/components/ui/tooltip";
|
|
||||||
import WeatherChart from '@/components/weather-chart';
|
|
||||||
import { useMediaQuery } from '@/hooks/use-media-query';
|
|
||||||
import { cn, SearchGroupId } from '@/lib/utils';
|
|
||||||
import { Wave } from "@foobar404/wave";
|
|
||||||
import { CurrencyDollar, Flag, RoadHorizon, SoccerBall, TennisBall, XLogo } from '@phosphor-icons/react';
|
import { CurrencyDollar, Flag, RoadHorizon, SoccerBall, TennisBall, XLogo } from '@phosphor-icons/react';
|
||||||
import { GitHubLogoIcon, TextIcon } from '@radix-ui/react-icons';
|
import { BorderTrail } from '@/components/core/border-trail';
|
||||||
import { ToolInvocation } from 'ai';
|
import { TextShimmer } from '@/components/core/text-shimmer';
|
||||||
import { useChat } from 'ai/react';
|
|
||||||
import Autoplay from 'embla-carousel-autoplay';
|
|
||||||
import { AnimatePresence, motion } from 'framer-motion';
|
|
||||||
import { GeistMono } from 'geist/font/mono';
|
|
||||||
import {
|
|
||||||
AlignLeft,
|
|
||||||
ArrowRight,
|
|
||||||
Book,
|
|
||||||
Brain,
|
|
||||||
Building,
|
|
||||||
Calculator,
|
|
||||||
Calendar,
|
|
||||||
Check,
|
|
||||||
ChevronDown,
|
|
||||||
ChevronUp,
|
|
||||||
Cloud,
|
|
||||||
Code,
|
|
||||||
Copy,
|
|
||||||
Download,
|
|
||||||
Edit2,
|
|
||||||
ExternalLink,
|
|
||||||
FileText,
|
|
||||||
Film,
|
|
||||||
Flame,
|
|
||||||
Globe,
|
|
||||||
Heart,
|
|
||||||
ListTodo,
|
|
||||||
Loader2,
|
|
||||||
LucideIcon,
|
|
||||||
MapPin,
|
|
||||||
Moon,
|
|
||||||
Pause,
|
|
||||||
Plane,
|
|
||||||
Play,
|
|
||||||
Plus,
|
|
||||||
Sparkles,
|
|
||||||
Sun,
|
|
||||||
TrendingUp,
|
|
||||||
TrendingUpIcon,
|
|
||||||
Tv,
|
|
||||||
User2,
|
|
||||||
Users,
|
|
||||||
X,
|
|
||||||
YoutubeIcon
|
|
||||||
} from 'lucide-react';
|
|
||||||
import Marked, { ReactRenderer } from 'marked-react';
|
|
||||||
import { useTheme } from 'next-themes';
|
|
||||||
import Image from 'next/image';
|
|
||||||
import Link from 'next/link';
|
|
||||||
import { parseAsString, useQueryState } from 'nuqs';
|
|
||||||
import React, {
|
|
||||||
Suspense,
|
|
||||||
useCallback,
|
|
||||||
useEffect,
|
|
||||||
useMemo,
|
|
||||||
useRef,
|
|
||||||
useState
|
|
||||||
} from 'react';
|
|
||||||
import Latex from 'react-latex-next';
|
|
||||||
import ReactMarkdown from 'react-markdown';
|
|
||||||
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
|
|
||||||
import { atomDark, vs } from 'react-syntax-highlighter/dist/cjs/styles/prism';
|
|
||||||
import { oneDark, oneLight } from 'react-syntax-highlighter/dist/esm/styles/prism';
|
|
||||||
import { Tweet } from 'react-tweet';
|
import { Tweet } from 'react-tweet';
|
||||||
import { toast } from 'sonner';
|
import NearbySearchMapView from '@/components/nearby-search-map-view';
|
||||||
import {
|
import { Separator } from '@/components/ui/separator';
|
||||||
fetchMetadata,
|
|
||||||
generateSpeech,
|
|
||||||
suggestQuestions
|
|
||||||
} from './actions';
|
|
||||||
import { TrendingQuery } from './api/trending/route';
|
import { TrendingQuery } from './api/trending/route';
|
||||||
|
import { FlightTracker } from '@/components/flight-tracker';
|
||||||
|
import { InstallPrompt } from '@/components/InstallPrompt';
|
||||||
|
import { atomDark } from 'react-syntax-highlighter/dist/cjs/styles/prism';
|
||||||
|
import { vs } from 'react-syntax-highlighter/dist/cjs/styles/prism';
|
||||||
|
import { useMediaQuery } from '@/hooks/use-media-query';
|
||||||
|
import TMDBResult from '@/components/movie-info';
|
||||||
|
import TrendingResults from '@/components/trending-tv-movies-results';
|
||||||
|
import { GeistMono } from 'geist/font/mono';
|
||||||
|
|
||||||
export const maxDuration = 60;
|
export const maxDuration = 60;
|
||||||
|
|
||||||
@ -559,15 +563,12 @@ const SponsorDialog = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const HomeContent = () => {
|
const HomeContent = () => {
|
||||||
const [query] = useQueryState('query', parseAsString.withDefault(''))
|
const searchParams = useSearchParams();
|
||||||
const [q] = useQueryState('q', parseAsString.withDefault(''))
|
|
||||||
const [model] = useQueryState('model', parseAsString.withDefault('grok-2-1212'))
|
|
||||||
|
|
||||||
// Memoize initial values to prevent re-calculation
|
// Memoize initial values to prevent re-calculation
|
||||||
const initialState = useMemo(() => ({
|
const initialState = useMemo(() => ({
|
||||||
query: query || q,
|
query: searchParams.get('query') || searchParams.get('q') || '',
|
||||||
model: model
|
model: searchParams.get('model') || 'grok-2-1212'
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}), []); // Empty dependency array as we only want this on mount
|
}), []); // Empty dependency array as we only want this on mount
|
||||||
|
|
||||||
const lastSubmittedQueryRef = useRef(initialState.query);
|
const lastSubmittedQueryRef = useRef(initialState.query);
|
||||||
@ -698,7 +699,6 @@ const HomeContent = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
fetchTrending();
|
fetchTrending();
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const ThemeToggle: React.FC = () => {
|
const ThemeToggle: React.FC = () => {
|
||||||
@ -892,11 +892,10 @@ Grok 2 models are now available for you to try out.
|
|||||||
const waveRef = useRef<Wave | null>(null);
|
const waveRef = useRef<Wave | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const _audioRef = audioRef.current
|
|
||||||
return () => {
|
return () => {
|
||||||
if (_audioRef) {
|
if (audioRef.current) {
|
||||||
_audioRef.pause();
|
audioRef.current.pause();
|
||||||
_audioRef.src = '';
|
audioRef.current.src = '';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
@ -2589,7 +2588,6 @@ Grok 2 models are now available for you to try out.
|
|||||||
<SuggestionCards
|
<SuggestionCards
|
||||||
trendingQueries={trendingQueries}
|
trendingQueries={trendingQueries}
|
||||||
/>
|
/>
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
), [trendingQueries]);
|
), [trendingQueries]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -1,60 +0,0 @@
|
|||||||
version: '3.8'
|
|
||||||
|
|
||||||
services:
|
|
||||||
web:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
ports:
|
|
||||||
- "3000:3000"
|
|
||||||
environment:
|
|
||||||
- NODE_ENV=production
|
|
||||||
- XAI_API_KEY=${XAI_API_KEY}
|
|
||||||
- UPSTASH_REDIS_REST_URL=${UPSTASH_REDIS_REST_URL}
|
|
||||||
- UPSTASH_REDIS_REST_TOKEN=${UPSTASH_REDIS_REST_TOKEN}
|
|
||||||
- ELEVENLABS_API_KEY=${ELEVENLABS_API_KEY}
|
|
||||||
- TAVILY_API_KEY=${TAVILY_API_KEY}
|
|
||||||
- EXA_API_KEY=${EXA_API_KEY}
|
|
||||||
- TMDB_API_KEY=${TMDB_API_KEY}
|
|
||||||
- YT_ENDPOINT=${YT_ENDPOINT}
|
|
||||||
- FIRECRAWL_API_KEY=${FIRECRAWL_API_KEY}
|
|
||||||
- OPENWEATHER_API_KEY=${OPENWEATHER_API_KEY}
|
|
||||||
- SANDBOX_TEMPLATE_ID=${SANDBOX_TEMPLATE_ID}
|
|
||||||
- GOOGLE_MAPS_API_KEY=${GOOGLE_MAPS_API_KEY}
|
|
||||||
- MAPBOX_ACCESS_TOKEN=${MAPBOX_ACCESS_TOKEN}
|
|
||||||
- AZURE_TRANSLATOR_KEY=${AZURE_TRANSLATOR_KEY}
|
|
||||||
- AZURE_TRANSLATOR_LOCATION=${AZURE_TRANSLATOR_LOCATION}
|
|
||||||
- AZURE_RESOURCE_NAME=${AZURE_RESOURCE_NAME}
|
|
||||||
- AZURE_API_KEY=${AZURE_API_KEY}
|
|
||||||
- TRIPADVISOR_API_KEY=${TRIPADVISOR_API_KEY}
|
|
||||||
- AVIATION_STACK_API_KEY=${AVIATION_STACK_API_KEY}
|
|
||||||
- CRON_SECRET=${CRON_SECRET}
|
|
||||||
- BLOB_READ_WRITE_TOKEN=${BLOB_READ_WRITE_TOKEN}
|
|
||||||
- NEXT_PUBLIC_MAPBOX_TOKEN=${NEXT_PUBLIC_MAPBOX_TOKEN}
|
|
||||||
- NEXT_PUBLIC_POSTHOG_KEY=${NEXT_PUBLIC_POSTHOG_KEY}
|
|
||||||
- NEXT_PUBLIC_POSTHOG_HOST=${NEXT_PUBLIC_POSTHOG_HOST}
|
|
||||||
- NEXT_PUBLIC_GOOGLE_MAPS_API_KEY=${NEXT_PUBLIC_GOOGLE_MAPS_API_KEY}
|
|
||||||
volumes:
|
|
||||||
- .:/app
|
|
||||||
- /app/node_modules
|
|
||||||
depends_on:
|
|
||||||
- code-interpreter
|
|
||||||
|
|
||||||
code-interpreter:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: e2b.Dockerfile
|
|
||||||
environment:
|
|
||||||
- E2B_API_KEY=${E2B_API_KEY}
|
|
||||||
volumes:
|
|
||||||
- ./certificates:/app/certificates
|
|
||||||
|
|
||||||
redis:
|
|
||||||
image: redis:alpine
|
|
||||||
ports:
|
|
||||||
- "6379:6379"
|
|
||||||
volumes:
|
|
||||||
- redis_data:/data
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
redis_data:
|
|
||||||
3
env/client.ts
vendored
3
env/client.ts
vendored
@ -7,13 +7,10 @@ export const clientEnv = createEnv({
|
|||||||
NEXT_PUBLIC_MAPBOX_TOKEN: z.string().min(1),
|
NEXT_PUBLIC_MAPBOX_TOKEN: z.string().min(1),
|
||||||
NEXT_PUBLIC_POSTHOG_KEY: z.string().min(1),
|
NEXT_PUBLIC_POSTHOG_KEY: z.string().min(1),
|
||||||
NEXT_PUBLIC_POSTHOG_HOST: z.string().min(1).url(),
|
NEXT_PUBLIC_POSTHOG_HOST: z.string().min(1).url(),
|
||||||
NEXT_PUBLIC_GOOGLE_MAPS_API_KEY: z.string().min(1),
|
|
||||||
},
|
},
|
||||||
runtimeEnv: {
|
runtimeEnv: {
|
||||||
NEXT_PUBLIC_MAPBOX_TOKEN: process.env.NEXT_PUBLIC_MAPBOX_TOKEN,
|
NEXT_PUBLIC_MAPBOX_TOKEN: process.env.NEXT_PUBLIC_MAPBOX_TOKEN,
|
||||||
NEXT_PUBLIC_POSTHOG_KEY: process.env.NEXT_PUBLIC_POSTHOG_KEY,
|
NEXT_PUBLIC_POSTHOG_KEY: process.env.NEXT_PUBLIC_POSTHOG_KEY,
|
||||||
NEXT_PUBLIC_POSTHOG_HOST: process.env.NEXT_PUBLIC_POSTHOG_HOST,
|
NEXT_PUBLIC_POSTHOG_HOST: process.env.NEXT_PUBLIC_POSTHOG_HOST,
|
||||||
NEXT_PUBLIC_GOOGLE_MAPS_API_KEY: process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
6
env/server.ts
vendored
6
env/server.ts
vendored
@ -4,9 +4,6 @@ import { z } from 'zod'
|
|||||||
|
|
||||||
export const serverEnv = createEnv({
|
export const serverEnv = createEnv({
|
||||||
server: {
|
server: {
|
||||||
XAI_API_KEY: z.string().min(1),
|
|
||||||
UPSTASH_REDIS_REST_URL: z.string().min(1).url(),
|
|
||||||
UPSTASH_REDIS_REST_TOKEN: z.string().min(1),
|
|
||||||
ELEVENLABS_API_KEY: z.string().min(1),
|
ELEVENLABS_API_KEY: z.string().min(1),
|
||||||
TAVILY_API_KEY: z.string().min(1),
|
TAVILY_API_KEY: z.string().min(1),
|
||||||
EXA_API_KEY: z.string().min(1),
|
EXA_API_KEY: z.string().min(1),
|
||||||
@ -19,12 +16,9 @@ export const serverEnv = createEnv({
|
|||||||
MAPBOX_ACCESS_TOKEN: z.string().min(1),
|
MAPBOX_ACCESS_TOKEN: z.string().min(1),
|
||||||
AZURE_TRANSLATOR_KEY: z.string().min(1),
|
AZURE_TRANSLATOR_KEY: z.string().min(1),
|
||||||
AZURE_TRANSLATOR_LOCATION: z.string().min(1),
|
AZURE_TRANSLATOR_LOCATION: z.string().min(1),
|
||||||
AZURE_RESOURCE_NAME: z.string().min(1),
|
|
||||||
AZURE_API_KEY: z.string().min(1),
|
|
||||||
TRIPADVISOR_API_KEY: z.string().min(1),
|
TRIPADVISOR_API_KEY: z.string().min(1),
|
||||||
AVIATION_STACK_API_KEY: z.string().min(1),
|
AVIATION_STACK_API_KEY: z.string().min(1),
|
||||||
CRON_SECRET: z.string().min(1),
|
CRON_SECRET: z.string().min(1),
|
||||||
BLOB_READ_WRITE_TOKEN: z.string().min(1),
|
|
||||||
},
|
},
|
||||||
experimental__runtimeEnv: process.env,
|
experimental__runtimeEnv: process.env,
|
||||||
})
|
})
|
||||||
|
|||||||
164
next.config.mjs
164
next.config.mjs
@ -9,86 +9,86 @@ jiti.import('./env/client')
|
|||||||
|
|
||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
transpilePackages: ["geist"],
|
transpilePackages: ['geist'],
|
||||||
async headers() {
|
async headers() {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
source: '/(.*)',
|
source: '/(.*)',
|
||||||
headers: [
|
headers: [
|
||||||
{
|
{
|
||||||
key: 'X-Content-Type-Options',
|
key: 'X-Content-Type-Options',
|
||||||
value: 'nosniff',
|
value: 'nosniff',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'X-Frame-Options',
|
key: 'X-Frame-Options',
|
||||||
value: 'DENY',
|
value: 'DENY',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'Referrer-Policy',
|
key: 'Referrer-Policy',
|
||||||
value: 'strict-origin-when-cross-origin',
|
value: 'strict-origin-when-cross-origin',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
images: {
|
images: {
|
||||||
dangerouslyAllowSVG: true,
|
dangerouslyAllowSVG: true,
|
||||||
remotePatterns: [
|
remotePatterns: [
|
||||||
{
|
{
|
||||||
protocol: 'https',
|
protocol: 'https',
|
||||||
hostname: 'www.google.com',
|
hostname: 'www.google.com',
|
||||||
port: '',
|
port: '',
|
||||||
pathname: '/s2/favicons',
|
pathname: '/s2/favicons',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
protocol: 'https',
|
protocol: 'https',
|
||||||
hostname: 'api.producthunt.com',
|
hostname: 'api.producthunt.com',
|
||||||
port: '',
|
port: '',
|
||||||
pathname: '/widgets/embed-image/v1/featured.svg',
|
pathname: '/widgets/embed-image/v1/featured.svg',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
protocol: 'https',
|
protocol: 'https',
|
||||||
hostname: 'metwm7frkvew6tn1.public.blob.vercel-storage.com',
|
hostname: 'metwm7frkvew6tn1.public.blob.vercel-storage.com',
|
||||||
port: '',
|
port: '',
|
||||||
pathname: "**"
|
pathname: '**',
|
||||||
},
|
},
|
||||||
// upload.wikimedia.org
|
// upload.wikimedia.org
|
||||||
{
|
{
|
||||||
protocol: 'https',
|
protocol: 'https',
|
||||||
hostname: 'upload.wikimedia.org',
|
hostname: 'upload.wikimedia.org',
|
||||||
port: '',
|
port: '',
|
||||||
pathname: '**'
|
pathname: '**',
|
||||||
},
|
},
|
||||||
// media.theresanaiforthat.com
|
// media.theresanaiforthat.com
|
||||||
{
|
{
|
||||||
protocol: 'https',
|
protocol: 'https',
|
||||||
hostname: 'media.theresanaiforthat.com',
|
hostname: 'media.theresanaiforthat.com',
|
||||||
port: '',
|
port: '',
|
||||||
pathname: '**'
|
pathname: '**',
|
||||||
},
|
},
|
||||||
// www.uneed.best
|
// www.uneed.best
|
||||||
{
|
{
|
||||||
protocol: 'https',
|
protocol: 'https',
|
||||||
hostname: 'www.uneed.best',
|
hostname: 'www.uneed.best',
|
||||||
port: '',
|
port: '',
|
||||||
pathname: '**'
|
pathname: '**',
|
||||||
},
|
},
|
||||||
// image.tmdb.org
|
// image.tmdb.org
|
||||||
{
|
{
|
||||||
protocol: 'https',
|
protocol: 'https',
|
||||||
hostname: 'image.tmdb.org',
|
hostname: 'image.tmdb.org',
|
||||||
port: '',
|
port: '',
|
||||||
pathname: '/t/p/original/**'
|
pathname: '/t/p/original/**',
|
||||||
},
|
},
|
||||||
// image.tmdb.org
|
// image.tmdb.org
|
||||||
{
|
{
|
||||||
protocol: 'https',
|
protocol: 'https',
|
||||||
hostname: 'image.tmdb.org',
|
hostname: 'image.tmdb.org',
|
||||||
port: '',
|
port: '',
|
||||||
pathname: '/**'
|
pathname: '/**',
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
|
|
||||||
export default nextConfig;
|
export default nextConfig
|
||||||
|
|||||||
@ -64,7 +64,6 @@
|
|||||||
"motion": "^11.13.5",
|
"motion": "^11.13.5",
|
||||||
"next": "^14.2.21",
|
"next": "^14.2.21",
|
||||||
"next-themes": "^0.3.0",
|
"next-themes": "^0.3.0",
|
||||||
"nuqs": "^2.3.0",
|
|
||||||
"openai": "^4.56.0",
|
"openai": "^4.56.0",
|
||||||
"posthog-js": "^1.202.2",
|
"posthog-js": "^1.202.2",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
|
|||||||
@ -173,9 +173,6 @@ importers:
|
|||||||
next-themes:
|
next-themes:
|
||||||
specifier: ^0.3.0
|
specifier: ^0.3.0
|
||||||
version: 0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
version: 0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
nuqs:
|
|
||||||
specifier: ^2.3.0
|
|
||||||
version: 2.3.0(next@14.2.21(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
|
|
||||||
openai:
|
openai:
|
||||||
specifier: ^4.56.0
|
specifier: ^4.56.0
|
||||||
version: 4.67.2(zod@3.24.1)
|
version: 4.67.2(zod@3.24.1)
|
||||||
@ -2789,9 +2786,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
|
resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
|
||||||
engines: {node: '>=16 || 14 >=14.17'}
|
engines: {node: '>=16 || 14 >=14.17'}
|
||||||
|
|
||||||
mitt@3.0.1:
|
|
||||||
resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==}
|
|
||||||
|
|
||||||
motion-dom@11.13.0:
|
motion-dom@11.13.0:
|
||||||
resolution: {integrity: sha512-Oc1MLGJQ6nrvXccXA89lXtOqFyBmvHtaDcTRGT66o8Czl7nuA8BeHAd9MQV1pQKX0d2RHFBFaw5g3k23hQJt0w==}
|
resolution: {integrity: sha512-Oc1MLGJQ6nrvXccXA89lXtOqFyBmvHtaDcTRGT66o8Czl7nuA8BeHAd9MQV1pQKX0d2RHFBFaw5g3k23hQJt0w==}
|
||||||
|
|
||||||
@ -2883,24 +2877,6 @@ packages:
|
|||||||
nth-check@2.1.1:
|
nth-check@2.1.1:
|
||||||
resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
|
resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
|
||||||
|
|
||||||
nuqs@2.3.0:
|
|
||||||
resolution: {integrity: sha512-ChS56bJZdaTQzCJb6jPel6cIHYh8/V/GSIjZoIe5yAssGdcrVaBFBgzHfJW6IewbR6yc1Zch2CmGsdgztR+xmA==}
|
|
||||||
peerDependencies:
|
|
||||||
'@remix-run/react': '>=2'
|
|
||||||
next: '>=14.2.0'
|
|
||||||
react: '>=18.2.0 || ^19.0.0-0'
|
|
||||||
react-router: ^7
|
|
||||||
react-router-dom: ^6 || ^7
|
|
||||||
peerDependenciesMeta:
|
|
||||||
'@remix-run/react':
|
|
||||||
optional: true
|
|
||||||
next:
|
|
||||||
optional: true
|
|
||||||
react-router:
|
|
||||||
optional: true
|
|
||||||
react-router-dom:
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
object-assign@4.1.1:
|
object-assign@4.1.1:
|
||||||
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
|
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@ -6759,8 +6735,6 @@ snapshots:
|
|||||||
|
|
||||||
minipass@7.1.2: {}
|
minipass@7.1.2: {}
|
||||||
|
|
||||||
mitt@3.0.1: {}
|
|
||||||
|
|
||||||
motion-dom@11.13.0: {}
|
motion-dom@11.13.0: {}
|
||||||
|
|
||||||
motion-utils@11.13.0: {}
|
motion-utils@11.13.0: {}
|
||||||
@ -6834,13 +6808,6 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
boolbase: 1.0.0
|
boolbase: 1.0.0
|
||||||
|
|
||||||
nuqs@2.3.0(next@14.2.21(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1):
|
|
||||||
dependencies:
|
|
||||||
mitt: 3.0.1
|
|
||||||
react: 18.3.1
|
|
||||||
optionalDependencies:
|
|
||||||
next: 14.2.21(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
|
||||||
|
|
||||||
object-assign@4.1.1: {}
|
object-assign@4.1.1: {}
|
||||||
|
|
||||||
object-hash@3.0.0: {}
|
object-hash@3.0.0: {}
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import type { Config } from "tailwindcss";
|
import type { Config } from "tailwindcss";
|
||||||
import { fontFamily } from 'tailwindcss/defaultTheme';
|
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
darkMode: ["class"],
|
darkMode: ["class"],
|
||||||
@ -24,9 +23,9 @@ const config = {
|
|||||||
'screen-small': '100svh',
|
'screen-small': '100svh',
|
||||||
},
|
},
|
||||||
fontFamily: {
|
fontFamily: {
|
||||||
sans: ['var(--font-geist-sans)', ...fontFamily.sans],
|
sans: ['var(--font-geist-sans)'],
|
||||||
serif: ['var(--font-serif)', ...fontFamily.serif],
|
serif: ['var(--font-serif)'],
|
||||||
mono: ['var(--font-geist-mono)', ...fontFamily.mono],
|
mono: ['var(--font-geist-mono)'],
|
||||||
},
|
},
|
||||||
colors: {
|
colors: {
|
||||||
border: "hsl(var(--border))",
|
border: "hsl(var(--border))",
|
||||||
@ -88,11 +87,7 @@ const config = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [require("tailwindcss-animate"), require("@tailwindcss/typography"),require("tailwind-scrollbar")],
|
||||||
require("tailwindcss-animate"),
|
|
||||||
require("@tailwindcss/typography"),
|
|
||||||
require("tailwind-scrollbar")
|
|
||||||
],
|
|
||||||
} satisfies Config
|
} satisfies Config
|
||||||
|
|
||||||
export default config
|
export default config
|
||||||
Loading…
Reference in New Issue
Block a user