From 4015bcbc9c95b97f16f5cb94aef80d997bbae3ae Mon Sep 17 00:00:00 2001 From: Samuel Aboderin Date: Mon, 16 Mar 2026 14:51:27 +0100 Subject: [PATCH 1/2] Revert "fix: make / the marketing landing page, move dashboard to /dashboard" This reverts commit 917695c2ab64aa542ac1e4185514e22a30253f96. --- app/dashboard/page.tsx | 135 ----------- app/docs/page.tsx | 2 +- app/home/page.tsx | 373 +++++++++++++++++++++++++++++ app/login/page.tsx | 2 +- app/page.tsx | 460 +++++++++--------------------------- app/prompts/new/page.tsx | 2 +- app/settings/page.tsx | 2 +- app/signup/page.tsx | 2 +- components/Header.tsx | 4 +- components/PromptDetail.tsx | 4 +- components/PromptForm.tsx | 2 +- components/Sidebar.tsx | 2 +- 12 files changed, 495 insertions(+), 495 deletions(-) delete mode 100644 app/dashboard/page.tsx create mode 100644 app/home/page.tsx diff --git a/app/dashboard/page.tsx b/app/dashboard/page.tsx deleted file mode 100644 index 222bd3a..0000000 --- a/app/dashboard/page.tsx +++ /dev/null @@ -1,135 +0,0 @@ -"use client"; - -import { Suspense } from "react"; -import { useState, useMemo, useEffect } from "react"; -import { groupPromptsByCollection, filterPrompts } from "@/lib/promptData"; -import { PromptModel } from "@/lib/types"; -import { Header } from "@/components/Header"; -import { Sidebar } from "@/components/Sidebar"; -import { Layout } from "@/components/Layout"; -import { PromptCollection } from "@/components/PromptCollection"; -import { UseCasesShowcase } from "@/components/UseCasesShowcase"; -import { PoweredByCarousel } from "@/components/PoweredByCarousel"; -import { usePrompts } from "@/lib/hooks/usePrompts"; -import { useAuth } from "@/components/AuthProvider"; - -function DashboardContent() { - const { prompts: allPrompts, loading, error } = usePrompts(); - const { loading: authLoading } = useAuth(); - const [searchQuery, setSearchQuery] = useState(""); - const [filters, setFilters] = useState<{ - query: string; - model: PromptModel | ""; - }>({ query: "", model: "" }); - const [activeCollection, setActiveCollection] = useState< - string | undefined - >(); - - useEffect(() => { - if (typeof window !== "undefined") { - const urlParams = new URLSearchParams(window.location.search); - const collection = urlParams.get("collection"); - if (collection) setActiveCollection(collection); - } - }, []); - - useEffect(() => { - setFilters((prev) => ({ ...prev, query: searchQuery })); - }, [searchQuery]); - - const filteredPrompts = useMemo(() => { - return filterPrompts(allPrompts, { - query: filters.query || undefined, - model: filters.model || undefined, - collection: activeCollection, - }); - }, [filters, allPrompts, activeCollection]); - - const promptsByCollection = useMemo(() => { - return groupPromptsByCollection(filteredPrompts); - }, [filteredPrompts]); - - const collections = Object.keys(promptsByCollection).sort(); - - return ( - - } - sidebar={ - allPrompts.length > 0 ? ( - - ) : null - } - > - {error ? ( -
-
-

Failed to load prompts

-

{error}

-
-
- ) : (authLoading || loading) ? ( -
- {[1, 2, 3].map((i) => ( -
-
- {[1, 2, 3].map((j) => ( -
- ))} -
- ))} -
- ) : allPrompts.length === 0 ? ( -
-
-

- closedNote -

-

- Your personal prompt notebook. Create, organize, and refine AI - prompts with speed and clarity. -

-
-
-
- Powered by -
- -
- -
- ) : ( -
-
- {collections.length === 0 ? ( -
-

- No prompts found matching your filters. -

-
- ) : ( -
- {collections.map((collection) => ( - - ))} -
- )} -
-
- )} - - ); -} - -export default function Dashboard() { - return ( - Loading...
}> - - - ); -} diff --git a/app/docs/page.tsx b/app/docs/page.tsx index 3001f7a..e283cc4 100644 --- a/app/docs/page.tsx +++ b/app/docs/page.tsx @@ -439,7 +439,7 @@ export default function DocsPage() { {" "}· Computer Engineering · UNILAG

- Home + Home New Prompt OCR
diff --git a/app/home/page.tsx b/app/home/page.tsx new file mode 100644 index 0000000..52e3a80 --- /dev/null +++ b/app/home/page.tsx @@ -0,0 +1,373 @@ +"use client"; + +import Link from "next/link"; +import { PoweredByCarousel } from "@/components/PoweredByCarousel"; +import { Header } from "@/components/Header"; +import { Layout } from "@/components/Layout"; +import { usePrompts } from "@/lib/hooks/usePrompts"; +import { useAuth } from "@/components/AuthProvider"; + +const CheckIcon = () => ( + + + +); + +const XIcon = () => ( + + + +); + +const comparison = [ + { feature: "Version history & diff view", closedNote: true, promptBase: false, flowGPT: false, notion: false }, + { feature: "Private by default", closedNote: true, promptBase: false, flowGPT: false, notion: true }, + { feature: "AI prompt refinement", closedNote: true, promptBase: false, flowGPT: false, notion: false }, + { feature: "OCR — import from screenshots", closedNote: true, promptBase: false, flowGPT: false, notion: false }, + { feature: "Prompt chaining", closedNote: true, promptBase: false, flowGPT: true, notion: false }, + { feature: "Built specifically for prompts", closedNote: true, promptBase: true, flowGPT: true, notion: false }, +]; + +const features = [ + { + badge: "NEW", + title: "Version History", + description: "Every edit is tracked. See exactly what changed between drafts with a visual diff, and restore any previous version in one click.", + icon: ( + + + + ), + }, + { + badge: null, + title: "AI Refinement", + description: "Paste a rough idea and let AI restructure it into a clean, reusable prompt — using your own API key.", + icon: ( + + + + ), + }, + { + badge: null, + title: "OCR Import", + description: "Photograph a whiteboard, screenshot a chat, or upload any image — closedNote extracts the text and saves it as a prompt.", + icon: ( + + + + ), + }, + { + badge: null, + title: "Prompt Chains", + description: "String prompts together into multi-step workflows. Output from one step feeds directly into the next.", + icon: ( + + + + ), + }, +]; + +export default function MarketingHome() { + const { prompts } = usePrompts(); + const { user } = useAuth(); + + return ( + } sidebar={null}> +
+ + {/* ── Hero ── */} +
+
+ + New — Version History is live +
+ +

+ + Prompts are living + +
+ + documents. + +

+ +

+ PromptBase stores them. Notion organizes them. closedNote is the only tool that + remembers how they evolved — every draft, every edit, every version. +

+ +
+ {user ? ( + <> + + Open my prompts + + + New prompt + + + ) : ( + <> + + Get started free + + + Read the docs + + + )} +
+
+ + {/* ── Powered by ── */} +
+

Powered by

+ +
+ + {/* ── The Problem ── */} +
+
+

The gap

+

+ Every tool stores prompts. +
+ None of them remember. +

+
+ +
+ {[ + { + label: "PromptBase / FlowGPT", + verdict: "Built for sharing, not crafting", + description: "Great marketplaces for discovering prompts. But your prompts are public by default, and there's no memory of how they were built. When something stops working, you're starting from scratch.", + tone: "neutral", + }, + { + label: "Notion / Notes apps", + verdict: "Flexible but completely dumb", + description: "Notion doesn't know a prompt from a grocery list. No AI awareness, no refinement, no version tracking. You're just storing text with extra friction.", + tone: "neutral", + }, + { + label: "closedNote", + verdict: "Private, versioned, intelligent", + description: "Your prompts stay yours. Every edit is tracked with a visual diff. Iterate with AI refinement, import with OCR, and always know how you got to the version that works.", + tone: "highlight", + }, + ].map((card) => ( +
+

+ {card.label} +

+

+ {card.verdict} +

+

+ {card.description} +

+
+ ))} +
+
+ + {/* ── Comparison Table ── */} +
+
+

How we stack up

+

Built different.

+
+ +
+ + + + + + + + + + + + {comparison.map((row, i) => ( + + + + + + + + ))} + +
FeatureclosedNotePromptBaseFlowGPTNotion
{row.feature} + {row.closedNote ? : } + + {row.promptBase ? : } + + {row.flowGPT ? : } + + {row.notion ? : } +
+
+
+ + {/* ── Version History Spotlight ── */} +
+
+
+ + Version History + +

+ Git for your prompts. +

+

+ Every time you save an edit, closedNote snapshots the version. Jump back to any point in time, see exactly what changed line-by-line, and restore with one click — without overwriting your history. +

+
    + {[ + "Full version timeline on every prompt", + "Visual diff — green added, red removed", + "Restore any version without losing history", + "No bloat — only versions when content changes", + ].map((point) => ( +
  • + + {point} +
  • + ))} +
+
+ + {/* Visual mockup */} +
+ {/* Window chrome */} +
+
+
+
+ Version History — Code Review Prompt +
+
+ {/* Timeline */} +
+ {[ + { v: "v3", date: "Mar 16", active: false }, + { v: "v2", date: "Mar 15", active: true }, + { v: "v1", date: "Mar 14", active: false }, + ].map((item) => ( +
+
{item.v}
+
{item.date}
+
+ ))} +
+ {/* Diff */} +
+ + Act as a coding assistant. + + {" "} + + You are an expert software engineer. + + {" "} + Review the following code and identify bugs, security issues, or performance problems.{" "} + + Be specific and actionable. + +
+
+
+ + Restore v2 + +
+
+
+
+ + {/* ── Features Grid ── */} +
+
+

Everything included

+

One tool. Everything you need.

+
+
+ {features.map((feature) => ( +
+
+
+ {feature.icon} +
+
+
+

{feature.title}

+ {feature.badge && ( + + {feature.badge} + + )} +
+

{feature.description}

+
+
+
+ ))} +
+
+ + {/* ── CTA ── */} +
+

+ Your prompts deserve better. +

+

+ Stop losing great drafts. Start building a prompt library that actually remembers how it was built. +

+
+ + {user ? "Go to my prompts" : "Get started — it's free"} + + {!user && ( + + Sign in + + )} +
+
+ +
+ + ); +} diff --git a/app/login/page.tsx b/app/login/page.tsx index b15db82..b7fd67a 100644 --- a/app/login/page.tsx +++ b/app/login/page.tsx @@ -28,7 +28,7 @@ export default function LoginPage() { if (!res.ok) { setError(res.error); } else { - router.push("/dashboard"); + router.push("/"); } } catch (err) { setError("An unexpected error occurred. Please try again."); diff --git a/app/page.tsx b/app/page.tsx index b707038..49b7bd2 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,373 +1,135 @@ "use client"; -import Link from "next/link"; -import { PoweredByCarousel } from "@/components/PoweredByCarousel"; +import { Suspense } from "react"; +import { useState, useMemo, useEffect } from "react"; +import { groupPromptsByCollection, filterPrompts } from "@/lib/promptData"; +import { PromptModel } from "@/lib/types"; import { Header } from "@/components/Header"; +import { Sidebar } from "@/components/Sidebar"; import { Layout } from "@/components/Layout"; +import { PromptCollection } from "@/components/PromptCollection"; +import { UseCasesShowcase } from "@/components/UseCasesShowcase"; +import { PoweredByCarousel } from "@/components/PoweredByCarousel"; import { usePrompts } from "@/lib/hooks/usePrompts"; import { useAuth } from "@/components/AuthProvider"; -const CheckIcon = () => ( - - - -); - -const XIcon = () => ( - - - -); - -const comparison = [ - { feature: "Version history & diff view", closedNote: true, promptBase: false, flowGPT: false, notion: false }, - { feature: "Private by default", closedNote: true, promptBase: false, flowGPT: false, notion: true }, - { feature: "AI prompt refinement", closedNote: true, promptBase: false, flowGPT: false, notion: false }, - { feature: "OCR — import from screenshots", closedNote: true, promptBase: false, flowGPT: false, notion: false }, - { feature: "Prompt chaining", closedNote: true, promptBase: false, flowGPT: true, notion: false }, - { feature: "Built specifically for prompts", closedNote: true, promptBase: true, flowGPT: true, notion: false }, -]; - -const features = [ - { - badge: "NEW", - title: "Version History", - description: "Every edit is tracked. See exactly what changed between drafts with a visual diff, and restore any previous version in one click.", - icon: ( - - - - ), - }, - { - badge: null, - title: "AI Refinement", - description: "Paste a rough idea and let AI restructure it into a clean, reusable prompt — using your own API key.", - icon: ( - - - - ), - }, - { - badge: null, - title: "OCR Import", - description: "Photograph a whiteboard, screenshot a chat, or upload any image — closedNote extracts the text and saves it as a prompt.", - icon: ( - - - - ), - }, - { - badge: null, - title: "Prompt Chains", - description: "String prompts together into multi-step workflows. Output from one step feeds directly into the next.", - icon: ( - - - - ), - }, -]; - -export default function MarketingHome() { - const { prompts } = usePrompts(); - const { user } = useAuth(); +function HomeContent() { + const { prompts: allPrompts, loading, error } = usePrompts(); + const { loading: authLoading } = useAuth(); + const [searchQuery, setSearchQuery] = useState(""); + const [filters, setFilters] = useState<{ + query: string; + model: PromptModel | ""; + }>({ query: "", model: "" }); + const [activeCollection, setActiveCollection] = useState< + string | undefined + >(); + + useEffect(() => { + if (typeof window !== "undefined") { + const urlParams = new URLSearchParams(window.location.search); + const collection = urlParams.get("collection"); + if (collection) setActiveCollection(collection); + } + }, []); + + useEffect(() => { + setFilters((prev) => ({ ...prev, query: searchQuery })); + }, [searchQuery]); + + const filteredPrompts = useMemo(() => { + return filterPrompts(allPrompts, { + query: filters.query || undefined, + model: filters.model || undefined, + collection: activeCollection, + }); + }, [filters, allPrompts, activeCollection]); + + const promptsByCollection = useMemo(() => { + return groupPromptsByCollection(filteredPrompts); + }, [filteredPrompts]); + + const collections = Object.keys(promptsByCollection).sort(); return ( - } sidebar={null}> -
- - {/* ── Hero ── */} -
-
- - New — Version History is live -
- -

- - Prompts are living - -
- - documents. - -

- -

- PromptBase stores them. Notion organizes them. closedNote is the only tool that - remembers how they evolved — every draft, every edit, every version. -

- -
- {user ? ( - <> - - Open my prompts - - - New prompt - - - ) : ( - <> - - Get started free - - - Read the docs - - - )} + + } + sidebar={ + allPrompts.length > 0 ? ( + + ) : null + } + > + {error ? ( +
+
+

Failed to load prompts

+

{error}

- - {/* ── Powered by ── */} -
-

Powered by

- -
- - {/* ── The Problem ── */} -
-
-

The gap

-

- Every tool stores prompts. -
- None of them remember. -

-
- -
- {[ - { - label: "PromptBase / FlowGPT", - verdict: "Built for sharing, not crafting", - description: "Great marketplaces for discovering prompts. But your prompts are public by default, and there's no memory of how they were built. When something stops working, you're starting from scratch.", - tone: "neutral", - }, - { - label: "Notion / Notes apps", - verdict: "Flexible but completely dumb", - description: "Notion doesn't know a prompt from a grocery list. No AI awareness, no refinement, no version tracking. You're just storing text with extra friction.", - tone: "neutral", - }, - { - label: "closedNote", - verdict: "Private, versioned, intelligent", - description: "Your prompts stay yours. Every edit is tracked with a visual diff. Iterate with AI refinement, import with OCR, and always know how you got to the version that works.", - tone: "highlight", - }, - ].map((card) => ( -
-

- {card.label} -

-

- {card.verdict} -

-

- {card.description} -

-
- ))} -
+ ) : (authLoading || loading) ? ( +
+ {[1, 2, 3].map((i) => ( +
+
+ {[1, 2, 3].map((j) => ( +
+ ))} +
+ ))}
- - {/* ── Comparison Table ── */} -
+ ) : allPrompts.length === 0 ? ( +
-

How we stack up

-

Built different.

+

+ closedNote +

+

+ Your personal prompt notebook. Create, organize, and refine AI + prompts with speed and clarity. +

- -
- - - - - - - - - - - - {comparison.map((row, i) => ( - - - - - - - - ))} - -
FeatureclosedNotePromptBaseFlowGPTNotion
{row.feature} - {row.closedNote ? : } - - {row.promptBase ? : } - - {row.flowGPT ? : } - - {row.notion ? : } -
-
-
- - {/* ── Version History Spotlight ── */} -
-
-
- - Version History - -

- Git for your prompts. -

-

- Every time you save an edit, closedNote snapshots the version. Jump back to any point in time, see exactly what changed line-by-line, and restore with one click — without overwriting your history. -

-
    - {[ - "Full version timeline on every prompt", - "Visual diff — green added, red removed", - "Restore any version without losing history", - "No bloat — only versions when content changes", - ].map((point) => ( -
  • - - {point} -
  • - ))} -
-
- - {/* Visual mockup */} -
- {/* Window chrome */} -
-
-
-
- Version History — Code Review Prompt -
-
- {/* Timeline */} -
- {[ - { v: "v3", date: "Mar 16", active: false }, - { v: "v2", date: "Mar 15", active: true }, - { v: "v1", date: "Mar 14", active: false }, - ].map((item) => ( -
-
{item.v}
-
{item.date}
-
- ))} -
- {/* Diff */} -
- - Act as a coding assistant. - - {" "} - - You are an expert software engineer. - - {" "} - Review the following code and identify bugs, security issues, or performance problems.{" "} - - Be specific and actionable. - -
-
-
- - Restore v2 - -
+
+
+ Powered by
+
+
- - {/* ── Features Grid ── */} -
-
-

Everything included

-

One tool. Everything you need.

-
-
- {features.map((feature) => ( -
-
-
- {feature.icon} -
-
-
-

{feature.title}

- {feature.badge && ( - - {feature.badge} - - )} -
-

{feature.description}

-
-
+ ) : ( +
+
+ {collections.length === 0 ? ( +
+

+ No prompts found matching your filters. +

+
+ ) : ( +
+ {collections.map((collection) => ( + + ))}
- ))} -
-
- - {/* ── CTA ── */} -
-

- Your prompts deserve better. -

-

- Stop losing great drafts. Start building a prompt library that actually remembers how it was built. -

-
- - {user ? "Go to my prompts" : "Get started — it's free"} - - {!user && ( - - Sign in - )}
- -
+ )} ); } + +export default function Home() { + return ( + Loading...
}> + + + ); +} diff --git a/app/prompts/new/page.tsx b/app/prompts/new/page.tsx index 1b30e23..76010ab 100644 --- a/app/prompts/new/page.tsx +++ b/app/prompts/new/page.tsx @@ -13,7 +13,7 @@ export default function NewPromptPage() { } sidebar={null}>
← Back diff --git a/app/settings/page.tsx b/app/settings/page.tsx index 3aa3b8d..a405f73 100644 --- a/app/settings/page.tsx +++ b/app/settings/page.tsx @@ -87,7 +87,7 @@ export default function SettingsPage() { const result = await deleteAccount(); if (result.ok) { - router.push("/"); + router.push("/home"); } else { setError(result.error); setIsDeleting(false); diff --git a/app/signup/page.tsx b/app/signup/page.tsx index 5a0ab1a..ab071ce 100644 --- a/app/signup/page.tsx +++ b/app/signup/page.tsx @@ -45,7 +45,7 @@ export default function SignupPage() { setShowEmailConfirmation(true); } else { // User created and logged in successfully - router.push("/dashboard"); + router.push("/"); } } catch (err) { setError("An unexpected error occurred. Please try again."); diff --git a/components/Header.tsx b/components/Header.tsx index 9183e11..0b62655 100644 --- a/components/Header.tsx +++ b/components/Header.tsx @@ -49,7 +49,7 @@ export function Header({ promptCount, showMobileMenu = true }: HeaderProps) { )} - + closedNote @@ -134,7 +134,7 @@ export function Header({ promptCount, showMobileMenu = true }: HeaderProps) {

{user.email}

- setIsAccountMenuOpen(false)} className="flex items-center gap-3 px-4 py-2.5 hover:bg-neutral-100 dark:hover:bg-neutral-800 transition-colors"> + setIsAccountMenuOpen(false)} className="flex items-center gap-3 px-4 py-2.5 hover:bg-neutral-100 dark:hover:bg-neutral-800 transition-colors">

My Prompts

diff --git a/components/PromptDetail.tsx b/components/PromptDetail.tsx index 677e846..2ebf426 100644 --- a/components/PromptDetail.tsx +++ b/components/PromptDetail.tsx @@ -73,7 +73,7 @@ export function PromptDetail({ prompt }: PromptDetailProps) { try { removeOptimistic(prompt.id); await deletePrompt(prompt.id); - router.push("/dashboard"); + router.push("/"); } catch (err) { setError("Failed to delete prompt. Please try again."); console.error("Error deleting prompt:", err); @@ -127,7 +127,7 @@ export function PromptDetail({ prompt }: PromptDetailProps) { return (
← Back to prompts diff --git a/components/PromptForm.tsx b/components/PromptForm.tsx index fcb048b..6a14b36 100644 --- a/components/PromptForm.tsx +++ b/components/PromptForm.tsx @@ -44,7 +44,7 @@ export function PromptForm() { }; addOptimistic(newPrompt); - router.push("/dashboard"); + router.push("/"); savePrompt(newPrompt) .then(() => refresh()) diff --git a/components/Sidebar.tsx b/components/Sidebar.tsx index 3a6c5c3..2563d9e 100644 --- a/components/Sidebar.tsx +++ b/components/Sidebar.tsx @@ -17,7 +17,7 @@ export function Sidebar({ prompts, activeCollection }: SidebarProps) {