File size: 10,142 Bytes
a2234fc
 
 
 
 
 
 
 
 
 
bcef2c3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
00a4363
 
34b0226
00a4363
bcef2c3
 
 
 
 
 
 
 
 
 
 
 
66de9c8
bcef2c3
 
b74c6ae
bcef2c3
 
 
00a4363
 
 
7299acc
00a4363
bcef2c3
 
00a4363
 
 
 
 
 
94b5741
00a4363
 
 
 
 
 
 
 
34b0226
00a4363
 
eb03313
34b0226
00a4363
34b0226
00a4363
 
34b0226
 
 
 
 
 
bdd1640
 
 
 
 
 
 
 
 
 
 
 
 
34b0226
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66de9c8
34b0226
00a4363
 
 
 
 
 
 
94b5741
00a4363
 
 
bcef2c3
00a4363
 
 
 
 
 
 
 
 
 
 
 
 
bcef2c3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
00a4363
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
---
title: NoteStack Test
emoji: 📚
colorFrom: indigo
colorTo: purple
sdk: docker
app_port: 7860
pinned: false
---

<p align="center">
  <picture>
    <source media="(prefers-color-scheme: dark)" srcset="marketing/logo/notestack-logo.svg">
    <img src="marketing/logo/notestack-logo-dark.svg" alt="Notestack" height="64">
  </picture>
</p>

<h3 align="center">The ultimate NotebookLM alternative for writers, bloggers and newsletters.</h3>

<p align="center">
  Your knowledge, in orbit. <a href="https://notestack.ai">notestack.ai</a>
  · <a href="https://notestack.ai/notebooklm-alternative">Notestack vs NotebookLM</a>
  · <a href="https://notestack.ai/blogs">Blog</a>
</p>

<p align="center">
  <a href="marketing/notestack-launch.mp4">
    <img src="marketing/notestack-launch-poster.jpg" alt="Watch the Notestack launch trailer" width="820">
  </a>
  <br>
  <sub>▶ Watch the launch trailer (82 s, sound on) · <a href="https://notestack.ai/demo.mp4">product demo (47 s)</a></sub>
</p>

Notestack turns any blog, newsletter, website or folder of markdown into a grounded research notebook, then into audio
overviews, videos and launch kits, all traced back to the exact lines the writer actually wrote.

- Design doc: [docs/DESIGN.md](docs/DESIGN.md)
- Foundations task list: [docs/PHASE0.md](docs/PHASE0.md)

## Why Notestack instead of NotebookLM

NotebookLM is a great general research notebook. Notestack is built for people who publish: it starts from your whole
archive, stays in sync with it, cites the exact lines behind every answer, and turns what you wrote into things you can ship.

| | Notestack | NotebookLM |
| --- | --- | --- |
| Getting your writing in | Syncs any blog, newsletter or site (Substack, Ghost, WordPress, Medium, RSS, or crawled with Firecrawl), plus md, txt, html and pdf uploads | Add sources one at a time |
| Stays in sync | New posts arrive automatically | Re-add sources by hand |
| Citations | Exact line ranges, verified before you see them | Passage level citations |
| Not in your sources | Says so; unverifiable claims are dropped | Grounded, passage citations |
| Audio | Two hosts on ElevenLabs voices, or your consented voice clone | Two host overviews, Google voices |
| Video | 9:16 shorts, 16:9 explainers, 1:1 audiograms, quote cards | Video overviews |
| Publishing | Launch Kits (threads, LinkedIn, Notes, Bluesky, SEO, carousels) and auto posting | Not a publishing tool |
| Your voice | Voice profile learned from your posts, used in every draft | General purpose writing |
| Seeing your archive | Topic constellation with rising and dormant topics, evergreen resurfacing | Idea Constellations per notebook |

The full comparison lives at [notestack.ai/notebooklm-alternative](https://notestack.ai/notebooklm-alternative).

## Layout

```
backend/    FastAPI + SQLAlchemy + Alembic, Postgres job queue worker, DSPy (LLM agnostic, Z.ai first)
frontend/   React + Vite + TS: night sky landing, pricing, blog, auth, Mission Control
renderer/   Remotion compositions + render service that uploads to R2 via presigned PUT; trailer and demo scripts
marketing/  Launch trailer, poster and logo files
docs/       Design doc and task lists
```

## Run locally

```bash
cp .env.example .env            # fill LLM_API_KEY (Z.ai), GOOGLE_CLIENT_ID, RESEND_API_KEY
docker compose up --build
```

- App: http://localhost:5173, API: http://localhost:8000/docs, MinIO console: http://localhost:9001
- Local storage is MinIO standing in for R2. Presigned URLs point at `http://minio:9000`, so add
  `127.0.0.1 minio` to your hosts file for browser uploads to work locally.
- With `EMAIL_PROVIDER=console`, verification codes print in the `api` logs.

Without Docker (one API process does everything):

```bash
cd backend && python -m venv .venv && .venv/Scripts/pip install -r requirements.txt
alembic upgrade head && uvicorn app.main:app --reload     # SQLite at backend/notestack.db
cd frontend && npm install && npm run dev
cd renderer && npm install && npm start                    # only needed for videos, quote cards, carousels
```

- With `ENV=development` the API runs the job worker in process (`RUN_WORKER_IN_API`), so syncing,
  topic mapping, audio and launch kits work without a second terminal. In production run
  `python -m app.worker` separately and set `RUN_WORKER_IN_API=false`.
- With no R2 settings, files live on local disk under `backend/.storage` and are served through
  signed `/api/storage/local/...` URLs (range requests supported for audio and video seeking).
- Audio needs `ELEVENLABS_API_KEY`; everything text based needs `LLM_API_KEY`.
- Launchpad: posts (text, images, videos from your Library; not audio) go to X and LinkedIn at their
  scheduled time through a `publish_post` job. Set up the developer apps and keys as described in
  `backend/.env.example`:
  - `X_CLIENT_ID` / `X_CLIENT_SECRET`: the X app's **OAuth 2.0 Client ID and Client Secret** (Read and write,
    Web App, callback `{API_URL}/api/social/x/callback`, scopes incl. `media.write`).
  - `LINKEDIN_CLIENT_ID` / `LINKEDIN_CLIENT_SECRET`: products "Sign In with LinkedIn using OpenID Connect" and
    "Share on LinkedIn", redirect `{API_URL}/api/social/linkedin/callback`.
  - `API_URL` must be reachable from the internet for the callbacks (an https tunnel locally).
  X and LinkedIn posts need a connected account. X tokens are refreshed automatically; LinkedIn connections
  last about 60 days. If a connection goes down (expired, revoked on the platform, or disconnected here) its
  scheduled posts are **paused** and never attempted; reconnecting the same account resumes the ones still
  ahead, and missed ones wait for a new time. Bluesky connects with an app password; Substack Notes has no API,
  so those posts arrive as an email reminder at send time.

## What is in the app

| Menu | Does |
| --- | --- |
| Mission Control | Pre-flight checklist, jobs in flight, sources, notebooks, recent launches, upcoming posts |
| Notebooks | Group posts, chat with cited answers (history kept), summaries, audio overviews, videos, quote cards |
| Sources | Connect feeds (Substack archive included), import one URL, upload md/txt/html/pdf, read posts by line |
| Topic map | LLM tagged topics per post, merged into a constellation; make a notebook from any topic |
| Voice profile | Writing voice built from your posts (editable), host voices, consented voice cloning |
| Video and audio | Audio overviews, 9:16 shorts, 16:9 explainers, 1:1 audiograms, quote cards |
| Launch Kit | Hooks, X thread, LinkedIn, Substack Notes, Bluesky, SEO pack, carousel, quote cards, all editable |
| Launchpad | Calendar and agenda, auto posting to X, LinkedIn and Bluesky, email reminders, tracked links, engagement |
| Archive | Every generated artifact with filters, players, downloads, retry and delete |
| Resurfacing | Evergreen scores and reshare angles for old posts, on this day, straight into a kit or the calendar |
| Settings | Profile, workspace, privacy, plan usage meters, connections, sign out everywhere, delete |

## Key choices

| Concern | Where |
| --- | --- |
| Cloudflare R2 storage (keys, presign, uploads) | `backend/app/services/storage.py`, `backend/app/routers/storage.py` |
| Resend email + unsubscribe + campaigns | `backend/app/services/email.py`, `backend/app/worker.py` |
| Google + email code auth, JWT revocation | `backend/app/auth.py`, `backend/app/routers/auth.py` |
| Research over posts as files (no embeddings) | `backend/app/corpus.py`, `backend/app/pipeline/research.py` |
| LLM provider (swap by env) | `backend/app/llm/provider.py`, `.env` `LLM_*` |
| Three plans, billing off | `backend/app/services/plans.py`, `BILLING_ENABLED` |
| Blog posts | `frontend/src/content/blogPosts.ts` (`/blogs`, `/blogs/:slug`) |
| Logo | `frontend/public/logo.svg` (white tile, black ringed planet); lockups in `marketing/logo/` |
| Sky background | `frontend/src/components/SkyCanvas.tsx` |

## Switching LLM providers

```bash
# Z.ai (default). Cheaper: glm-5.3-flash. Free for dev: glm-4.7-flash
LLM_MODEL=openai/glm-5.3  LLM_API_BASE=https://api.z.ai/api/paas/v4  LLM_REASONING_EFFORT=low
# Anthropic
LLM_MODEL=anthropic/claude-sonnet-5  LLM_API_BASE=
# OpenAI
LLM_MODEL=openai/gpt-5  LLM_API_BASE=
```

## Videos and brand

| Asset | File | Rebuild |
| --- | --- | --- |
| Launch trailer (82 s, "Coming soon") | `marketing/notestack-launch.mp4` | `renderer/scripts/make_launch_vo.py`, then `make_launch_music.py`, then `npx remotion render src/index.ts LaunchTrailer ../marketing/notestack-launch.mp4` |
| Landing demo (47 s) | `frontend/public/demo.mp4` | `renderer/scripts/make_demo_vo.py`, then `npx remotion render src/index.ts LandingDemo ../frontend/public/demo.mp4`, then bump `DEMO_VERSION` in `Landing.tsx` |
| Logo | `marketing/logo/` (mark, lockup for dark and light backgrounds) | Mark is `frontend/public/logo.svg`; the renderer uses a copy at `renderer/public/logo.svg` |

Narration is voiced on ElevenLabs (run the scripts from `backend/` with `PYTHONPATH=.`); music is synthesized, no samples.
Preview any composition with `cd renderer && npm run studio`.

## For AI agents

`https://notestack.ai/llms.txt` tells assistants and crawlers what Notestack is, which pages answer which questions, and
what not to index. It is generated on every build from `frontend/seo/sitemap.ts` alongside `sitemap.xml` and `robots.txt`,
so new blog posts appear in all three automatically.

## Roadmap

- [ ] Complete the checkout flow
- [ ] Delete a free tier knowledge base after one week, prompting the writer to upgrade to keep it
- [ ] Onboarding message: the free tier indexes the first 5 posts; upgrade to index the rest
- [ ] An inner "galaxy" view inside the topic map, using a statistical word model to link related pieces of knowledge
- [ ] Make the main app view look good on mobile
- [ ] Explore a whole website through its `llms.txt` and sitemap XML, so every post and page gets included

## Rules

- No em dashes in any UI, email or generated copy. `npm run check:copy` and
  `app/llm/postprocess.py` enforce it.
- Palette is black, `#217cff` and white only.