aboutsummaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorDhravya Shah <[email protected]>2024-07-26 12:02:20 -0500
committerGitHub <[email protected]>2024-07-26 12:02:20 -0500
commit650237195fd07ff0e186e8a1808e02e31a016d37 (patch)
tree16d8afcd9f22b002284af092d7f50ca735f25230 /apps
parentMerge pull request #171 from JedPattersonn/jed/fix-breadcrumb (diff)
parentcatch (diff)
downloadsupermemory-650237195fd07ff0e186e8a1808e02e31a016d37.tar.xz
supermemory-650237195fd07ff0e186e8a1808e02e31a016d37.zip
Merge pull request #163 from aryasaatvik/pnpm
pnpm
Diffstat (limited to 'apps')
-rw-r--r--apps/cf-ai-backend/package.json8
-rw-r--r--apps/extension/content/ContentApp.tsx792
-rw-r--r--apps/web/.eslintrc.js3
-rw-r--r--apps/web/app/(auth)/layout.tsx14
-rw-r--r--apps/web/app/(auth)/onboarding/page.tsx6
-rw-r--r--apps/web/app/(dash)/home/filterSpaces.tsx4
-rw-r--r--apps/web/app/(landing)/Features/generating.tsx20
-rw-r--r--apps/web/app/(landing)/Features/index.tsx426
-rw-r--r--apps/web/app/(landing)/Showcase.tsx40
-rw-r--r--apps/web/app/actions/doers.ts18
-rw-r--r--apps/web/app/api/store/route.ts20
-rw-r--r--apps/web/package.json33
12 files changed, 698 insertions, 686 deletions
diff --git a/apps/cf-ai-backend/package.json b/apps/cf-ai-backend/package.json
index fee0c0d8..2b83cc93 100644
--- a/apps/cf-ai-backend/package.json
+++ b/apps/cf-ai-backend/package.json
@@ -12,6 +12,10 @@
},
"license": "MIT",
"dependencies": {
- "@hono/zod-validator": "^0.2.1"
- }
+ "@hono/zod-validator": "^0.2.1",
+ "hono": "^4.5.1"
+ },
+ "devDependencies": {
+ "@cloudflare/workers-types": "^4.20240614.0"
+ }
}
diff --git a/apps/extension/content/ContentApp.tsx b/apps/extension/content/ContentApp.tsx
index 89a3a635..c0339897 100644
--- a/apps/extension/content/ContentApp.tsx
+++ b/apps/extension/content/ContentApp.tsx
@@ -31,400 +31,400 @@ export default function ContentApp({
token: string | undefined;
shadowRoot: ShadowRoot;
}) {
- const [hover, setHover] = useState(false);
-
- const { toast } = useToast();
-
- const [loading, setLoading] = useState(false);
-
- const [webNote, setWebNote] = useState<string>("");
-
- const [importedCount, setImportedCount] = useState(0);
- const [isImporting, setIsImporting] = useState(false);
- const [importDone, setImportDone] = useState(false);
-
- const [portalContainer, setPortalContainer] = useState<HTMLElement | null>(
- null,
- );
- const [isPopoverOpen, setIsPopoverOpen] = useState(false);
- const [isPopover2Open, setIsPopover2Open] = useState(false);
-
- const [spacesOptions, setSpacesOptions] = useState<
- { id: number; name: string }[]
- >([]);
- const [selectedSpace, setSelectedSpace] = useState<string>();
-
- const [userNotLoggedIn, setUserNotLoggedIn] = useState(false);
-
- const showLoginToast = async () => {
- setUserNotLoggedIn(true);
-
- const NOSHOW_TOAST = ["accounts.google.com", "supermemory.ai"];
-
- const noLoginWarning = await chrome.storage.local.get("noLoginWarning");
- if (Object.keys(noLoginWarning).length > 0) {
- return;
- }
-
- if (!NOSHOW_TOAST.includes(window.location.host)) {
- const t = toast({
- title: "Please login to supermemory.ai to use this extension.",
- action: (
- <div className="flex flex-col gap-2">
- <button
- onClick={() =>
- window.open("https://supermemory.ai/signin", "_blank")
- }
- >
- Login
- </button>
-
- <button
- className="text-xs"
- onClick={async () => {
- await chrome.storage.local.set({
- noLoginWarning: true,
- });
- t.dismiss();
- }}
- >
- Ignore
- </button>
- </div>
- ),
- });
- }
- };
-
- useEffect(() => {
- document.addEventListener("mousemove", (e) => {
- const percentageX = (e.clientX / window.innerWidth) * 100;
- const percentageY = (e.clientY / window.innerHeight) * 100;
-
- if (percentageX > 75 && percentageY > 75) {
- setHover(true);
- } else {
- setHover(false);
- }
- });
-
- const getUserData = () => {
- chrome.runtime.sendMessage({ type: "getJwt" });
- };
-
- getUserData();
-
- chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
- if (request.type === "import-update") {
- setIsImporting(true);
- setImportedCount(request.importedCount);
- }
-
- if (request.type === "import-done") {
- setIsImporting(false);
- setImportDone(true);
- }
-
- if (request.type === "supermemory-message") {
- toast({
- title: request.message,
- });
- }
- });
-
- const portalDiv = document.createElement("div");
- portalDiv.id = "popover-portal";
- shadowRoot.appendChild(portalDiv);
- setPortalContainer(portalDiv);
-
- return () => {
- document.removeEventListener("mousemove", () => {});
- };
- }, []);
-
- const getSpaces = async () => {
- const response = await fetch(`${BACKEND_URL}/api/spaces`, {
- headers: {
- Authorization: `Bearer ${token}`,
- },
- });
-
- if (response.status === 401) {
- showLoginToast();
- return;
- }
-
- try {
- const data = await response.json();
- setSpacesOptions(data.data);
- } catch (e) {
- console.error(
- `Error in supermemory.ai extension: ${e}. Please contact the developer https://x.com/dhravyashah`,
- );
- }
- };
-
- async function sendUrlToAPI(spaces: string[]) {
- setLoading(true);
-
- setTimeout(() => {
- setLoading(false);
- }, 1500);
-
- // get the current URL
- const url = window.location.href;
-
- const blacklist: string[] = [];
- // check if the URL is blacklisted
- if (blacklist.some((blacklisted) => url.includes(blacklisted))) {
- return;
- } else {
- const clone = document.cloneNode(true) as Document;
- const article = new Readability(clone).parse();
-
- const ogImage = document
- .querySelector('meta[property="og:image"]')
- ?.getAttribute("content");
-
- const favicon = (
- document.querySelector('link[rel="icon"]') as HTMLLinkElement
- )?.href;
-
- setLoading(true);
-
- setIsPopoverOpen(false);
-
- await fetch(`${BACKEND_URL}/api/store`, {
- method: "POST",
- headers: {
- Authorization: `Bearer ${token}`,
- },
- body: JSON.stringify({
- pageContent:
- (webNote ? `Note about this website: ${webNote}\n\n` : "") +
- article?.textContent,
- url: url + "#supermemory-user-" + Math.random(),
- title: article?.title.slice(0, 500),
- spaces: spaces,
- description: article?.excerpt.slice(0, 250),
- ogImage: ogImage?.slice(0, 1000),
- image: favicon,
- }),
- }).then(async (rep) => {
- if (rep.status === 401) {
- showLoginToast();
- return;
- }
-
- const d = await rep.json();
-
- if (rep.status === 200) {
- toast({
- title: "Saved to supermemory.ai",
- });
- } else {
- toast({
- title: `Failed to save to supermemory.ai: ${d.error ?? "Unknown error"}`,
- });
- }
- setLoading(false);
- return rep;
- });
- }
- }
-
- if (!shadowRoot || !portalContainer) {
- return null;
- }
-
- return (
- <div className="flex justify-end items-end min-h-screen h-full w-full">
- <Toaster />
-
- <Popover
- open={isPopoverOpen}
- onOpenChange={() => setIsPopoverOpen(!isPopoverOpen)}
- >
- <TooltipProvider>
- <Tooltip>
- <TooltipTrigger onClick={async () => await getSpaces()} asChild>
- <PopoverTrigger
- className={`${hover || isPopoverOpen ? "opacity-100" : "opacity-75 pointer-events-none translate-x-3/4"} focus-within:translate-x-0 focus-visible:translate-x-0 size-12 hover:bg-black p-2 rounded-l-2xl transition bg-secondary border-2 border-border opacity-0 absolute flex bottom-20 items-center text-lg`}
- >
- <svg
- className={`w-full h-full size-8 ${loading && "animate-spin"}`}
- width={24}
- height={24}
- viewBox="0 0 42 42"
- fill="currentColor"
- xmlns="http://www.w3.org/2000/svg"
- >
- <path
- d="M19.0357 8C20.5531 8 21 9.27461 21 10.8438V16.3281H23.5536V14.2212C23.5536 13.1976 23.9468 12.216 24.6467 11.4922L25.0529 11.0721C24.9729 10.8772 24.9286 10.6627 24.9286 10.4375C24.9286 9.54004 25.6321 8.8125 26.5 8.8125C27.3679 8.8125 28.0714 9.54004 28.0714 10.4375C28.0714 11.335 27.3679 12.0625 26.5 12.0625C26.2822 12.0625 26.0748 12.0167 25.8863 11.9339L25.4801 12.354C25.0012 12.8492 24.7321 13.5209 24.7321 14.2212V16.3281H28.9714C29.2045 15.7326 29.7691 15.3125 30.4286 15.3125C31.2964 15.3125 32 16.04 32 16.9375C32 17.835 31.2964 18.5625 30.4286 18.5625C29.7691 18.5625 29.2045 18.1424 28.9714 17.5469H21V21.2031H25.0428C25.2759 20.6076 25.8405 20.1875 26.5 20.1875C27.3679 20.1875 28.0714 20.915 28.0714 21.8125C28.0714 22.71 27.3679 23.4375 26.5 23.4375C25.8405 23.4375 25.2759 23.0174 25.0428 22.4219H21V26.0781H24.4125C25.4023 26.0781 26.3516 26.4847 27.0515 27.2085L29.0292 29.2536C29.2177 29.1708 29.4251 29.125 29.6429 29.125C30.5107 29.125 31.2143 29.8525 31.2143 30.75C31.2143 31.6475 30.5107 32.375 29.6429 32.375C28.775 32.375 28.0714 31.6475 28.0714 30.75C28.0714 30.5248 28.1157 30.3103 28.1958 30.1154L26.2181 28.0703C25.7392 27.5751 25.0897 27.2969 24.4125 27.2969H21V31.1562C21 32.7254 20.5531 34 19.0357 34C17.6165 34 16.4478 32.8879 16.3004 31.4559C16.0451 31.527 15.775 31.5625 15.5 31.5625C13.7665 31.5625 12.3571 30.1051 12.3571 28.3125C12.3571 27.9367 12.421 27.5711 12.5339 27.2359C11.0509 26.657 10 25.1742 10 23.4375C10 21.8176 10.9183 20.416 12.2491 19.766C11.8219 19.2125 11.5714 18.5117 11.5714 17.75C11.5714 16.191 12.6321 14.891 14.0464 14.5711C13.9679 14.2918 13.9286 13.9922 13.9286 13.6875C13.9286 12.1691 14.9402 10.8895 16.3004 10.534C16.4478 9.11211 17.6165 8 19.0357 8Z"
- fill={loading ? "gray" : "#fff"}
- />
- </svg>
- </PopoverTrigger>
- </TooltipTrigger>
- <TooltipContent side="left">
- {userNotLoggedIn ? (
- <>You need to login to use this extension.</>
- ) : (
- <p>Add to supermemory.ai</p>
- )}
- </TooltipContent>
- </Tooltip>
- </TooltipProvider>
- <PopoverContent
- key={userNotLoggedIn ? "login" : "spaces"}
- container={portalContainer}
- >
- {userNotLoggedIn ? (
- <div className="flex flex-col gap-2">
- <button
- onClick={() => {
- window.open("https://supermemory.ai/signin", "_blank");
- }}
- className="bg-slate-700 text-white p-2 rounded-md"
- >
- Login to supermemory.ai
- </button>
- </div>
- ) : (
- <div className="flex flex-col gap-2">
- <Select onValueChange={(value) => setSelectedSpace(value)}>
- <SelectTrigger className="text-white">
- <SelectValue
- className="placeholder:font-semibold placeholder:text-white"
- placeholder="Select a space"
- />
- </SelectTrigger>
- <SelectContent container={portalContainer}>
- <SelectGroup>
- <SelectLabel>Your spaces</SelectLabel>
- {spacesOptions.map((space) => (
- <SelectItem key={space.id} value={`${space.id}`}>
- {space.name}
- </SelectItem>
- ))}
- </SelectGroup>
- </SelectContent>
- </Select>
-
- <Label className="text-slate-400" htmlFor="input-note">
- Add a note
- </Label>
- <Textarea
- value={webNote}
- onChange={(e) => setWebNote(e.target.value)}
- placeholder="Add a note"
- className="text-white"
- id="input-note"
- />
-
- <button
- onClick={async () => {
- await sendUrlToAPI(selectedSpace ? [selectedSpace] : []);
- }}
- className="bg-slate-700 text-white p-2 rounded-md"
- >
- Add to{" "}
- {selectedSpace
- ? spacesOptions.find((s) => s.id === parseInt(selectedSpace))
- ?.name
- : "supermemory.ai"}
- </button>
- </div>
- )}
- </PopoverContent>
- </Popover>
-
- {(window.location.host === "twitter.com" ||
- window.location.host === "x.com") && (
- <Popover open={isPopover2Open} onOpenChange={setIsPopover2Open}>
- <TooltipProvider>
- <Tooltip>
- <TooltipTrigger asChild>
- <PopoverTrigger
- className={`${hover || isPopover2Open ? "opacity-100" : "opacity-75 pointer-events-none translate-x-3/4"} focus-within:translate-x-0 focus-visible:translate-x-0 size-12 hover:bg-black p-2 rounded-l-2xl transition bg-secondary border-2 border-border opacity-0 absolute flex bottom-6 items-center text-lg`}
- >
- <svg
- xmlns="http://www.w3.org/2000/svg"
- viewBox="0 0 24 24"
- fill="currentColor"
- className="size-8"
- >
- <path d="M12 1.5a.75.75 0 0 1 .75.75V7.5h-1.5V2.25A.75.75 0 0 1 12 1.5ZM11.25 7.5v5.69l-1.72-1.72a.75.75 0 0 0-1.06 1.06l3 3a.75.75 0 0 0 1.06 0l3-3a.75.75 0 1 0-1.06-1.06l-1.72 1.72V7.5h3.75a3 3 0 0 1 3 3v9a3 3 0 0 1-3 3h-9a3 3 0 0 1-3-3v-9a3 3 0 0 1 3-3h3.75Z" />
- </svg>
- </PopoverTrigger>
- </TooltipTrigger>
- <TooltipContent side="left">
- {userNotLoggedIn ? (
- <>You need to login to use this extension.</>
- ) : (
- <p>Import all twitter bookmarks</p>
- )}
- </TooltipContent>
- </Tooltip>
- </TooltipProvider>
- <PopoverContent
- key={userNotLoggedIn ? "login" : "spaces"}
- container={portalContainer}
- >
- {userNotLoggedIn ? (
- <div className="flex flex-col gap-2">
- <button
- onClick={() => {
- window.open("https://supermemory.ai/signin", "_blank");
- }}
- className="bg-slate-700 text-white p-2 rounded-md"
- >
- Login to supermemory.ai
- </button>
- </div>
- ) : (
- <div className="flex flex-col gap-2">
- <button
- disabled={isImporting}
- onClick={async () => {
- setIsImporting(true);
- chrome.runtime.sendMessage({ type: "batchImportAll" });
- }}
- className="bg-slate-700 text-white p-2 rounded-md disabled:bg-slate-700/50 disabled:pointer-events-none"
- >
- Import all Twitter bookmarks
- </button>
-
- {isImporting && (
- <div className="flex items-center gap-2">
- <p>Imported {importedCount} bookmarks</p>
- <svg
- className="animate-spin w-6 h-6"
- xmlns="http://www.w3.org/2000/svg"
- fill="none"
- viewBox="0 0 24 24"
- stroke="currentColor"
- >
- <path
- strokeLinecap="round"
- strokeLinejoin="round"
- strokeWidth={2}
- d="M12 6v6m0 0v6m0-6h6m-6 0H6"
- />
- </svg>
- </div>
- )}
-
- {importDone && (
- <p className="text-green-500">
- All your twitter bookmarks have been imported!
- </p>
- )}
- </div>
- )}
- </PopoverContent>
- </Popover>
- )}
- </div>
- );
+ const [hover, setHover] = useState(false);
+
+ const { toast } = useToast();
+
+ const [loading, setLoading] = useState(false);
+
+ const [webNote, setWebNote] = useState<string>("");
+
+ const [importedCount, setImportedCount] = useState(0);
+ const [isImporting, setIsImporting] = useState(false);
+ const [importDone, setImportDone] = useState(false);
+
+ const [portalContainer, setPortalContainer] = useState<HTMLElement | null>(
+ null,
+ );
+ const [isPopoverOpen, setIsPopoverOpen] = useState(false);
+ const [isPopover2Open, setIsPopover2Open] = useState(false);
+
+ const [spacesOptions, setSpacesOptions] = useState<
+ { id: number; name: string }[]
+ >([]);
+ const [selectedSpace, setSelectedSpace] = useState<string>();
+
+ const [userNotLoggedIn, setUserNotLoggedIn] = useState(false);
+
+ const showLoginToast = async () => {
+ setUserNotLoggedIn(true);
+
+ const NOSHOW_TOAST = ["accounts.google.com", "supermemory.ai"];
+
+ const noLoginWarning = await chrome.storage.local.get("noLoginWarning");
+ if (Object.keys(noLoginWarning).length > 0) {
+ return;
+ }
+
+ if (!NOSHOW_TOAST.includes(window.location.host)) {
+ const t = toast({
+ title: "Please login to supermemory.ai to use this extension.",
+ action: (
+ <div className="flex flex-col gap-2">
+ <button
+ onClick={() =>
+ window.open("https://supermemory.ai/signin", "_blank")
+ }
+ >
+ Login
+ </button>
+
+ <button
+ className="text-xs"
+ onClick={async () => {
+ await chrome.storage.local.set({
+ noLoginWarning: true,
+ });
+ t.dismiss();
+ }}
+ >
+ Ignore
+ </button>
+ </div>
+ ),
+ });
+ }
+ };
+
+ useEffect(() => {
+ document.addEventListener("mousemove", (e) => {
+ const percentageX = (e.clientX / window.innerWidth) * 100;
+ const percentageY = (e.clientY / window.innerHeight) * 100;
+
+ if (percentageX > 75 && percentageY > 75) {
+ setHover(true);
+ } else {
+ setHover(false);
+ }
+ });
+
+ const getUserData = () => {
+ chrome.runtime.sendMessage({ type: "getJwt" });
+ };
+
+ getUserData();
+
+ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
+ if (request.type === "import-update") {
+ setIsImporting(true);
+ setImportedCount(request.importedCount);
+ }
+
+ if (request.type === "import-done") {
+ setIsImporting(false);
+ setImportDone(true);
+ }
+
+ if (request.type === "supermemory-message") {
+ toast({
+ title: request.message,
+ });
+ }
+ });
+
+ const portalDiv = document.createElement("div");
+ portalDiv.id = "popover-portal";
+ shadowRoot.appendChild(portalDiv);
+ setPortalContainer(portalDiv);
+
+ return () => {
+ document.removeEventListener("mousemove", () => {});
+ };
+ }, []);
+
+ const getSpaces = async () => {
+ const response = await fetch(`${BACKEND_URL}/api/spaces`, {
+ headers: {
+ Authorization: `Bearer ${token}`,
+ },
+ });
+
+ if (response.status === 401) {
+ showLoginToast();
+ return;
+ }
+
+ try {
+ const data = await response.json();
+ setSpacesOptions(data.data);
+ } catch (e) {
+ console.error(
+ `Error in supermemory.ai extension: ${e}. Please contact the developer https://x.com/dhravyashah`,
+ );
+ }
+ };
+
+ async function sendUrlToAPI(spaces: string[]) {
+ setLoading(true);
+
+ setTimeout(() => {
+ setLoading(false);
+ }, 1500);
+
+ // get the current URL
+ const url = window.location.href;
+
+ const blacklist: string[] = [];
+ // check if the URL is blacklisted
+ if (blacklist.some((blacklisted) => url.includes(blacklisted))) {
+ return;
+ } else {
+ const clone = document.cloneNode(true) as Document;
+ const article = new Readability(clone).parse();
+
+ const ogImage = document
+ .querySelector('meta[property="og:image"]')
+ ?.getAttribute("content");
+
+ const favicon = (
+ document.querySelector('link[rel="icon"]') as HTMLLinkElement
+ )?.href;
+
+ setLoading(true);
+
+ setIsPopoverOpen(false);
+
+ await fetch(`${BACKEND_URL}/api/store`, {
+ method: "POST",
+ headers: {
+ Authorization: `Bearer ${token}`,
+ },
+ body: JSON.stringify({
+ pageContent:
+ (webNote ? `Note about this website: ${webNote}\n\n` : "") +
+ article?.textContent,
+ url: url + "#supermemory-user-" + Math.random(),
+ title: article?.title.slice(0, 500),
+ spaces: spaces,
+ description: article?.excerpt.slice(0, 250),
+ ogImage: ogImage?.slice(0, 1000),
+ image: favicon,
+ }),
+ }).then(async (rep) => {
+ if (rep.status === 401) {
+ showLoginToast();
+ return;
+ }
+
+ const d = await rep.json();
+
+ if (rep.status === 200) {
+ toast({
+ title: "Saved to supermemory.ai",
+ });
+ } else {
+ toast({
+ title: `Failed to save to supermemory.ai: ${d.error ?? "Unknown error"}`,
+ });
+ }
+ setLoading(false);
+ return rep;
+ });
+ }
+ }
+
+ if (!shadowRoot || !portalContainer) {
+ return null;
+ }
+
+ return (
+ <div className="flex justify-end items-end min-h-screen h-full w-full">
+ <Toaster />
+
+ <Popover
+ open={isPopoverOpen}
+ onOpenChange={() => setIsPopoverOpen(!isPopoverOpen)}
+ >
+ <TooltipProvider>
+ <Tooltip>
+ <TooltipTrigger onClick={async () => await getSpaces()} asChild>
+ <PopoverTrigger
+ className={`${hover || isPopoverOpen ? "opacity-100" : "opacity-75 pointer-events-none translate-x-3/4"} focus-within:translate-x-0 focus-visible:translate-x-0 size-12 hover:bg-black p-2 rounded-l-2xl transition bg-secondary border-2 border-border opacity-0 absolute flex bottom-20 items-center text-lg`}
+ >
+ <svg
+ className={`w-full h-full size-8 ${loading && "animate-spin"}`}
+ width={24}
+ height={24}
+ viewBox="0 0 42 42"
+ fill="currentColor"
+ xmlns="http://www.w3.org/2000/svg"
+ >
+ <path
+ d="M19.0357 8C20.5531 8 21 9.27461 21 10.8438V16.3281H23.5536V14.2212C23.5536 13.1976 23.9468 12.216 24.6467 11.4922L25.0529 11.0721C24.9729 10.8772 24.9286 10.6627 24.9286 10.4375C24.9286 9.54004 25.6321 8.8125 26.5 8.8125C27.3679 8.8125 28.0714 9.54004 28.0714 10.4375C28.0714 11.335 27.3679 12.0625 26.5 12.0625C26.2822 12.0625 26.0748 12.0167 25.8863 11.9339L25.4801 12.354C25.0012 12.8492 24.7321 13.5209 24.7321 14.2212V16.3281H28.9714C29.2045 15.7326 29.7691 15.3125 30.4286 15.3125C31.2964 15.3125 32 16.04 32 16.9375C32 17.835 31.2964 18.5625 30.4286 18.5625C29.7691 18.5625 29.2045 18.1424 28.9714 17.5469H21V21.2031H25.0428C25.2759 20.6076 25.8405 20.1875 26.5 20.1875C27.3679 20.1875 28.0714 20.915 28.0714 21.8125C28.0714 22.71 27.3679 23.4375 26.5 23.4375C25.8405 23.4375 25.2759 23.0174 25.0428 22.4219H21V26.0781H24.4125C25.4023 26.0781 26.3516 26.4847 27.0515 27.2085L29.0292 29.2536C29.2177 29.1708 29.4251 29.125 29.6429 29.125C30.5107 29.125 31.2143 29.8525 31.2143 30.75C31.2143 31.6475 30.5107 32.375 29.6429 32.375C28.775 32.375 28.0714 31.6475 28.0714 30.75C28.0714 30.5248 28.1157 30.3103 28.1958 30.1154L26.2181 28.0703C25.7392 27.5751 25.0897 27.2969 24.4125 27.2969H21V31.1562C21 32.7254 20.5531 34 19.0357 34C17.6165 34 16.4478 32.8879 16.3004 31.4559C16.0451 31.527 15.775 31.5625 15.5 31.5625C13.7665 31.5625 12.3571 30.1051 12.3571 28.3125C12.3571 27.9367 12.421 27.5711 12.5339 27.2359C11.0509 26.657 10 25.1742 10 23.4375C10 21.8176 10.9183 20.416 12.2491 19.766C11.8219 19.2125 11.5714 18.5117 11.5714 17.75C11.5714 16.191 12.6321 14.891 14.0464 14.5711C13.9679 14.2918 13.9286 13.9922 13.9286 13.6875C13.9286 12.1691 14.9402 10.8895 16.3004 10.534C16.4478 9.11211 17.6165 8 19.0357 8Z"
+ fill={loading ? "gray" : "#fff"}
+ />
+ </svg>
+ </PopoverTrigger>
+ </TooltipTrigger>
+ <TooltipContent side="left">
+ {userNotLoggedIn ? (
+ <>You need to login to use this extension.</>
+ ) : (
+ <p>Add to supermemory.ai</p>
+ )}
+ </TooltipContent>
+ </Tooltip>
+ </TooltipProvider>
+ <PopoverContent
+ key={userNotLoggedIn ? "login" : "spaces"}
+ container={portalContainer}
+ >
+ {userNotLoggedIn ? (
+ <div className="flex flex-col gap-2">
+ <button
+ onClick={() => {
+ window.open("https://supermemory.ai/signin", "_blank");
+ }}
+ className="bg-slate-700 text-white p-2 rounded-md"
+ >
+ Login to supermemory.ai
+ </button>
+ </div>
+ ) : (
+ <div className="flex flex-col gap-2">
+ <Select onValueChange={(value) => setSelectedSpace(value)}>
+ <SelectTrigger className="text-white">
+ <SelectValue
+ className="placeholder:font-semibold placeholder:text-white"
+ placeholder="Select a space"
+ />
+ </SelectTrigger>
+ <SelectContent container={portalContainer}>
+ <SelectGroup>
+ <SelectLabel>Your spaces</SelectLabel>
+ {spacesOptions.map((space) => (
+ <SelectItem key={space.id} value={`${space.id}`}>
+ {space.name}
+ </SelectItem>
+ ))}
+ </SelectGroup>
+ </SelectContent>
+ </Select>
+
+ <Label className="text-slate-400" htmlFor="input-note">
+ Add a note
+ </Label>
+ <Textarea
+ value={webNote}
+ onChange={(e) => setWebNote(e.target.value)}
+ placeholder="Add a note"
+ className="text-white"
+ id="input-note"
+ />
+
+ <button
+ onClick={async () => {
+ await sendUrlToAPI(selectedSpace ? [selectedSpace] : []);
+ }}
+ className="bg-slate-700 text-white p-2 rounded-md"
+ >
+ Add to{" "}
+ {selectedSpace
+ ? spacesOptions.find((s) => s.id === parseInt(selectedSpace))
+ ?.name
+ : "supermemory.ai"}
+ </button>
+ </div>
+ )}
+ </PopoverContent>
+ </Popover>
+
+ {(window.location.host === "twitter.com" ||
+ window.location.host === "x.com") && (
+ <Popover open={isPopover2Open} onOpenChange={setIsPopover2Open}>
+ <TooltipProvider>
+ <Tooltip>
+ <TooltipTrigger asChild>
+ <PopoverTrigger
+ className={`${hover || isPopover2Open ? "opacity-100" : "opacity-75 pointer-events-none translate-x-3/4"} focus-within:translate-x-0 focus-visible:translate-x-0 size-12 hover:bg-black p-2 rounded-l-2xl transition bg-secondary border-2 border-border opacity-0 absolute flex bottom-6 items-center text-lg`}
+ >
+ <svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="currentColor"
+ className="size-8"
+ >
+ <path d="M12 1.5a.75.75 0 0 1 .75.75V7.5h-1.5V2.25A.75.75 0 0 1 12 1.5ZM11.25 7.5v5.69l-1.72-1.72a.75.75 0 0 0-1.06 1.06l3 3a.75.75 0 0 0 1.06 0l3-3a.75.75 0 1 0-1.06-1.06l-1.72 1.72V7.5h3.75a3 3 0 0 1 3 3v9a3 3 0 0 1-3 3h-9a3 3 0 0 1-3-3v-9a3 3 0 0 1 3-3h3.75Z" />
+ </svg>
+ </PopoverTrigger>
+ </TooltipTrigger>
+ <TooltipContent side="left">
+ {userNotLoggedIn ? (
+ <>You need to login to use this extension.</>
+ ) : (
+ <p>Import all twitter bookmarks</p>
+ )}
+ </TooltipContent>
+ </Tooltip>
+ </TooltipProvider>
+ <PopoverContent
+ key={userNotLoggedIn ? "login" : "spaces"}
+ container={portalContainer}
+ >
+ {userNotLoggedIn ? (
+ <div className="flex flex-col gap-2">
+ <button
+ onClick={() => {
+ window.open("https://supermemory.ai/signin", "_blank");
+ }}
+ className="bg-slate-700 text-white p-2 rounded-md"
+ >
+ Login to supermemory.ai
+ </button>
+ </div>
+ ) : (
+ <div className="flex flex-col gap-2">
+ <button
+ disabled={isImporting}
+ onClick={async () => {
+ setIsImporting(true);
+ chrome.runtime.sendMessage({ type: "batchImportAll" });
+ }}
+ className="bg-slate-700 text-white p-2 rounded-md disabled:bg-slate-700/50 disabled:pointer-events-none"
+ >
+ Import all Twitter bookmarks
+ </button>
+
+ {isImporting && (
+ <div className="flex items-center gap-2">
+ <p>Imported {importedCount} bookmarks</p>
+ <svg
+ className="animate-spin w-6 h-6"
+ xmlns="http://www.w3.org/2000/svg"
+ fill="none"
+ viewBox="0 0 24 24"
+ stroke="currentColor"
+ >
+ <path
+ strokeLinecap="round"
+ strokeLinejoin="round"
+ strokeWidth={2}
+ d="M12 6v6m0 0v6m0-6h6m-6 0H6"
+ />
+ </svg>
+ </div>
+ )}
+
+ {importDone && (
+ <p className="text-green-500">
+ All your twitter bookmarks have been imported!
+ </p>
+ )}
+ </div>
+ )}
+ </PopoverContent>
+ </Popover>
+ )}
+ </div>
+ );
}
diff --git a/apps/web/.eslintrc.js b/apps/web/.eslintrc.js
index 83d36d43..f3042174 100644
--- a/apps/web/.eslintrc.js
+++ b/apps/web/.eslintrc.js
@@ -6,4 +6,7 @@ module.exports = {
parserOptions: {
project: true,
},
+ ignorePatterns: [
+ "postcss.config.js",
+ ]
};
diff --git a/apps/web/app/(auth)/layout.tsx b/apps/web/app/(auth)/layout.tsx
index 904d1987..8f45efbc 100644
--- a/apps/web/app/(auth)/layout.tsx
+++ b/apps/web/app/(auth)/layout.tsx
@@ -1,12 +1,12 @@
-import React from 'react';
-import { Toaster } from '@repo/ui/shadcn/sonner';
+import React from "react";
+import { Toaster } from "@repo/ui/shadcn/sonner";
function Layout({ children }: { children: React.ReactNode }) {
- return (
- <div>
- {children} <Toaster />
- </div>
- );
+ return (
+ <div>
+ {children} <Toaster />
+ </div>
+ );
}
export default Layout;
diff --git a/apps/web/app/(auth)/onboarding/page.tsx b/apps/web/app/(auth)/onboarding/page.tsx
index 10dd2325..df5b83d6 100644
--- a/apps/web/app/(auth)/onboarding/page.tsx
+++ b/apps/web/app/(auth)/onboarding/page.tsx
@@ -10,7 +10,7 @@ import { CheckIcon, PlusCircleIcon } from "@heroicons/react/24/outline";
import { motion } from "framer-motion";
import { useEffect, useState } from "react";
import { toast } from "sonner";
-import { completeOnboarding, createMemory } from "@repo/web/app/actions/doers";
+import { completeOnboarding, createMemory } from "@/app/actions/doers";
import { useRouter } from "next/navigation";
import Logo from "../../../public/logo.svg";
import Image from "next/image";
@@ -28,7 +28,9 @@ export default function Home() {
if (currStep > 3) {
updateDb().then(() => {
push("/home?q=what%20is%20supermemory");
- });
+ }).catch((e) => {
+ console.error(e);
+ });
}
}, [currStep]);
diff --git a/apps/web/app/(dash)/home/filterSpaces.tsx b/apps/web/app/(dash)/home/filterSpaces.tsx
index 9896141c..ec90a29a 100644
--- a/apps/web/app/(dash)/home/filterSpaces.tsx
+++ b/apps/web/app/(dash)/home/filterSpaces.tsx
@@ -62,7 +62,9 @@ export function FilterSpaces({
placeholder={selectedSpaces.length ? "" : "Search in Spaces"}
onKeyDown={handleKeyDown}
className="text-white peer placeholder:text-white"
- onChangeCapture={(e) => setInput(e.currentTarget.value)}
+ onChangeCapture={(e: React.ChangeEvent<HTMLInputElement>) =>
+ setInput(e.target.value)
+ }
value={input}
/>
</div>
diff --git a/apps/web/app/(landing)/Features/generating.tsx b/apps/web/app/(landing)/Features/generating.tsx
index 6dd0b231..0efdde41 100644
--- a/apps/web/app/(landing)/Features/generating.tsx
+++ b/apps/web/app/(landing)/Features/generating.tsx
@@ -1,16 +1,16 @@
import { Loader, Loader2 } from "lucide-react";
const Generating = ({ className }: { className?: string }) => {
- return (
- <div
- className={`flex items-center md:h-[3.5rem] px-6 bg-n-8/80 rounded-[1.7rem] ${
- className || ""
- } text-base`}
- >
- <Loader2 className="w-5 h-5 mr-2" />
- Searching your second brain...
- </div>
- );
+ return (
+ <div
+ className={`flex items-center md:h-[3.5rem] px-6 bg-n-8/80 rounded-[1.7rem] ${
+ className || ""
+ } text-base`}
+ >
+ <Loader2 className="w-5 h-5 mr-2" />
+ Searching your second brain...
+ </div>
+ );
};
export default Generating;
diff --git a/apps/web/app/(landing)/Features/index.tsx b/apps/web/app/(landing)/Features/index.tsx
index 7f1a4ccb..cc307374 100644
--- a/apps/web/app/(landing)/Features/index.tsx
+++ b/apps/web/app/(landing)/Features/index.tsx
@@ -5,219 +5,219 @@ import Image from "next/image";
import { AnimatedBeamShow } from "../CardPatterns/AnimatedBeamWithOutput";
const Services = () => {
- return (
- <div id="how-to-use">
- <div className="container">
- <div className="mr-auto max-w-5xl">
- <h1 className="mr-auto text-left font-geistSans tracking-tighter text-4xl md:text-5xl lg:text-6xl text-transparent bg-clip-text bg-[linear-gradient(180deg,_#FFF_0%,_rgba(255,_255,_255,_0.00)_202.08%)]">
- Sounds super cool? There's more.
- </h1>
- <p className="mb-10 ml-auto text-lg tracking-tight text-left font-nomral"></p>
- </div>
-
- <div className="relative bg-page-gradient">
- <div className="flex overflow-hidden relative items-stretch p-8 mb-5 rounded-3xl border lg:p-20 z-1 h-[55rem] md:h-[45rem] border-white/20 xl:h-[46rem]">
- <img
- src="/images/tailwind-bg-gradient.avif"
- className="absolute top-0 right-0 opacity-100 z-2"
- />
- <img
- src="/images/tailwind-bg-gradient.avif"
- className="absolute top-0 right-0 opacity-100 z-2"
- />
- <div className="absolute top-0 left-0 w-full h-full md:w-3/5 xl:w-auto">
- <img
- className="object-cover w-full h-full md:object-right"
- width={800}
- alt="Smartest AI"
- height={730}
- src={"/images/service-1.png"}
- />
- </div>
-
- <div className="relative ml-auto z-1 max-w-[17rem]">
- <h4 className="mb-4 text-3xl md:text-4xl">
- We paid attention to details.
- </h4>
- <p className="body-2 mb-[3rem] text-n-3">
- a small team of 4 student developers who have one mission.{" "}
- <br />
- Make the best second brain for everyone.
- </p>
- <ul className="text-lg">
- {supermemoryPoints.map((item, index) => (
- <li
- key={index}
- className="flex items-start py-4 border-t border-white/20"
- >
- <CheckIcon className="inline-flex justify-center items-center mt-2 ml-2 w-4 h-4 rounded-full text-slate-200 size-4" />
- {/* <img width={24} height={24} src={check} /> */}
- <p className="ml-4">{item}</p>
- </li>
- ))}
- </ul>
- </div>
-
- <Generating className="absolute right-4 bottom-4 left-4 border lg:bottom-8 lg-right-auto lg:left-1/2 lg:-translate-x-1/2 border-n-1/10" />
- </div>
-
- <div className="grid relative gap-5 lg:grid-cols-2 z-1">
- <div className="overflow-hidden flex flex-col md:flex-row md:block relative rounded-3xl border min-h-[34rem] bg-hero-gradient bg-slate-950/10 border-white/10">
- <div className="md:absolute inset-0">
- <div className="absolute -z-1 inset-0 h-[600px] w-full bg-transparent opacity-5 bg-[linear-gradient(to_right,#f0f0f0_1px,transparent_1px),linear-gradient(to_bottom,#f0f0f0_1px,transparent_1px)] bg-[size:6rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_110%)]"></div>
-
- <Image
- src="/images/landing_integrations.png"
- className="object-contain w-full h-full"
- width={630}
- height={750}
- alt="robot"
- />
- </div>
-
- <div className="flex md:absolute md:mt-4 lg:-mt-20 inset-0 flex-col md:justify-end justify-center items-center md:items-start p-8 bg-glass-gradient">
- <h4 className="text-3xl tracking-tight mb-2 text-center text-transparent bg-clip-text bg-[linear-gradient(180deg,_#FFF_0%,_rgba(255,_255,_255,_0.00)_202.08%)]">
- Supermemory works everywhere you are.
- </h4>
- <p className="max-w-lg text-lg font-normal tracking-tighter text-gray-400 mb-[3rem]">
- We already have integrations for Telegram and Twitter (X),
- with whatsapp and SMS coming soon. So you can add and query
- data in a private manner, from anywhere.
- </p>
- <a
- href="/signin"
- className="inline-flex justify-center items-center py-4 px-10 w-full text-center bg-transparent bg-gradient-to-tr to-transparent rounded-xl transition-colors sm:w-auto mt-[-20px] bg-glass-gradient group from-zinc-300/5 via-gray-400/5 border-white/10 border-[1px] hover:bg-transparent/10"
- >
- Get started
- <ChevronRight className="ml-2 w-4 h-4 duration-300 group-hover:translate-x-1" />
- </a>
- </div>
- </div>
-
- <div
- style={{
- background:
- "linear-gradient(143.6deg, rgba(192, 132, 252, 0) 20.79%, rgba(140, 121, 249, 0.3) 60.92%, rgba(140, 121, 249, 0) 80.35%)",
- }}
- className="overflow-hidden relative py-4 rounded-3xl group bg-glass-gradient lg:min-h-[30rem]"
- >
- <div className="relative py-12 px-4 xl:px-8">
- <h4 className="text-3xl tracking-tight mb-2 text-left text-transparent bg-clip-text bg-[linear-gradient(180deg,_#FFF_0%,_rgba(255,_255,_255,_0.00)_202.08%)]">
- Privacy First
- </h4>
- <p className="text-lg text-gray-400 body-2 mb-[2rem]">
- We use state-of-the art technology and providers to make sure
- that your data is completely safe and secure, and only store
- what's absolutely needed.
- </p>
- </div>
-
- <div className="overflow-hidden relative rounded-xl h-[20rem] md:h-[25rem]">
- <img
- src={"/images/landing_vault.png"}
- className="object-cover w-full h-full transition-all duration-500 ease-linear transform group-hover:rotate-3"
- width={520}
- height={400}
- alt="vault image"
- />
- </div>
-
- <Gradient opacity={5} />
- </div>
- </div>
-
- <div
- style={{
- background:
- "linear-gradient(143.6deg, rgba(192, 132, 252, 0) 20.79%, rgba(140, 121, 249, 0.2) 40.92%, rgba(140, 121, 249, 0) 80.35%)",
- }}
- className="flex overflow-hidden relative items-center p-8 mt-5 mb-5 rounded-3xl border lg:p-20 bg-page-gradient z-1 h-[38rem] border-white/20 xl:h-[28rem] dark:[box-shadow:0_-20px_80px_-20px_#8686f01f_inset]"
- >
- <img
- src="/images/tailwind-bg-gradient.avif"
- className="absolute top-0 right-0 opacity-60 z-2"
- />
-
- <div className="absolute top-0 right-0 left-0 mx-auto w-full h-full xl:w-auto">
- <img
- className="object-cover z-40 w-full h-full border-r-2 md:scale-110 border-r-white/5"
- width={800}
- alt="Github"
- height={730}
- src={"/images/github.webp"}
- />
- </div>
-
- <div className="absolute right-0 left-0 bottom-5 mx-auto mt-20 text-center z-1 p-8">
- <h4 className="mb-4 text-4xl tracking-tighter text-white lg:text-5xl">
- Proudly <br /> Open Source
- </h4>
- <p className="text-lg body-2 mb-[3rem] ">
- You dont even need to trust us. Just deploy it yourself and
- enjoy the benefits.
- </p>
- <a
- href="https://git.new/memory"
- className="inline-flex gap-x-1 justify-center items-center py-4 px-10 text-center bg-transparent bg-gradient-to-tr to-transparent rounded-xl transition-colors sm:w-auto w-fit mt-[-20px] bg-glass-gradient group from-zinc-300/5 via-gray-400/5 border-white/10 border-[1px] hover:bg-transparent/10"
- >
- <GithubIcon className="inline-flex justify-center items-center w-5 h-5" />{" "}
- Star us on Github
- <ChevronRight className="ml-2 w-4 h-4 duration-300 group-hover:translate-x-1" />
- </a>
- </div>
- </div>
-
- <div className="grid relative gap-5 lg:grid-cols-2 z-1">
- <div className="overflow-hidden relative rounded-3xl border max-h-[20rem] min-h-[40rem] md:min-h-[33rem] bg-hero-gradient bg-slate-950/10 border-white/10">
- <div className="absolute inset-0">
- <AnimatedBeamShow />
- </div>
-
- <div className="flex absolute inset-0 flex-col justify-end items-start p-8 pl-10 mt-4 lg:-mt-20 translate-y-10 md:translate-y-0 bg-glass-gradient">
- <h4 className="text-3xl tracking-tight mb-2 text-center text-transparent bg-clip-text bg-[linear-gradient(180deg,_#FFF_0%,_rgba(255,_255,_255,_0.00)_202.08%)]">
- Bringing content in is easy.
- </h4>
- <p className="max-w-lg text-lg font-normal tracking-tighter text-gray-400 mb-[3rem]">
- You can use our chrome extension, iOS shortcut, or our API to
- send content to supermemory.
- </p>
- </div>
- </div>
-
- <div className="overflow-hidden bg-page-gradient relative py-4 rounded-3xl max-h-[33rem] group lg:min-h-[30rem]">
- <div className="absolute -z-1 inset-0 h-[600px] w-full bg-transparent opacity-5 bg-[linear-gradient(to_right,#f0f0f0_1px,transparent_1px),linear-gradient(to_bottom,#f0f0f0_1px,transparent_1px)] bg-[size:6rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_110%)]"></div>
-
- <div className="relative py-12 px-4 xl:px-8">
- <h4 className="text-3xl tracking-tight mb-2 text-left text-transparent bg-clip-text bg-[linear-gradient(180deg,_#FFF_0%,_rgba(255,_255,_255,_0.00)_202.08%)]">
- Self hostable
- </h4>
- <p className="text-lg text-gray-400 body-2 mb-[2rem]">
- All the code is open source and self hostable for
- non-commercial use.
- </p>
- </div>
-
- <div className="overflow-hidden relative mt-[-50px] mb-10 rounded-xl h-[20rem] md:h-[25rem]">
- <img
- src={
- "https://www.koyeb.com/_next/image?url=%2Fimages%2Fillustrations%2Fhome-scale-mesh.webp&w=384&q=75"
- }
- className="object-cover w-full h-full transition-all duration-500 ease-linear transform group-hover:rotate-3"
- width={1000}
- height={1000}
- alt="Scary robot"
- />
- </div>
-
- <Gradient opacity={5} />
- </div>
- </div>
-
- <Gradient />
- </div>
- </div>
- </div>
- );
+ return (
+ <div id="how-to-use">
+ <div className="container">
+ <div className="mr-auto max-w-5xl">
+ <h1 className="mr-auto text-left font-geistSans tracking-tighter text-4xl md:text-5xl lg:text-6xl text-transparent bg-clip-text bg-[linear-gradient(180deg,_#FFF_0%,_rgba(255,_255,_255,_0.00)_202.08%)]">
+ Sounds super cool? There's more.
+ </h1>
+ <p className="mb-10 ml-auto text-lg tracking-tight text-left font-nomral"></p>
+ </div>
+
+ <div className="relative bg-page-gradient">
+ <div className="flex overflow-hidden relative items-stretch p-8 mb-5 rounded-3xl border lg:p-20 z-1 h-[55rem] md:h-[45rem] border-white/20 xl:h-[46rem]">
+ <img
+ src="/images/tailwind-bg-gradient.avif"
+ className="absolute top-0 right-0 opacity-100 z-2"
+ />
+ <img
+ src="/images/tailwind-bg-gradient.avif"
+ className="absolute top-0 right-0 opacity-100 z-2"
+ />
+ <div className="absolute top-0 left-0 w-full h-full md:w-3/5 xl:w-auto">
+ <img
+ className="object-cover w-full h-full md:object-right"
+ width={800}
+ alt="Smartest AI"
+ height={730}
+ src={"/images/service-1.png"}
+ />
+ </div>
+
+ <div className="relative ml-auto z-1 max-w-[17rem]">
+ <h4 className="mb-4 text-3xl md:text-4xl">
+ We paid attention to details.
+ </h4>
+ <p className="body-2 mb-[3rem] text-n-3">
+ a small team of 4 student developers who have one mission.{" "}
+ <br />
+ Make the best second brain for everyone.
+ </p>
+ <ul className="text-lg">
+ {supermemoryPoints.map((item, index) => (
+ <li
+ key={index}
+ className="flex items-start py-4 border-t border-white/20"
+ >
+ <CheckIcon className="inline-flex justify-center items-center mt-2 ml-2 w-4 h-4 rounded-full text-slate-200 size-4" />
+ {/* <img width={24} height={24} src={check} /> */}
+ <p className="ml-4">{item}</p>
+ </li>
+ ))}
+ </ul>
+ </div>
+
+ <Generating className="absolute right-4 bottom-4 left-4 border lg:bottom-8 lg-right-auto lg:left-1/2 lg:-translate-x-1/2 border-n-1/10" />
+ </div>
+
+ <div className="grid relative gap-5 lg:grid-cols-2 z-1">
+ <div className="overflow-hidden flex flex-col md:flex-row md:block relative rounded-3xl border min-h-[34rem] bg-hero-gradient bg-slate-950/10 border-white/10">
+ <div className="md:absolute inset-0">
+ <div className="absolute -z-1 inset-0 h-[600px] w-full bg-transparent opacity-5 bg-[linear-gradient(to_right,#f0f0f0_1px,transparent_1px),linear-gradient(to_bottom,#f0f0f0_1px,transparent_1px)] bg-[size:6rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_110%)]"></div>
+
+ <Image
+ src="/images/landing_integrations.png"
+ className="object-contain w-full h-full"
+ width={630}
+ height={750}
+ alt="robot"
+ />
+ </div>
+
+ <div className="flex md:absolute md:mt-4 lg:-mt-20 inset-0 flex-col md:justify-end justify-center items-center md:items-start p-8 bg-glass-gradient">
+ <h4 className="text-3xl tracking-tight mb-2 text-center text-transparent bg-clip-text bg-[linear-gradient(180deg,_#FFF_0%,_rgba(255,_255,_255,_0.00)_202.08%)]">
+ Supermemory works everywhere you are.
+ </h4>
+ <p className="max-w-lg text-lg font-normal tracking-tighter text-gray-400 mb-[3rem]">
+ We already have integrations for Telegram and Twitter (X),
+ with whatsapp and SMS coming soon. So you can add and query
+ data in a private manner, from anywhere.
+ </p>
+ <a
+ href="/signin"
+ className="inline-flex justify-center items-center py-4 px-10 w-full text-center bg-transparent bg-gradient-to-tr to-transparent rounded-xl transition-colors sm:w-auto mt-[-20px] bg-glass-gradient group from-zinc-300/5 via-gray-400/5 border-white/10 border-[1px] hover:bg-transparent/10"
+ >
+ Get started
+ <ChevronRight className="ml-2 w-4 h-4 duration-300 group-hover:translate-x-1" />
+ </a>
+ </div>
+ </div>
+
+ <div
+ style={{
+ background:
+ "linear-gradient(143.6deg, rgba(192, 132, 252, 0) 20.79%, rgba(140, 121, 249, 0.3) 60.92%, rgba(140, 121, 249, 0) 80.35%)",
+ }}
+ className="overflow-hidden relative py-4 rounded-3xl group bg-glass-gradient lg:min-h-[30rem]"
+ >
+ <div className="relative py-12 px-4 xl:px-8">
+ <h4 className="text-3xl tracking-tight mb-2 text-left text-transparent bg-clip-text bg-[linear-gradient(180deg,_#FFF_0%,_rgba(255,_255,_255,_0.00)_202.08%)]">
+ Privacy First
+ </h4>
+ <p className="text-lg text-gray-400 body-2 mb-[2rem]">
+ We use state-of-the art technology and providers to make sure
+ that your data is completely safe and secure, and only store
+ what's absolutely needed.
+ </p>
+ </div>
+
+ <div className="overflow-hidden relative rounded-xl h-[20rem] md:h-[25rem]">
+ <img
+ src={"/images/landing_vault.png"}
+ className="object-cover w-full h-full transition-all duration-500 ease-linear transform group-hover:rotate-3"
+ width={520}
+ height={400}
+ alt="vault image"
+ />
+ </div>
+
+ <Gradient opacity={5} />
+ </div>
+ </div>
+
+ <div
+ style={{
+ background:
+ "linear-gradient(143.6deg, rgba(192, 132, 252, 0) 20.79%, rgba(140, 121, 249, 0.2) 40.92%, rgba(140, 121, 249, 0) 80.35%)",
+ }}
+ className="flex overflow-hidden relative items-center p-8 mt-5 mb-5 rounded-3xl border lg:p-20 bg-page-gradient z-1 h-[38rem] border-white/20 xl:h-[28rem] dark:[box-shadow:0_-20px_80px_-20px_#8686f01f_inset]"
+ >
+ <img
+ src="/images/tailwind-bg-gradient.avif"
+ className="absolute top-0 right-0 opacity-60 z-2"
+ />
+
+ <div className="absolute top-0 right-0 left-0 mx-auto w-full h-full xl:w-auto">
+ <img
+ className="object-cover z-40 w-full h-full border-r-2 md:scale-110 border-r-white/5"
+ width={800}
+ alt="Github"
+ height={730}
+ src={"/images/github.webp"}
+ />
+ </div>
+
+ <div className="absolute right-0 left-0 bottom-5 mx-auto mt-20 text-center z-1 p-8">
+ <h4 className="mb-4 text-4xl tracking-tighter text-white lg:text-5xl">
+ Proudly <br /> Open Source
+ </h4>
+ <p className="text-lg body-2 mb-[3rem] ">
+ You dont even need to trust us. Just deploy it yourself and
+ enjoy the benefits.
+ </p>
+ <a
+ href="https://git.new/memory"
+ className="inline-flex gap-x-1 justify-center items-center py-4 px-10 text-center bg-transparent bg-gradient-to-tr to-transparent rounded-xl transition-colors sm:w-auto w-fit mt-[-20px] bg-glass-gradient group from-zinc-300/5 via-gray-400/5 border-white/10 border-[1px] hover:bg-transparent/10"
+ >
+ <GithubIcon className="inline-flex justify-center items-center w-5 h-5" />{" "}
+ Star us on Github
+ <ChevronRight className="ml-2 w-4 h-4 duration-300 group-hover:translate-x-1" />
+ </a>
+ </div>
+ </div>
+
+ <div className="grid relative gap-5 lg:grid-cols-2 z-1">
+ <div className="overflow-hidden relative rounded-3xl border max-h-[20rem] min-h-[40rem] md:min-h-[33rem] bg-hero-gradient bg-slate-950/10 border-white/10">
+ <div className="absolute inset-0">
+ <AnimatedBeamShow />
+ </div>
+
+ <div className="flex absolute inset-0 flex-col justify-end items-start p-8 pl-10 mt-4 lg:-mt-20 translate-y-10 md:translate-y-0 bg-glass-gradient">
+ <h4 className="text-3xl tracking-tight mb-2 text-center text-transparent bg-clip-text bg-[linear-gradient(180deg,_#FFF_0%,_rgba(255,_255,_255,_0.00)_202.08%)]">
+ Bringing content in is easy.
+ </h4>
+ <p className="max-w-lg text-lg font-normal tracking-tighter text-gray-400 mb-[3rem]">
+ You can use our chrome extension, iOS shortcut, or our API to
+ send content to supermemory.
+ </p>
+ </div>
+ </div>
+
+ <div className="overflow-hidden bg-page-gradient relative py-4 rounded-3xl max-h-[33rem] group lg:min-h-[30rem]">
+ <div className="absolute -z-1 inset-0 h-[600px] w-full bg-transparent opacity-5 bg-[linear-gradient(to_right,#f0f0f0_1px,transparent_1px),linear-gradient(to_bottom,#f0f0f0_1px,transparent_1px)] bg-[size:6rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_110%)]"></div>
+
+ <div className="relative py-12 px-4 xl:px-8">
+ <h4 className="text-3xl tracking-tight mb-2 text-left text-transparent bg-clip-text bg-[linear-gradient(180deg,_#FFF_0%,_rgba(255,_255,_255,_0.00)_202.08%)]">
+ Self hostable
+ </h4>
+ <p className="text-lg text-gray-400 body-2 mb-[2rem]">
+ All the code is open source and self hostable for
+ non-commercial use.
+ </p>
+ </div>
+
+ <div className="overflow-hidden relative mt-[-50px] mb-10 rounded-xl h-[20rem] md:h-[25rem]">
+ <img
+ src={
+ "https://www.koyeb.com/_next/image?url=%2Fimages%2Fillustrations%2Fhome-scale-mesh.webp&w=384&q=75"
+ }
+ className="object-cover w-full h-full transition-all duration-500 ease-linear transform group-hover:rotate-3"
+ width={1000}
+ height={1000}
+ alt="Scary robot"
+ />
+ </div>
+
+ <Gradient opacity={5} />
+ </div>
+ </div>
+
+ <Gradient />
+ </div>
+ </div>
+ </div>
+ );
};
export default Services;
diff --git a/apps/web/app/(landing)/Showcase.tsx b/apps/web/app/(landing)/Showcase.tsx
index 36cbf0c3..e4c5b7af 100644
--- a/apps/web/app/(landing)/Showcase.tsx
+++ b/apps/web/app/(landing)/Showcase.tsx
@@ -148,26 +148,26 @@ function Feature({
}
function FeaturesMobile() {
- return (
- <div className="-mx-4 mt-20 flex flex-col gap-y-10 overflow-hidden px-4 sm:-mx-6 sm:px-6 lg:hidden">
- {features.map((feature) => (
- <div key={feature.summary}>
- <Feature feature={feature} className="mx-auto max-w-2xl" isActive />
- <div className="relative mt-10 pb-10">
- <div className="absolute -inset-x-4 bottom-0 top-8 bg-page-gradient sm:-inset-x-6" />
- <div className="relative mx-auto lg:w-[52.75rem] md:w-[40rem] overflow-hidden rounded-xl bg-glass-gradient shadow-lg shadow-gray-200/5 ring-1 ring-slate-500/10">
- <img
- className="w-full"
- src={`/images/${feature.image}`}
- alt=""
- sizes="52.75rem"
- />
- </div>
- </div>
- </div>
- ))}
- </div>
- );
+ return (
+ <div className="-mx-4 mt-20 flex flex-col gap-y-10 overflow-hidden px-4 sm:-mx-6 sm:px-6 lg:hidden">
+ {features.map((feature) => (
+ <div key={feature.summary}>
+ <Feature feature={feature} className="mx-auto max-w-2xl" isActive />
+ <div className="relative mt-10 pb-10">
+ <div className="absolute -inset-x-4 bottom-0 top-8 bg-page-gradient sm:-inset-x-6" />
+ <div className="relative mx-auto lg:w-[52.75rem] md:w-[40rem] overflow-hidden rounded-xl bg-glass-gradient shadow-lg shadow-gray-200/5 ring-1 ring-slate-500/10">
+ <img
+ className="w-full"
+ src={`/images/${feature.image}`}
+ alt=""
+ sizes="52.75rem"
+ />
+ </div>
+ </div>
+ </div>
+ ))}
+ </div>
+ );
}
function FeaturesDesktop() {
diff --git a/apps/web/app/actions/doers.ts b/apps/web/app/actions/doers.ts
index da2bfb5f..ff0ed5d9 100644
--- a/apps/web/app/actions/doers.ts
+++ b/apps/web/app/actions/doers.ts
@@ -324,7 +324,7 @@ export const createMemory = async (input: {
};
}
- let contentId: number | undefined;
+ let contentId: number;
const response = (await vectorSaveResponse.json()) as {
status: string;
@@ -381,6 +381,14 @@ export const createMemory = async (input: {
revalidatePath("/memories");
revalidatePath("/home");
+ if (!insertResponse[0]?.id) {
+ return {
+ success: false,
+ data: 0,
+ error: "Something went wrong while saving the document to the database",
+ };
+ }
+
contentId = insertResponse[0]?.id;
} catch (e) {
const error = e as Error;
@@ -405,14 +413,6 @@ export const createMemory = async (input: {
};
}
- if (!contentId) {
- return {
- success: false,
- data: 0,
- error: "Something went wrong while saving the document to the database",
- };
- }
-
if (storeToSpaces.length > 0) {
// Adding the many-to-many relationship between content and spaces
const spaceData = await db
diff --git a/apps/web/app/api/store/route.ts b/apps/web/app/api/store/route.ts
index 992c2a0e..13cef19e 100644
--- a/apps/web/app/api/store/route.ts
+++ b/apps/web/app/api/store/route.ts
@@ -75,7 +75,7 @@ const createMemoryFromAPI = async (input: {
};
}
- let contentId: number | undefined;
+ let contentId: number;
const saveToDbUrl =
(input.data.url.split("#supermemory-user-")[0] ?? input.data.url) +
@@ -102,7 +102,15 @@ const createMemoryFromAPI = async (input: {
})
.returning({ id: storedContent.id });
- contentId = insertResponse[0]?.id;
+ if (!insertResponse[0]?.id) {
+ return {
+ success: false,
+ data: 0,
+ error: "Failed to save to database",
+ };
+ }
+
+ contentId = insertResponse[0].id;
} catch (e) {
const error = e as Error;
console.log("Error: ", error.message);
@@ -122,14 +130,6 @@ const createMemoryFromAPI = async (input: {
};
}
- if (!contentId) {
- return {
- success: false,
- data: 0,
- error: "Failed to save to database",
- };
- }
-
if (input.data.spaces.length > 0) {
// Adding the many-to-many relationship between content and spaces
const spaceData = await db
diff --git a/apps/web/package.json b/apps/web/package.json
index 7d97fe7c..98016d8c 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -2,26 +2,28 @@
"name": "@repo/web",
"version": "1.0.0",
"private": true,
- "packageManager": "[email protected]",
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "eslint . --max-warnings 0",
+ "tsc": "tsc --noEmit --incremental",
"cf-typegen": "wrangler types --env-interface CloudflareEnv env.d.ts",
- "pages:build": "npx @cloudflare/next-on-pages",
- "preview": "npm run pages:build && wrangler pages dev",
- "deploy": "npm run pages:build && wrangler pages deploy --branch main",
- "schema-update": "bunx drizzle-kit generate sqlite",
- "update-local-db": "bunx wrangler d1 execute dev-d1-anycontext --local",
- "update-prod-db": "bunx wrangler d1 execute prod-d1-supermemory --remote"
+ "pages:build": "pnpm dlx @cloudflare/next-on-pages",
+ "preview": "pnpm run pages:build && wrangler pages dev",
+ "deploy": "pnpm run pages:build && wrangler pages deploy --branch main",
+ "schema-update": "drizzle-kit generate sqlite",
+ "update-local-db": "wrangler d1 execute dev-d1-anycontext --local",
+ "update-prod-db": "wrangler d1 execute prod-d1-supermemory --remote"
},
"dependencies": {
"@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-popover": "^1.0.7",
"@radix-ui/react-slot": "^1.1.0",
"@sentry/nextjs": "^8",
+ "clsx": "^2.1.1",
"cmdk": "^1.0.0",
+ "drizzle-orm": "0.30.0",
"lowlight": "^3.1.0",
"million": "^3.1.6",
"next": "^14.1.1",
@@ -33,21 +35,20 @@
"use-debounce": "^10.0.1"
},
"devDependencies": {
+ "@cloudflare/next-on-pages": "1",
"@next/eslint-plugin-next": "^14.1.1",
"@repo/eslint-config": "*",
- "@repo/typescript-config": "*",
- "@repo/tailwind-config": "*",
"@repo/shared-types": "*",
+ "@repo/tailwind-config": "*",
+ "@repo/typescript-config": "*",
"@types/eslint": "^8.56.5",
"@types/node": "^20.11.24",
"@types/react": "^18.2.61",
"@types/react-dom": "^18.2.19",
+ "drizzle-kit": "0.21.2",
"eslint": "^8.57.0",
- "typescript": "^5.3.3"
- },
- "trustedDependencies": [
- "esbuild",
- "workerd",
- "xycolors"
- ]
+ "postcss": "^8.4.38",
+ "typescript": "^5.3.3",
+ "wrangler": "^3.66.0"
+ }
}