Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 89 additions & 51 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
<p align="center">
<img src="screenshots/closedNotes.png" alt="closedNote" style="max-width:100%;height:auto;" />
</p>

# closedNote

> **Prompts are living documents. closedNote is the only prompt manager that remembers how they evolved.**
Expand All @@ -9,73 +13,118 @@
[![License: MIT](https://img.shields.io/badge/license-MIT-green?style=flat-square)](LICENSE)
[![Deployed on Vercel](https://img.shields.io/badge/deployed-Vercel-black?style=flat-square&logo=vercel)](https://vercel.com)

**📊 Project Scope: 13 API Routes · 17 React Components · 25 Passing Tests**

---

## Explanation
## 🧠 The Story

PromptBase stores prompts. Notion organizes them. FlowGPT shares them. None of them remember how they got there.
I got tired of re-engineering my "perfect ChatGPT prompts" every time I needed a particular kind of answer. Then my mum started doing the same thing. Then my grandma. Then my classmates.

In real life, prompts evolve. You tweak your "code review prompt" three times, and by the fourth iteration you've forgotten what made version 2 actually work. There is no tool aimed at everyday users that tracks how your prompts change over time, until now.
Meanwhile, prompt engineers were dropping tips on X and Stack Overflow, but nobody had a good place to store, iterate on, and *remember* them.

closedNote is built on one thesis: **a prompt is not a sticky note. It's a document with a history.**
So I built one, and added version control, because the best prompt you'll ever write is usually the fourth draft of something you thought was broken.

Beyond versioning, closedNote adds structure: organize into collections, chain into multi-step workflows, refine with AI, and import from any image via OCR, all private by default.

---

## Version History, git for your prompts
## ⚖️ How We Compare

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.
<p align="center">
<img src="screenshots/compare.png" alt="compare" width="70%" />
</p>

![Version History](./screenshots/versioning01.png)
---

- Full version timeline on every prompt
- Visual diff, additions in green, removals in red
- Restore any version without losing the history chain
- Versions only created when content actually changes, no noise
## 🏗️ Architecture & Fault Tolerance

---
closedNote is a full-stack **Next.js 14** application backed by **Supabase (PostgreSQL + Auth)**. The core architectural goal is simple: **every feature that matters (writing, versioning, change tracking, searching, chaining) must feel instant, safe, and impossible to lose**.

### Versioning and Change Tracking (Core System)

- **Automatic version snapshots** are created only when content actually changes (no noisy duplicates).
- Every version is **comparable and restorable**, so you can experiment freely without fear of losing a working draft.

### Prompt Threads (Multi-step Workflows)

- **Threads** model prompts as ordered steps where each step can be refined independently.
- Each step has its **own version history**, so workflows evolve without breaking the whole chain.

## All Features
### Search & Navigation (Fast Retrieval)

- **Version History**, track every draft with a visual diff and one-click restore *(new)*
- **Instant Search**, command palette (`⌘K`) across your entire library
- **Collections**, group prompts by topic, project, or use case
- **AI Refinement**, clean up rough ideas into polished, reusable prompts using your own API key
- **OCR Import**, upload a screenshot or photo, extract the text, save it as a prompt
- **Prompt Chains**, link prompts into multi-step workflows where each output feeds the next
- **One-Click Copy**, paste straight into ChatGPT, Claude, Cursor, or wherever you work
- **Private by Default**, row-level security ensures your data is never accessible to others
- **Dark Mode**, full theme support, system-aware
- **Fully Responsive**, works on mobile without crying
- A global **command palette (`⌘K` / `Ctrl+K`)** provides fast navigation across prompts, collections, and threads.
- Search is designed to keep your library usable even as it scales.

### Privacy and Security by Design

- **Supabase Row-Level Security (RLS)** enforces access control at the database layer.
- Every prompt, version, collection, and thread is strictly scoped to the authenticated user’s ID.

---

## Demo
## ✨ Core Features

### Dashboard
### 1. Prompt Threads (Chains)

![Desktop Screenshot 1](./screenshots/desktop1.png)
This is closedNote's biggest differentiator. Instead of writing one massive, brittle prompt, you can break complex tasks into discrete, testable steps. Chain prompts into multi-step workflows where each output feeds the next.

![Desktop Screenshot 2](./screenshots/desktop2.png)
<p align="center">
<img src="screenshots/prompt-chains-detail.png" alt="Prompt chain workflow showing sequential steps" width="70%" />
</p>

### Prompt Editor
### 2. Version History (Git for Prompts)

![Desktop Screenshot 3](./screenshots/desktop3.png)
Every edit is automatically snapshotted. Powered by Google's `diff-match-patch` algorithm, you get a visual, character-level diff of what changed (additions in green, removals in red) and one-click restoration without losing your timeline.

### Image to Text (OCR)
<p align="center">
<img src="screenshots/version-history-diff.png" alt="Version history with visual character diffs" width="70%" />
</p>

### 3. AI Refinement & Organization

Turn rough ideas into structured prompts using your own API keys. Group prompts into Collections, and instantly search your entire library via the `⌘K` command palette.

---

## ✅ All Features

![OCR Feature](./screenshots/OCR.png)
- **Version History** - track every draft with a visual diff and one-click restore
- **Prompt Threads** - link prompts into multi-step workflows where each output feeds the next
- **OCR Import** - upload a screenshot or photo, extract the text, save it as a prompt
- **Instant Search** - command palette (`⌘K`) across your entire library
- **Collections** - group prompts by topic, project, or use case
- **AI Refinement** - clean up rough ideas into polished, reusable prompts using your own API key
- **One-Click Copy** - paste straight into ChatGPT, Claude, Cursor, or wherever you work
- **Private by Default** - row-level security ensures your data is never accessible to others
- **Dark Mode** - full theme support, system-aware
- **Fully Responsive** - works on mobile without crying

### Mobile
---

## 🎬 Demo

### Dashboard

| | |
|---|---|
| ![Mobile Screenshot 1](./screenshots/mobile1.png) | ![Mobile Screenshot 2](./screenshots/mobile2.png) |
|--|--|
| ![Desktop Screenshot 1](./screenshots/dashboard-light.png) | ![Desktop Screenshot 2](./screenshots/dashboard-dark.png) |

### Prompt Editor

<p align="center">
<img src="screenshots/new-prompt.png" alt="prompt editor" width="70%" />
</p>

### Image to Text (OCR)

<p align="center">
<img src="screenshots/ocr-import.png" alt="Version history with visual character diffs" width="70%" />
</p>

---

## Tech Stack
## 🧱 Tech Stack

| Layer | Technology |
|---|---|
Expand All @@ -89,7 +138,7 @@ Users without API keys get full prompt management + offline OCR. AI features unl

---

## Tests
## 🧪 Tests

![Test Results](./screenshots/test.png)

Expand All @@ -98,20 +147,9 @@ Users without API keys get full prompt management + offline OCR. AI features unl
```bash
npm test
```

---

## The Story

I got tired of re-engineering my "perfect ChatGPT prompts" every time I needed a particular kind of answer. Then my mum started doing the same thing. Then my grandma. Then my classmates.

Meanwhile, prompt engineers were dropping tips on X and Stack Overflow, but nobody had a good place to store, iterate on, and *remember* them.

So I built one, and added version control, because the best prompt you'll ever write is usually the fourth draft of something you thought was broken.

---

## Run Locally
## Run Locally

```bash
git clone https://github.com/aboderinsamuel/closedNote.git
Expand All @@ -132,15 +170,15 @@ NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key

---

## Deploy
## 🚀 Deploy

1. Fork this repo
2. Import to [Vercel](https://vercel.com) and add the two env vars above
3. In Supabase → Authentication → URL Configuration, add your Vercel domain to Redirect URLs

---

## Contributing
## 🤝 Contributing

Got ideas? Contributions welcome.

Expand All @@ -153,7 +191,7 @@ See [open issues](https://github.com/aboderinsamuel/closedNote/issues) for what'

---

## Built by
## 👤 Built by

**Samuel Aboderin**, Computer Engineering, UNILAG 🇳🇬

Expand Down
1 change: 0 additions & 1 deletion app/api/chat/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ async function callOpenAI(

export async function POST(req: Request) {
try {
// Verify the caller is an authenticated user before doing any work
const user = await getUserFromRequest(req);
if (!user) {
return NextResponse.json(
Expand Down
1 change: 0 additions & 1 deletion app/api/ocr/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ async function callOpenAIVision(apiKey: string, arrayBuf: ArrayBuffer, mimeType:

export async function POST(request: Request) {
try {
// Verify the caller is an authenticated user before doing any work
const user = await getUserFromRequest(request);
if (!user) {
return NextResponse.json(
Expand Down
Loading
Loading