Self-hosted service
nikunjsingh93/react-glass-keep avatar
nikunjsingh93/react-glass-keep

Glass Keep is a self-hosted Keep clone whose clients are useless without its server

Glass Keep is Keep Notes alternative using Glass design. Docker Server, Tauri Clients and PWA

603 stars53 forksJavaScriptMIT

At a glance

What is it?
nikunjsingh93/react-glass-keep is a Markdown notes app with a Vite and React web front end, an Express and SQLite API, Tauri 2 desktop and Android clients, and a PWA, and it ships a local Qwen assistant backed by a llama.cpp build compiled inside its Docker image. The most consequential line in the documentation is that the client apps are client apps only and a running server is required.
Who is it for?
Use Glass Keep if you want a self-hosted Keep alternative with Markdown, checklists, images, tags and a local AI assistant that never sends your notes to a cloud model. Do not adopt it if you need a client that works without a server, because the Windows, macOS and Android builds are clients only, and check the Node version constraint before you start, since the package requires Node 24.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

One server, three clients, and an explicit dependency between them

Glass Keep is a sleek, Keep-style notes app with Markdown, checklists, images, tag chips, colour themes, dark mode, drag-and-drop reordering, import and export, authentication and a glassy interface. It is built with Vite and React on the front end and a small Express and SQLite API behind it.

The architecture statement in the documentation is blunt and worth reading before anything else. The Windows, macOS and Android apps are client apps only, and a running Glass Keep server is required. Deploy the server using the Docker instructions, or connect to an existing instance, then enter its server URL in the app. The client apps do not install or run the server.

So the desktop and mobile builds are not a packaged version of the app. They are shells that point at a server you run. That is a deliberate design for a self-hosted tool, and it has an obvious consequence: the app is only as available as the machine running the Docker container.

The clients are built with Tauri 2 and keep offline data separate per server, which is a sensible detail, since someone using this for personal notes and someone testing it against a colleague's instance should not have their caches mixed.

The downloadable artefacts are a Windows .exe, an Android .apk and a macOS .dmg, taken from the GitHub release page. The web app is the same front end served as an installable progressive web app, installable on desktop and mobile.

The licence is MIT, and the package metadata records version 1.0.17 with the package name liquid-keep, marked private so it is never published to a registry.

The Docker image compiles llama.cpp from a pinned commit

The most surprising thing about this repository is how much of it is about building an inference server.

The Dockerfile does not install a model or download a binary. It builds llama.cpp from source, in a dedicated builder stage based on debian:trixie-slim, and pins the exact source archive to a commit hash:

dockerfile
FROM --platform=$BUILDPLATFORM debian:trixie-slim AS llama-builder
ARG TARGETARCH
RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates curl cmake ninja-build g++ libgomp1 && rm -rf /var/lib/apt/lists/*
WORKDIR /llama
RUN curl -fsSL https://github.com/ggml-org/llama.cpp/archive/620d2225cc436ab0b001e3200e590e3b286ef9ab.tar.gz | tar xz --strip-components=1

The build cross compiles for the target architecture, choosing a g++ package and a target triple per architecture, and it configures llama.cpp with the CPU variants enabled, the native instruction set off, the UI, tests, examples and curl off, and the server on. It then builds only the llama-server target with four jobs, and collects the licence files from the source tree into a /licenses directory, which is the kind of step most projects skip and some compliance processes require.

The reason for this is the local AI feature. The application does not call a cloud model, it runs a model on the server, and the model weights are downloaded only on first use, which the comment at the top of the Dockerfile says explicitly.

The second build stage is the web application itself, on node:24-trixie-slim, with npm ci run from a copied manifest so the dependency layer caches, then the source, the public directory and the server directory copied in.

The practical implication for a self-hosted user is that the first image build is a compile, not a pull. On a Raspberry Pi or a small VPS, cross-compiling llama.cpp is the long pole in the setup, and the target architecture handling in that RUN line is what makes one image definition serve both amd64 and arm64.

A 533 MB model that starts for questions and stops after 60 idle seconds

The private AI assistant is the feature that separates Glass Keep from a plain notes app, and its design is deliberately conservative about resources.

It uses Qwen with llama.cpp, and the documentation describes the properties in four bullets. Local inference: questions and note excerpts stay on your server, and no cloud AI key is required. It loads on demand, downloading a verified 533 MB model once, starting only when a question arrives, and stopping after 60 idle seconds. Answers are note-aware, using ranked note retrieval with query expansion, progressive answers and clickable source-note links. And it works across clients, so the web app, Windows, macOS and Android all use the same server AI, with support for English, Hindi and French, and no second model or vector service.

The on-demand behaviour is what makes this deployable. A resident 533 MB model in memory on a small server is a permanent tax, whereas a process that starts for a question and exits 60 seconds later costs nothing when nobody is asking.

The note-aware part is the more interesting engineering claim, and also the one with the most room to disappoint. Ranked retrieval over your own notes with query expansion is what turns a generic model into an assistant that knows your content, and clickable source links let you check the answer against the note it came from. But the documentation itself points to a local AI guide that covers accuracy limitations, and it is worth reading that before you trust a summary of a note you care about.

The no-second-vector-service claim is worth noting too, because the usual architecture for this is an embedding model plus a vector database. Doing retrieval without one keeps the deployment to a single process and a single 533 MB download, at the cost of the retrieval quality that a purpose built vector index would give you.

Collaboration with view-only roles and a stale save guard

The collaboration feature is the newest part of the app, and it is marked as new in the feature list, so the wording reflects a recent addition rather than a long settled behaviour.

Real-time collaboration for checklists is the headline. Multiple people can add and tick items together and see updates instantly. Collaboration on notes goes further, allowing people to co-edit Markdown notes and watch changes sync across collaborators. Collaborators are invited by username or email, and there is a view-only mode that opens a note without overwriting edits from others.

The last of those is a real design decision rather than a missing feature. In a shared editor, read access that is not read-only will eventually destroy someone else's work, and the project handles it by giving collaborators an explicit mode instead of relying on everyone clicking the right button.

The conflict handling is described in one sentence that is worth reading twice. Revision checks reject stale saves, and the editor keeps your draft and lets you download it before reloading. So when two people edit the same note and one saves first, the second does not lose their text: the save is refused, the draft survives locally, and the user is offered the draft as a download. Losing a paragraph to a concurrent save is the kind of failure that makes people stop trusting a notes app, and this is the specific mechanism that prevents it.

The bug fix list at the end of the documentation confirms the shape of the problem. One fix addressed an issue where opening notes in view mode would overwrite edits made in edit mode, which is the exact class of bug the view-only mode is meant to make impossible, and the conflict resolution was improved afterwards.

Multi-user auth with a first-run admin and a last-admin guard

The account model is described in the first feature block, and two details in it are more than ordinary.

There is registration, login with username and password, and sign out, and each user sees only their own notes. The first run is called out as secure: you supply INITIAL_ADMIN_USERNAME and INITIAL_ADMIN_PASSWORD when creating a new installation, which means the first administrator is defined by configuration at deployment time rather than by whoever opens the web page first.

There is also a secret recovery key that you download, and a sign in with secret key option, which is the answer to the question every self-hosted app eventually faces, namely what happens when the only administrator loses their password. A recovery key you stored at setup time is a workable answer.

The admin panel is a separate area, reachable from the three dots dropdown, and the documentation lists what it does. It can add a new user, and it can toggle new account creation, which is off by default. That default is the important part for an instance that is reachable from the internet: open registration on a self-hosted notes server is how you get spam notes, and the project ships with it closed.

The user list shows the name, the email or username, whether the user is an admin, the number of notes, the storage used, and when the account was created. Deleting a user deletes their notes as well, and the documentation notes that this is protected against deleting the last admin, which is the kind of guard that saves you from locking yourself out of your own server.

The dependency list backs the implementation up, with jsonwebtoken for sessions, bcryptjs for password hashing, express-rate-limit for throttling, dompurify for sanitising rendered content and cors for cross-origin access.

Notes, checklists, drawings, and the data paths out

The note model is broad enough to be worth a section of its own.

Text notes are Markdown with H1, H2 and H3 headings, bold, italic, strike, links, blockquotes and inline or fenced code, with a formatting toolbar available in both the composer and the modal edit mode, and a Smart Enter behaviour that continues lists or exits them on an empty line. Checklists support adding items, toggling them done and inline editing, with drag to reorder inside the modal and control of items directly from the notes grid without opening the modal. There are also drawing and handwritten notes with customisable brush sizes and colours.

Images attach in multiples with client side compression, appear as thumbnails in the grid and larger in the modal, and there is a fullscreen viewer with next and previous plus a download action.

Organisation is where the Keep lineage shows. Notes can be pinned, with pinned and others sections, tagged with tag chips entered as comma separated input, and there is a tag sidebar with counts, quick filters for all notes and all images, per-note colour themes, and search across the title, the Markdown text, tags, checklist items and image names. Grid cards truncate the body and the overflowing tag chips. Drag to reorder works within each section.

The data paths are the part to evaluate carefully if you plan to move in or out. You can export all notes as JSON and import JSON or ZIP, where an import merges and keeps existing notes. You can download a single note as a .md file. There are automatic JSON exports, downloadable every 1, 7 or 30 days while the app is open, which the documentation suggests you then sync yourself with Syncthing or another service, with no cloud provider setup required. And you can import from Google Keep by picking multiple .json files from a Takeout archive.

That automatic export cadence is a quiet but important design decision. The app is local-first in the sense that your notes live in its SQLite file, and the exports are the escape hatch that keeps them from being trapped there.

Node 24, a private package, and weekly releases

The build and release setup tells you how this project is maintained, and it is a small team shipping quickly.

The package is named liquid-keep, marked private so it is never published to npm, licensed MIT, and it requires Node 24, with the engine constraint written as greater than or equal to 24 and less than 25. That is a firm floor. Node 24 is a current release rather than a long term one, so a deployment pinned to an older Node has to upgrade, and an organisation that standardises on Node 20 will find this project does not support it.

The scripts show the whole workflow in one place. The dev script runs Vite and the API server together with concurrently, the API script runs the server on port 8080 in watch mode with NODE_ENV set to development, and the test script uses the Node built-in test runner over the files in tests/. The native scripts build the Tauri clients, with separate configs for macOS and Android, a version script that checks the version before a native build, and an icon preparation step for Android.

The release cadence is fast. The three most recent tags are v1.0.17 on 2026-10-20, v1.0.16 on 2026-10-19 and v1.0.15 on 2026-10-19, and the release notes are descriptive, with the last one titled as compact inline Ask AI and the previous one as Russian language support. Two releases on the same day is a project shipping continuously.

The repository root also carries a local_docker_run.sh script for running the stack without the full compose setup, a data/ directory for the SQLite file, a docs/ directory with the native app guide, the local AI guide and the export and restore guide referenced throughout the documentation, and a SECURITY.md file.

The practical caution for a self-hosted deployment is that this is a fast moving project on a recent Node, so pin the image tag you run rather than tracking latest, and read the CHANGELOG.md before upgrading.

Editorial conclusion

Use Glass Keep if you want a self-hosted Keep alternative with Markdown, checklists, images, tags and a local AI assistant that never sends your notes to a cloud model. Do not adopt it if you need a client that works without a server, because the Windows, macOS and Android builds are clients only, and check the Node version constraint before you start, since the package requires Node 24. Before deploying, set INITIAL_ADMIN_USERNAME and INITIAL_ADMIN_PASSWORD on the first run, decide whether the 533 MB model download on the server is acceptable to you, and read the export and restore guide so you know how your notes leave the system if you want them to.

Frequently asked questions

What is Glass Keep and how is it deployed?

It is a self-hosted, Keep-style notes application with a React and Vite front end, an Express and SQLite API, Tauri 2 desktop and Android clients and a PWA. The server is deployed with Docker, and the Windows, macOS and Android apps are clients only, so a running server is required.

Does Glass Keep have an AI assistant that calls a cloud API?

No. The assistant uses Qwen with llama.cpp running locally on the server, so questions and note excerpts stay on your server and no cloud AI key is needed. It downloads a verified 533 MB model on first use, starts only for questions and stops after 60 idle seconds.

How does Glass Keep handle two people editing the same note?

Revision checks reject stale saves, and the editor keeps your draft and lets you download it before reloading. Collaborators can also be given view-only mode so they cannot overwrite edits from others.

How do I set up the first administrator account in Glass Keep?

You supply INITIAL_ADMIN_USERNAME and INITIAL_ADMIN_PASSWORD when creating a new installation, so the first admin comes from deployment configuration. New account creation is off by default and can be toggled from the admin panel, and deleting the last admin is prevented.

Can I get my notes out of Glass Keep?

Yes. You can export all notes as JSON, import JSON or ZIP files that merge with existing notes, download individual notes as .md files, and enable automatic JSON exports every 1, 7 or 30 days while the app is open. Import from Google Keep through a Takeout archive is also supported.

What does running the Glass Keep Docker image involve?

The image builds llama.cpp from a pinned source commit in a builder stage, cross compiling for amd64 or arm64, and then builds the Node application in a second stage. Model weights are not baked in, they are downloaded on the server on first use.

Official sources

  1. Issues
  2. License: MIT
  3. nikunjsingh93/react-glass-keep on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/nikunjsingh93-react-glass-keep.svg)](https://hysenlabs.com/projects/nikunjsingh93-react-glass-keep)

Was this useful?