diff --git a/src/interface/web/app/search/layout.tsx b/src/interface/web/app/search/layout.tsx
new file mode 100644
index 00000000..ed06f884
--- /dev/null
+++ b/src/interface/web/app/search/layout.tsx
@@ -0,0 +1,24 @@
+import type { Metadata } from "next";
+
+import "../globals.css";
+
+
+export const metadata: Metadata = {
+ title: "Khoj AI - Search",
+ description: "Search through all the documents you've shared with Khoj AI using natural language queries.",
+ icons: {
+ icon: '/static/favicon.ico',
+ },
+};
+
+export default function RootLayout({
+ children,
+}: Readonly<{
+ children: React.ReactNode;
+}>) {
+ return (
+
+ {children}
+
+ );
+}
diff --git a/src/interface/web/app/search/page.tsx b/src/interface/web/app/search/page.tsx
new file mode 100644
index 00000000..30be4f5d
--- /dev/null
+++ b/src/interface/web/app/search/page.tsx
@@ -0,0 +1,170 @@
+'use client'
+
+import { Input } from '@/components/ui/input';
+
+import { useAuthenticatedData } from '../common/auth';
+import { useEffect, useState } from 'react';
+import SidePanel from '../components/sidePanel/chatHistorySidePanel';
+import NavMenu from '../components/navMenu/navMenu';
+import styles from './search.module.css';
+import { ScrollArea } from '@/components/ui/scroll-area';
+import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card';
+import { Folder, FolderOpen, GithubLogo, LinkSimple, MagnifyingGlass, NoteBlank, NotionLogo } from '@phosphor-icons/react';
+
+interface AdditionalData {
+ file: string;
+ source: string;
+ compiled: string;
+ heading: string;
+}
+
+interface SearchResult {
+ type: string;
+ additional: AdditionalData;
+ entry: string;
+ score: number;
+ "corpus-id": string;
+}
+
+function getNoteTypeIcon(source: string) {
+ if (source === 'notion') {
+ return ;
+ }
+ if (source === 'github') {
+ return ;
+ }
+ return ;
+}
+
+function Note(note: SearchResult) {
+ const isFileNameURL = (note.additional.file || '').startsWith('http');
+ const fileName = isFileNameURL ? note.additional.heading : note.additional.file.split('/').pop();
+ console.log("note.additional.file", note.additional.file);
+ console.log("filename", fileName);
+ return (
+
+
+
+
+ {getNoteTypeIcon(note.additional.source)}
+
+
+
+ {fileName}
+
+
+
+
+ {note.entry}
+
+
+
+ {
+ isFileNameURL ?
+
+ {note.additional.file}
+
+ :
+
+ {note.additional.file}
+
+ }
+
+
+ );
+
+}
+
+export default function Search() {
+ const authenticatedData = useAuthenticatedData();
+ const [searchQuery, setSearchQuery] = useState('');
+ const [isMobileWidth, setIsMobileWidth] = useState(false);
+ const [title, setTitle] = useState('Search');
+ const [searchResults, setSearchResults] = useState([]);
+ const [searchResultsLoading, setSearchResultsLoading] = useState(false);
+
+ useEffect(() => {
+ setIsMobileWidth(window.innerWidth < 786);
+
+ window.addEventListener('resize', () => {
+ setIsMobileWidth(window.innerWidth < 786);
+ });
+
+ }, []);
+
+ useEffect(() => {
+ setTitle(isMobileWidth ? '' : 'Search');
+ }, [isMobileWidth]);
+
+ function search(query: string) {
+ if (searchResultsLoading) {
+ return;
+ }
+
+ if (!searchQuery.trim()) {
+ return;
+ }
+
+ const apiUrl = `/api/search?q=${encodeURIComponent(searchQuery)}&client=web`;
+ fetch(apiUrl, {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json',
+ }
+ }).then(response => response.json())
+ .then(data => {
+ setSearchResults(data);
+ setSearchResultsLoading(false);
+ }).catch((error) => {
+ console.error('Error:', error);
+ });
+ }
+
+ console.log('searchResults', searchResults);
+
+ return (
+
+
+
+
+
+
+
+ {
+ isMobileWidth &&
Search
+ }
+
+
+ setSearchQuery(e.target.value)}
+ type="search"
+ placeholder="Search Documents" />
+
+
+ {
+ searchResults.length > 0 &&
+
+
+ {
+ searchResults.map((result, index) => {
+ return (
+
+ );
+ })
+ }
+
+
+ }
+
+
+
+ );
+}
diff --git a/src/interface/web/app/search/search.module.css b/src/interface/web/app/search/search.module.css
new file mode 100644
index 00000000..b063fde6
--- /dev/null
+++ b/src/interface/web/app/search/search.module.css
@@ -0,0 +1,12 @@
+div.searchLayout {
+ display: grid;
+ grid-template-columns: auto 1fr;
+ gap: 1rem;
+ height: 100vh;
+}
+
+@media screen and (max-width: 768px) {
+ div.searchLayout {
+ gap: 0;
+ }
+}