# ScrollToPrompt: a scrollbar minimap for AI chat history

> A TypeScript browser extension that injects markers into the scrollbar of ChatGPT, Claude and Gemini so a user can jump back to an earlier prompt, built on a modular adapter pattern with Shadow DOM isolation and no published releases.

**AhmadHassan-BTed/ScrollToPrompt** — Navigation minimap extension for modern AI chat interfaces, injecting responsive scrollbar indicators via Shadow DOM isolation.

- Repository: https://github.com/AhmadHassan-BTed/ScrollToPrompt
- Stars: 1,280 · Forks: 0
- Language: TypeScript
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/ahmadhassan-bted-scrolltoprompt

## The problem is that AI chat transcripts scroll forever

A long conversation with a chat assistant becomes a wall of messages with no table of contents. Scrolling back to find the prompt where something was decided means either scrolling or using the browser's find, which locates text but does not give a visual map of where the prompts sit in the thread. The project notes frame the goal as a Minimap-like experience for chat history, so that context is always one click away.

ScrollToPrompt is a browser extension that draws markers into the scrollbar area of supported chat interfaces. Each marker corresponds to a prompt the user sent, and clicking one scrolls the transcript to that point. The description calls it a navigation minimap extension for modern AI chat interfaces, injecting responsive scrollbar indicators via Shadow DOM isolation.

The target users are people who use AI assistants heavily enough that transcripts get long: developers iterating on code with a model, researchers working through a long reasoning chain, or anyone who has lost the thread of a conversation that kept going. The scope is narrow on purpose. It is a navigation aid, not a client, not a prompt manager, and it does not touch the messages themselves.

## Site specific adapters keep the engine separate from the DOM

The architecture is a modular adapter pattern, and the project notes are explicit that the intent is high cohesion and zero coupling between platform-specific logic and the core engine. The folder structure under `src/` shows the split: `adapters/` for site-specific logic, `core/` for business logic and the engine, `components/` for isolated UI components built on Shadow DOM, `background/` for service worker logic, `content/` for content script entry points, `types/` for global TypeScript definitions, `utils/` for shared utility functions, and `assets/` for static assets and icons.

Adapters exist for ChatGPT, Claude and Gemini, and they are described as handling DOM selection. That is the crux of the design. Each assistant renders its transcript differently, and those layouts change without notice, so the selector knowledge is confined to one file per site. The engine above it never asks which site it is running on; it asks the adapter.

The rendering side is equally isolated. The UI layer is a Shadow DOM component system, and the reason given is to prevent styling conflicts with the host page. A scrollbar overlay injected into a page that has its own stylesheet is exactly the situation where a host rule like `div { position: fixed }` or a global `*` reset can wreck a naive implementation. Shadow DOM gives the extension a styling boundary that the host page does not reach into.

## MutationObserver with debounced rendering is the performance bet

Chat transcripts do not arrive all at once. They stream in token by token, and new messages push the document height around while the user may be scrolling. The notes list high performance as a feature and describes the mechanism as optimized `MutationObserver` logic with debounced rendering.

The problem that solves is straightforward. A naive implementation that re-scans the whole transcript on every DOM mutation would do a large amount of work for a change that usually touches one text node, and during streaming that mutation rate is high. A MutationObserver gives a targeted callback, and the debounce collapses a burst of mutations into a single redraw. The result is that the marker rail stays in sync with the transcript without the extension competing with the page for main thread time.

The other listed behaviour is theme awareness, described as dynamic styling that adapts to both light and dark modes. Since the markers are drawn over the host page's own scrollbar region, they have to remain legible whether the user is running a light or a dark interface, and the sites supported all offer both.

## Building and loading the extension from source

The prerequisites are Node.js v18 or newer and a package manager, with npm, pnpm or yarn listed as acceptable. The installation path documented is a development path, three commands from a clean checkout:

```bash
git clone https://github.com/AhmadHassan-BTed/ScrollToPrompt.git
```

Then install the dependencies and start the development server:

```bash
npm install
```

```bash
npm run dev
```

The project is bundled with Vite using `@crxjs/vite-plugin`, and the scripts in package.json confirm the mapping: `dev` runs `vite`, `build` runs `tsc && vite build`, `preview` runs `vite preview`, `test` runs `vitest`, and `lint` runs ESLint across TypeScript files with `--max-warnings 0`. Formatting is handled by Prettier, and a `prepare` script runs `husky install` so a pre-commit hook is set up on install.

Loading the built extension into a browser is a manual step. Open `chrome://extensions` in Chrome, Brave or Edge, enable Developer Mode, click Load Unpacked, and select the `dist` folder produced by the build. The documentation is specific about the folder, so an incorrect path here is the most likely reason a first attempt fails.

## The privacy claim and the API URL do not obviously agree

The feature list includes privacy first, zero data collection, and the note that all logic runs locally in your browser. That is the claim a reader will take away from the README.

The repository complicates it. A `.env.example` file at the root defines an extension configuration with `VITE_DEBUG_MODE=false` and `VITE_API_URL=https://api.scrolltoprompt.com`. A Vite-prefixed variable is read at build time and ends up in the bundled output, so a URL to a project-owned API domain is part of the configuration the project ships.

The documentation does not explain what that endpoint is used for, and the project notes do not describe any request to a server. It may be unused scaffolding, a debug hook, or something in progress, and none of that can be confirmed from what is written here. What can be said is that a reader who cares about the zero data collection claim should read `dist` after a build and check for network calls rather than taking the README at face value.

Privacy is otherwise handled in the ordinary way for an extension of this type. The description says all logic runs locally, and the repository ships no analytics or telemetry dependencies in package.json, whose only runtime dependencies are `clsx` and `tailwind-merge` for class name handling.

## Two supporting directories that are not in the src folder

The top level of the repository is broader than the `src/` tree, and the extra entries hint at how the extension is assembled. There are `background/`, `content/` and `popup/` directories alongside `src/`, plus `assets/`, `docs/`, a `manifest.json` and a `vite.config.ts`.

That duplication is the practical wrinkle of a browser extension built with a bundler. The manifest and the popup are extension surfaces that the Vite build has to emit at known paths, and the instruction to load the `dist` folder reflects that the final layout is produced by the build rather than matching the source tree. Contributors following `src/` alone will not find everything that ships.

The project also carries the usual governance files: CONTRIBUTING.md, CODE_OF_CONDUCT.md, SECURITY.md for reporting vulnerabilities, SUPPORT.md, CHANGELOG.md, a separate ROADMAP.md, and an .editorconfig with an .env.example for local configuration. The project asks contributors to read CONTRIBUTING.md and CODE_OF_CONDUCT.md, and points vulnerability reports at SECURITY.md.

## An unfinished roadmap and no published releases

The roadmap file and the roadmap section in the README list four open items: support for Perplexity and Poe, customizable marker colors, a search-to-prompt feature, and support for localized prompt detection. Two of these are worth noting for adoption decisions.

Perplexity and Poe are not supported today, so the extension covers three assistants rather than the wider set. Localized prompt detection is on the list, which implies that detection of where a user prompt begins depends on matching text in a specific language. On a chat interface running in another language, the markers may not line up correctly. That is a real boundary on the tool's usefulness, and it is a stated limitation rather than a guess.

There is also a version story to be aware of. package.json declares version 1.0.0 and the repository has no GitHub releases, so there is no tagged artifact to install and no changelog entry tied to a release page. The repository is not archived and the last push was on 2026-06-30, so work is continuing, but the only install path the documentation gives is the manual load-unpacked route described above.

The licence is MIT, with the LICENSE file at the repository root. For a browser extension that injects UI into other people's pages, that matters mainly for redistribution: the code is easy to fork and rebrand, and the attribution requirement in the licence file travels with any copy.

## Conclusion

Adopt ScrollToPrompt if you work in long AI chat sessions and want to jump back to a specific prompt in ChatGPT, Claude or Gemini without scrolling, and you are willing to load an unpacked extension from source. Do not adopt it for Perplexity or Poe, which the roadmap lists as not yet supported, or if you need a store-installed release, since the repository has no GitHub releases. Verify first what the extension actually sends over the network, because the .env.example file defines a VITE_API_URL pointing at api.scrolltoprompt.com even though the README claims zero data collection.

## FAQ

### Which AI chat sites does ScrollToPrompt support?

The extension ships site-specific adapters for ChatGPT, Claude and Gemini, with support for Perplexity and Poe listed as an open roadmap item.

### How do I install ScrollToPrompt in Chrome?

Clone the repository, run `npm install` and `npm run build`, then open `chrome://extensions`, enable Developer Mode, click Load Unpacked and select the `dist` folder generated by the build. The documentation describes the same steps for Brave and Edge.

### Does ScrollToPrompt collect any data?

The project notes state zero data collection and that all logic runs locally in your browser, and the runtime dependencies are limited to clsx and tailwind-merge. The `.env.example` file does define a `VITE_API_URL=https://api.scrolltoprompt.com` value, and the documentation does not explain what it is used for.

### Why does ScrollToPrompt use Shadow DOM for its markers?

The UI layer is a Shadow DOM component system, and the stated reason is to prevent styling conflicts with the host page, since injected UI sits inside a page that ships its own styles.

### What is the development workflow for ScrollToPrompt?

The package.json scripts are `dev` for vite, `build` for `tsc && vite build`, `preview` for `vite preview`, `test` for vitest, `lint` for ESLint over TypeScript with `--max-warnings 0`, and `format` for Prettier over the src directory.

## Sources

- [AhmadHassan-BTed/ScrollToPrompt on GitHub](https://github.com/AhmadHassan-BTed/ScrollToPrompt)
- [Issues](https://github.com/AhmadHassan-BTed/ScrollToPrompt/issues)
- [License: MIT](https://github.com/AhmadHassan-BTed/ScrollToPrompt/blob/main/LICENSE)
- [README](https://github.com/AhmadHassan-BTed/ScrollToPrompt/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/ahmadhassan-bted-scrolltoprompt
