桌面和安卓客户端只是客户端,必须先自行部署或连接一个运行中的服务端;空数据库首次启动必须提供 INITIAL_ADMIN_USERNAME 和 INITIAL_ADMIN_PASSWORD;默认关闭注册(ALLOW_REGISTRATION=false),需手动改为 true 才能创建新账号;本地 AI 首次使用会下载 533 MB 模型。
react-glass-keep
nikunjsingh93MIT活跃维护自托管的笔记应用,用 Markdown 记录内容,支持 Docker 服务端、Tauri 桌面客户端和 PWA 网页端,可作为 Google Keep 的替代品。
Glass Keep is Keep Notes alternative using Glass design. Docker Server, Tauri Clients and PWA
docker pull nikunjsingh/glass-keep:latest
docker run -d --name glass-keep -p 8080:8080 -e NODE_ENV=production -e API_PORT=8080 -e JWT_SECRET -e DB_FILE="/app/data/notes.db" -e INITIAL_ADMIN_USERNAME -e INITIAL_ADMIN_PASSWORD -e ALLOW_REGISTRATION=false -v ~/.glass-keep:/app/data nikunjsingh/glass-keep:latestREADME 未说明显存或 GPU 要求;本地 AI 模型为 533 MB,按需下载并运行在服务端,空闲 60 秒后停止。
自托管的 Keep 风格笔记应用,带 Docker 服务端和 Tauri 桌面/安卓客户端
自托管的笔记应用,用 Markdown 记录内容,支持 Docker 服务端、Tauri 桌面客户端和 PWA 网页端,可作为 Google Keep 的替代品。
核心能力
- 支持 Markdown、清单、手绘、图片和标签的笔记
- 内置 Qwen + llama.cpp 本地 AI 助手,按需加载模型
- 支持清单与笔记的实时多人协作,含只读模式
- 提供 Docker 服务端、Tauri 客户端和可安装 PWA
- 支持导出 JSON、导入 Google Keep Takeout 数据
容易踩的坑
- v1.0.22Glass Keep 1.0.22 — Stable notes, HTTP imports and visible version最新正式版2026-11-08 · 2026-11-08 20:49 UTC
Client apps require a separately hosted Glass Keep server. Web/server and all client versions are 1.0.22.
Notes remain visible after import and refresh
- Keeps the current notes when a refresh fails or browser caching runs out of space. Stale responses across imports, view changes and account changes are ignored; closing the import dialog refreshes the current view.
- Invalid responses and empty offline caches no longer claim the account has no notes. Refresh failures show Retry. Actual offline-cache failures are reported without turning a successful server response into a failed save or blank screen; pending offline edits remain protected.
Untouched notes and LAN HTTP imports
- Imported titles containing whitespace can be opened and closed without an unwanted trim/save or false unsaved-draft warning. Actual draft/revision conflicts still keep the local draft open.
- Uses a cryptographic UUID fallback on ordinary LAN HTTP origins where the browser does not expose the secure-context-only randomUUID function. This could previously label valid Takeout notes as Invalid JSON regardless of CPU architecture.
- Distinguishes JSON syntax errors from note preparation errors and translates the guidance into every supported language. The reporter's private archive was not available; malformed source files may still need correction.
Visible version and update guide
The installed interface version appears below the logo on the main screen, linked to GitHub update instructions. Native apps display their bundled client version. Update Docker and installed clients separately. Header geometry stays stable while resizing, with compact search/Ask AI alignment preserved across all supported languages.
Addresses the latest follow-up in issue #37.
Update and downloads
Docker:
nikunjsingh/glass-keep:1.0.22or:latest, AMD64/ARM64. Pull/recreate through Portainer while preserving the existing data volume and environment, then refresh the web app. Update installed native clients separately.Downloads: Windows x64/ARM64 installers and portable executables, signed Android ARM64 APK, Apple Silicon/Intel Mac DMGs, and SHA-256 checksums. Android keeps its signing identity for in-place updates. Windows lacks commercial publisher signing; portable apps require WebView2. Mac requires macOS 13+, uses an ad-hoc signature and is not notarized; first launch may need Privacy & Security → Open Anyway.
Large import protections remain: small requests/chunked intact notes, 12 MiB per Keep image and 128 MiB per encoded note. See the Takeout guide. Keep duplicate skipping enabled when restarting an import that already saved notes.
Verification
- 39 unit/server tests pass, including cryptographic fallback, quota failures with durable drafts, account isolation and out-of-order replies.
- Actual insecure-HTTP browser regression reproduces missing randomUUID, imports valid Takeout notes, closes import with a delayed empty reply, exercises quota/failed/malformed refreshes, closes untouched padded-title notes and preserves real conflicting drafts.
- Existing 1,300-note interrupted-import, web/native, and responsive AI layout checks pass. Header/version visibility tested at 320px; AI alignment covers all languages and themes on web/native at 320/390/768/1280px.
- Both frontend builds, native platform builds, compiled Windows clients, Android version/signing and both Docker architectures are verified. No new physical Android or interactive Mac test was performed.
- v1.0.21Glass Keep 1.0.21 — Resumable imports and intact large notes2026-11-02 · 2026-11-02 16:01 UTC
查看更新说明
These are client apps only. You need a running Glass Keep server. Update both the server and native clients to 1.0.21 for the new upload protocol.
Reliable large imports
- Imports large notes intact through authenticated, account-scoped 256 KiB chunk uploads, replacing the old 19 MiB per-request barrier. Complete encoded notes may be up to 128 MiB; pictures are not resized, split into other notes or silently dropped.
- Retries transient connection/proxy errors up to five times with backoff. Stable operation identifiers prevent duplicate saves after lost replies, even when duplicate skipping is off. If retries run out, leave the dialog open and use Resume import once the server is reachable.
- Continues past individual invalid or oversized notes and lists their titles/reasons under Notes needing attention. Download a failure report or retry the failed notes. A note that fails preparation is not saved partially.
- Removes repeated full-library image hashing, offline-cache rewrites and refresh storms during import. Duplicate fingerprints are indexed and invalidated on edits; realtime import notifications are batched per affected account.
- Uses bounded uploads for Glass Keep backup restores too. Existing data, sessions, ownership, sharing and offline-edit behavior remain compatible. Recovery messages are translated into every supported language.
Addresses the latest follow-up in issue #37.
Limits and recovery
Google Keep images remain limited to 12 MiB each. A note larger than 128 MiB encoded, or with an unsupported/oversized image, is reported while other notes continue. Requests retain the global 20 MiB limit; the new transport sends small batches/chunks. Staging reserves at most 128 MiB per account and 512 MiB globally, and unfinished uploads expire after one hour without activity with automatic cleanup.
Imports still need a reachable server, plus storage/memory for the final note/image dataset. Resume state belongs to the open dialog. Reselecting files or reopening starts a new import: keep Skip duplicate notes enabled when restarting. Existing successfully saved notes are preserved.
See the Takeout import guide for exact archive limits and recovery steps.
Update and downloads
All web/server/Windows/macOS/Android versions are 1.0.21. Docker:
nikunjsingh/glass-keep:1.0.21or:latest, AMD64/ARM64. Pull and recreate in Portainer, preserving the existing data volume/settings, then refresh the web app. Install updated native clients separately.Attached: Windows x64/ARM64 installers and portable executables, signed Android ARM64 APK, Apple Silicon/Intel Mac DMGs, and SHA-256 checksums. Android retains its signing identity for in-place updates. Windows lacks commercial publisher signing; portable clients need WebView2. Mac requires macOS 13+, uses ad-hoc signing and is not notarized; first launch may require Privacy & Security → Open Anyway.
Verification
- 36 unit/server tests pass, including >20 MiB atomic commits, account isolation, expiry, duplicate-cache invalidation and preserved legacy sessions/data.
- Actual browser recovery test imports 1,300 small notes and one intact note with two images over 20 MiB encoded. It loses six batch replies, explicitly resumes after retries run out, and loses a large-note commit reply. With duplicate skipping OFF there are no duplicate saves; a bad image note is reported and later notes import.
- Web/native/export regressions, locale checks and both frontend builds pass. Compiled Windows x64/ARM64 clients verify the real Rust transport and an intact >20 MiB note with its original pictures. The 450 MiB synthetic archive still imports.
- Both Docker architectures and all native build jobs pass. APK version/signing identity verified. No new physical Android or interactive Mac test was performed; the
- v1.0.20Glass Keep 1.0.20 — Takeout import controls and pictures2026-10-29 · 2026-10-29 13:22 UTC
查看更新说明
These are client apps only. You need a running Glass Keep server to use them.
Google Keep import controls and pictures
- Adds clear Choose Takeout ZIP, Choose Takeout folder, and Add JSON files and images buttons in Settings → Import Google Keep across web and native clients. Addresses the follow-up in issue #37.
- Select JSON and pictures together, or add missing pictures after selecting JSON without losing your notes. Folder imports include nested attachment folders. If folder selection is unavailable on your device, use the ZIP option.
- Lists missing images before uploading and requires an explicit choice to import without them. Selecting only JSON cannot give the app permission to read nearby pictures.
- Matches attachment paths first and unique filenames as a fallback for individually selected files. Ambiguous filenames are reported instead of guessed. Removes the dormant legacy text-only importer.
- Keeps the large ZIP reader, lazy attachment reads, duplicate checks and per-file/per-note limits from 1.0.19. New guidance is available in every supported language.
Already imported text-only notes? Reimport the complete folder/ZIP to add copies containing pictures. Earlier copies remain untouched; review them before deleting any. Duplicate skipping compares image content as well as text.
See the Takeout import guide for exact limits and recovery steps. Standard ZIPs up to 2 GiB are supported; individual images must be at most 12 MiB and each encoded note must fit the 19 MiB upload guard. Extract ZIP64/encrypted/multidisk archives and use folder import.
Web, server, Windows, macOS and Android all use 1.0.20.
Update and downloads
Docker:
nikunjsingh/glass-keep:1.0.20ornikunjsingh/glass-keep:latest, AMD64/ARM64. Pull and recreate through Portainer while preserving your data volume and settings. Refresh the web app after updating. Update native clients separately because their interface is bundled in each app.Attached: Windows x64/ARM64 installers and portable executables, signed Android ARM64 APK, Apple Silicon/Intel macOS DMGs, and SHA-256 checksums. Android retains its existing signing identity for in-place updates. Windows installers lack commercial publisher signing; portable clients require WebView2. Mac clients require macOS 13+, use an ad-hoc signature and are not Apple-notarized; first launch may require Privacy & Security → Open Anyway.
Verification
- All 31 unit/server tests pass, including lazy attachments, path/CRC/size checks, filename matching and ambiguous/missing-picture cases.
- Actual browser and native-interface tests exercise ZIP, folder and multi-file pickers, add images after JSON, verify saved image bytes and rendered pictures, and check controls on phone/desktop widths.
- The synthetic 450 MiB Takeout ZIP still imports via the backup entry point and renders its image. The reporter's private export was not available.
- Both frontend builds, multi-architecture Docker smoke checks, native platform builds and compiled Windows client checks pass. No physical Android or interactive Mac test was performed for this release.
- v1.0.19Glass Keep 1.0.19 — Large Google Keep imports2026-10-29 · 2026-10-29 04:00 UTC
查看更新说明
These are client apps only. You need a running Glass Keep server to use them.
Large Google Keep Takeout imports
- Removes the old 100 MiB eager-import cap for Google Keep. Standard ZIPs up to 2 GiB are indexed with file slices and attachments are read one note at a time into bounded API batches.
- Takeout ZIPs selected through Import backup open the correct Import Google Keep dialog before the unrelated 200 MiB backup limit is checked. Addresses issue #37.
- Adds reading/import progress, a bounded preview, cancellation between batches, and localized messages in all five languages. Existing ownership filtering, duplicate skipping and optional sharing restoration remain available.
- Retains ZIP integrity/path/expanded-size checks and per-file/per-note upload limits. ZIP64, encrypted or multidisk archives should be extracted and imported through the Keep folder. Glass Keep JSON/backup.json restores retain their existing 200 MiB limit.
See the large Takeout import guide for exact limits and recovery steps. Individual attachments must be at most 12 MiB and each encoded note must fit the 19 MiB import guard. The app still needs memory for the final imported note/image dataset.
Web, server, Windows, macOS and Android all use 1.0.19.
Update and downloads
Docker:
nikunjsingh/glass-keep:1.0.19ornikunjsingh/glass-keep:latest, AMD64/ARM64. Pull and recreate through Portainer, keeping your existing data volume and settings. Install updated native clients separately for the bundled importer.Attached: Windows x64/ARM64 installers and portable executables, signed Android ARM64 APK, Apple Silicon/Intel macOS DMGs, and SHA-256 checksums. Android retains its existing signing identity for in-place updates. Windows installers do not have a commercial publisher certificate; portable clients require WebView2. Mac clients require macOS 13+, use an ad-hoc signature and are not Apple-notarized; first launch may require Privacy & Security → Open Anyway.
Verification
- All 30 unit/server tests pass, including malformed ZIPs, CRC/size/path validation, lazy reads, streamed ZIP descriptors, Unicode names, cancellation, ownership and legacy restore behavior.
- Actual browser file-picker testing imports a synthetic 450 MiB Takeout ZIP through the backup entry point, preserves its note/image and verifies image decoding. This fixture is not the reporter's private export. The compiled Windows ARM64 client also imports the same 450 MiB fixture and renders its image.
- A separate synthetic 405 MiB attachment-volume check processes 81 notes, reads no attachments during preview and keeps the largest upload request below 7 MB.
- Web/native/export browser regressions, locale checks, both frontend builds and packaged Docker checks pass. Native platform builds and compiled Windows checks are verified.
- v1.0.18Glass Keep 1.0.18 — German language support2026-10-21 · 2026-10-21 19:22 UTC
查看更新说明
These are client apps only. You need a running Glass Keep server to use them.
German language support
- Adds Deutsch on sign-in, native server connection and Settings language pickers across web, Windows, macOS and Android.
- Incorporates all 338 German translations from piwanowitsch in PR #35, with corrected registration, startup/loading text and full integration.
- Saves the language on this device, with translations bundled for offline use. Notes retain their original titles and content.
- Includes German settings, export/import, sharing, administration, AI controls and warnings. Compact Ask AI layout is verified in all five supported languages.
Thanks to piwanowitsch for contributing the German translation.
Web, server, Windows, macOS and Android all use 1.0.18.
Update and downloads
Docker:
nikunjsingh/glass-keep:1.0.18ornikunjsingh/glass-keep:latest, AMD64/ARM64. Pull and recreate through Portainer, keeping your existing data volume and settings. Install the updated native client separately for its bundled translations.Attached: Windows x64/ARM64 installers and portable executables, signed Android ARM64 APK, Apple Silicon/Intel macOS DMGs, and SHA-256 checksums. Android retains its existing signing identity for in-place updates. Windows installers do not have a commercial publisher certificate; portable clients require WebView2. Mac clients require macOS 13+, use an ad-hoc signature and are not Apple-notarized; first launch may require Privacy & Security → Open Anyway.
Verification
Translation checks cover complete key coverage, nonempty strings and unchanged substitution placeholders. Web/native browser checks verify German selection and persistence, sign-in and connection screens, settings, the AI enable warning, export controls, and first-paint loading text. AI button layout passes in English, German, Hindi, French and Russian at 320/390/768/1280 pixels in both themes, including busy states. Existing Android drawer Back/safe-area, selection, export and offline-editing checks pass. Both frontend builds and packaged Docker checks pass; native platform builds are verified.
用户点评
登录用户的真实使用记录,可按版本和硬件筛选还没有人点评。第一个说出真实体验的人最有价值。
Glass Keep
A sleek, Keep-style notes app with Markdown, checklists, images, tag chips, color themes, dark mode, drag-and-drop reordering, import/export, auth, and a glassy UI — built with Vite + React and a tiny Express + SQLite API.
The Windows, macOS and Android apps are client apps only. A running Glass Keep server is required. Deploy the server using the Docker instructions below (or connect to an existing instance), then enter its server URL in the app. The client apps do not install or run the server.
The clients are built with Tauri 2 and keep offline data separate per server. See the native app installation and build guide.
Download Windows .exe, Android .apk, and macOS .dmg clients from the GitHub release page.
Web App Screenshots
Mobile Screenshots
✨ Features
-
Auth & Multi-user
- Register, Login (username + password), Sign out
- Secure first run: supply
INITIAL_ADMIN_USERNAMEandINITIAL_ADMIN_PASSWORDwhen creating a new installation. - Secret recovery key download + Sign in with Secret Key
- Each user sees only their notes
-
Private AI Assistant (Qwen + llama.cpp)
- Local inference — Questions and note excerpts stay on your server; no cloud AI key is required.
- Loads on demand — Downloads a verified 533 MB model once, starts only for questions, and stops after 60 idle seconds.
- Note-aware answers — Ranked note retrieval with query expansion, progressive answers, and clickable source-note links.
- Works across clients — Web, Windows, macOS, and Android use the same server AI. Supports English, Hindi and French; no second model or vector service.
- See the local AI guide for resource limits, cache location, optional settings and accuracy limitations.
-
Collaboration (real-time) ✅ NEW
- Real-time collaboration for checklists — multiple people can add/tick items together and see updates instantly.
- Collaboration on notes — co-edit Markdown notes and watch changes sync across collaborators.
- Add and remove collaborators — invite users by username/email to collaborate on your notes.
- View-only mode for collaborators — open notes in view mode without overwriting edits from others.
- Revision checks reject stale saves; the editor keeps your draft and lets you download it before reloading.
-
Admin Panel
- New Admin Panel Sidebar in 3 dots Dropdown with many features like Add new uesr, Toggle new account creation (off by default) ✅ NEW
- View all users with: Name, Email/Username, Is Admin, Notes count, Storage used, Created at
- Delete user (also deletes their notes; protected against deleting the last admin)
-
Notes
- Text notes with Markdown (H1/H2/H3, bold, italic, strike, links, blockquote, inline/fenced code)
- Checklists (add items, toggle done, inline edit)
- Drag to reorder checklist items within the modal ✅ NEW
- Control checklist items directly from the notes grid — toggle items without opening the modal ✅ NEW
- Drawing/Handwritten notes — create freehand drawings with customizable brush sizes and colors ✅ NEW
- Smart Enter continues lists / exits on empty line
- Formatting toolbar in editor (composer + modal edit mode)
- Links open in new tab from view mode
-
Images
- Attach multiple images (client-side compression)
- Thumbs in grid, larger in modal
- Fullscreen viewer with next/prev + download image
-
Organization & Layout
- Pin / Unpin; “Pinned / Others” sections
- Tags as chips (comma input → chips; quick add/remove)
- Tag sidebar/drawer with list of all tags + counts
- Quick filters: Notes (All) and All Images
- Per-note color themes
- Search across title, Markdown text, tags, checklist items, image names
- Drag to reorder within each section
- Grid cards show truncated body with … and tag chips with … when overflowing
-
Modal
- Glassy blurred backdrop; sticky header
- View / Edit toggle button
- Pin, more (⋮) menu (Download .md), Close
- Footer: tags chip editor, color palette, image add, Delete (confirm dialog), Save
- Click edit button in body to switch to edit mode
- Dense list rendering in view mode (minimal spacing)
-
PWA
- Installable on desktop & mobile
-
Bulk actions (multi-select) ✅ NEW
- Select multiple notes at once to Download, Pin/Unpin, Delete, or Change Color.
-
Data
- Export all notes (JSON) and Import JSON/ZIP (merges; keeps existing notes)
- Automatic JSON exports: download your notes every 1/7/30 days while the app is open, then sync the download folder yourself with Syncthing or another service. No cloud-provider setup is required. See the export and restore guide.
- Per-note Download .md
- Import from Google Keep (Google Takeout) — choose a ZIP, an extracted Keep folder or JSON files, with attachment previews and batched uploads. See the large Takeout import guide.
- Backend: Express API + SQLite (
better-sqlite3)
-
UI/Theme ✅ IMPROVED
- Tailwind (v4) look & feel with glassmorphism
- Dark/Light mode with persistence
- Responsive header: hamburger + logo; "Glass Keep" title hidden on small screens
- Improved color picker — circular color indicator showing selected color ✅ NEW
- Colorful emoji icons — enhanced icons for checklist (✅), drawing (🖌️), and images (🖼️) ✅ NEW
- Better visual feedback — cleaner UI elements with improved spacing and colors ✅ NEW
🐛 Recent Bug Fixes ✅
-
Collaboration fixes
- Fixed issue where opening notes in view mode would overwrite edits made in edit mode
- Improved conflict resolution — only saves when user actually makes edits, not just opening/closing notes
- Fixed token expiration handling — automatic logout and redirect when session expires
- Added connection timeout handling for better reliability after long idle periods
-
UI/UX improvements
- Fixed metadata changes (color, tags, images) not saving for collaborative notes
- Improved auto-save for collaborative notes — metadata changes save immediately
- Better error handling for network failures and expired sessions
🧰 Requirements
- Node.js 24 LTS and npm
- (Optional) Docker & Docker Compose
- SQLite is embedded (no external DB needed)
📦 Project Structure
.
├─ public/ # PWA icons, manifest generated by Vite plugin
├─ src/ # React app (App.jsx, etc.)
├─ server/ # Express + SQLite API (index.js, data.sqlite on runtime)
├─ index.html
├─ vite.config.js
├─ package.json
└─ README.md
[!IMPORTANT] Supply
INITIAL_ADMIN_USERNAMEandINITIAL_ADMIN_PASSWORDbefore the first Docker run for an empty database.JWT_SECRETis optional; existing configured secrets continue to work unchanged. Passwords need at least 12 characters and at most 72 UTF-8 bytes. There are no default credentials. Initial admin settings are ignored after accounts exist; removeINITIAL_ADMIN_PASSWORDafter setup.
🐳 Docker Deploy to Server(single image: API + built frontend)
Dockerfile
Your Dockerfile builds the frontend, bundles the API, and runs the Express server that serves both the API and the built UI.
Build & Run
# Get the latest image from Docker Hub
docker pull nikunjsingh/glass-keep:latest
# Create data dir
mkdir -p ~/.glass-keep
# (optional) stop/remove any old container
docker rm -f glass-keep 2>/dev/null || true
# Run
docker run -d \
--name glass-keep \
--restart unless-stopped \
-p 8080:8080 \
-e NODE_ENV=production \
-e API_PORT=8080 \
-e JWT_SECRET \
-e DB_FILE="/app/data/notes.db" \
-e INITIAL_ADMIN_USERNAME \
-e INITIAL_ADMIN_PASSWORD \
-e ALLOW_REGISTRATION=false \
-v ~/.glass-keep:/app/data \
nikunjsingh/glass-keep:latest
- App & API: http://localhost:8080
- Admin Panel (Docker/prod): http://localhost:8080/#/admin
(Initial administrator credentials are required only for an empty database.)
docker-compose.yml
version: "3.8"
services:
app:
image: nikunjsingh/glass-keep:latest
container_name: glass-keep
restart: unless-stopped
environment:
NODE_ENV: production
API_PORT: "8080"
JWT_SECRET: ${JWT_SECRET:-}
DB_FILE: /app/data/notes.db
INITIAL_ADMIN_USERNAME: ${INITIAL_ADMIN_USERNAME:-}
INITIAL_ADMIN_PASSWORD: ${INITIAL_ADMIN_PASSWORD:-}
ALLOW_REGISTRATION: "false" # <— set to "true" to allow new account creation
ports:
- "8080:8080"
volumes:
- /home/YOURUSER/.glass-keep:/app/data # <— change this to your actual home path username
Run:
mkdir -p /home/YOURUSER/.glass-keep
docker compose up -d
Persistent data: notes DB lives in the mounted
./datafolder on your host.
🛠 Setup (Development)
1) Install dependencies
npm install
# (Optional) only If you don't have these dev/runtime deps yet:
npm install -D concurrently nodemon
npm install express better-sqlite3 cors jsonwebtoken bcryptjs
2) Run (web + API)
POSIX/mac/Linux:
INITIAL_ADMIN_USERNAME="your-admin-username" INITIAL_ADMIN_PASSWORD="$INITIAL_ADMIN_PASSWORD" npm run dev
Windows (PowerShell):
$env:INITIAL_ADMIN_USERNAME = "your-admin-username"
# Set INITIAL_ADMIN_PASSWORD to your chosen password (12+ characters) in this session.
npm run dev
- Frontend (Vite): http://localhost:5173
- Docker: http://localhost:8080
(Vite dev server proxies/api→http://localhost:8080.)
Promote an existing user to admin (optional):
-- Run against server/data.sqlite
UPDATE users SET is_admin=1 WHERE email='your-admin-username';
3) Docker (Local Development)
Quick Local Docker Script:
./local_docker_run.sh
Or manually:
docker build -t glass-keep:local .
docker rm -f glass-keep 2>/dev/null || true
docker run -d \
--name glass-keep \
--restart unless-stopped \
-p 8080:8080 \
-e NODE_ENV=production \
-e API_PORT=8080 \
-e JWT_SECRET \
-e DB_FILE=/app/data/notes.db \
-e INITIAL_ADMIN_USERNAME \
-e INITIAL_ADMIN_PASSWORD \
-e ALLOW_REGISTRATION=false \
-v "$HOME/.glass-keep:/app/data" \
glass-keep:local
🧭 Using the Admin Panel
- Where
- Dev: http://localhost:5173/#/admin
- Docker/Prod: http://localhost:8080/#/admin
- Who can access: Users with
is_admin = 1.- Auto-promote by setting
ADMIN_EMAILS="your-admin-username"before starting the server/container, or - Run a one-off SQL update:
UPDATE users SET is_admin=1 WHERE email='your-admin-username';
- Auto-promote by setting
Sign in using the initial administrator credentials you supplied. Existing databases retain their accounts. Admins can create users and change passwords in the Admin Panel.
- What you can do
- View all users with: Is Admin, Notes count, Storage used, Created at
- Delete a user (also removes their notes; cannot delete the last admin)
Open the Admin Panel from the main menu, or navigate to
/#/admin.
🧭 Usage Guide
-
Create a note
- Choose Text / Checklist / Drawing in the composer toggle. ✅ NEW
- For text notes: Enter a Title and content.
- For checklists: Add checklist items and toggle them as needed.
- For drawings: Draw freehand with customizable brush sizes and colors. ✅ NEW
- Add tags (comma-separated) — they become chips.
- Choose a color, attach images, then click Add Note.
-
Markdown editing
-
Use the Formatting button (Aa) in the composer or modal edit mode:
- H1/H2/H3, bold, italic,
strike,inline code,fenced code, quote, lists, link
- H1/H2/H3, bold, italic,
-
Smart Enter continues lists or exits on empty line.
-
-
Open / Edit
- Click a card to open the modal.
- Modal header has View / Edit toggle, Pin, ⋮ (Download .md), and Close.
- Click edit button in the body to switch to edit mode.
-
Images
- Click a modal image to open Fullscreen Viewer (download, next/prev).
- Images are compressed client-side on upload.
-
Pin & Reorder
- Use the pin icon on a card or modal header.
- Drag cards to reorder within Pinned or Others.
- Drag checklist items to reorder them within a checklist note. ✅ NEW
- Toggle checklist items directly from the notes grid without opening the modal. ✅ NEW
-
Tags & Filters
- Open the hamburger menu → sidebar lists all tags + counts.
- Quick filters: Notes (All), All Images.
-
Search & AI Assistance ✅ NEW
- Deep Search: Searches across title, Markdown text, tags, checklist items, and image names.
- AI Assistant: Press Enter in the search bar to ask questions about your notes.
- Smart Grounding: The AI analyzes your relevant notes to give you accurate, private answers.
- One-Click Clear: Closing the AI response box automatically clears your search query.
-
Export / Import
- Header ⋮ → Export to JSON (backup/sharing).
- Import JSON merges with existing notes (keeps existing).
-
Secret Key
- Header ⋮ → Download secret key (.txt).
- On login screen, choose Forgot username/password? → Sign in with Secret Key.
-
Collaboration
- Open a note and click the collaboration icon (👥) in the modal header.
- Add collaborators by username or email — they can view and edit the note.
- View current collaborators and remove them if needed. ✅ NEW
- Changes sync in real-time across all collaborators.
🔐 Security Notes
- Treat your Secret Key like a password. Anyone with it can sign in as you.
- A long random
JWT_SECRETis recommended, but is optional and does not block startup. Existing configured secrets and the original fallback remain supported. Set optionalJWT_TTL(default7d) to control session duration. Changing a password revokes existing sessions. - Serve over HTTPS in production for PWA and security best practices.
🧪 Troubleshooting
-
Dev proxy error (
ECONNREFUSEDto/api)- Ensure the API is running on
:8080(npm run devstarts both).
- Ensure the API is running on
-
Docker runs but CSS looks wrong
- Rebuild after Tailwind config changes:
docker compose build --no-cache. - Ensure the app is built (
npm run build) before running the Node server image.
- Rebuild after Tailwind config changes:
-
PWA “Install” doesn’t appear
- Use the built preview (
npm run preview) or serve production build over HTTPS. - Check DevTools → Application → Manifest & Service Worker for errors.
- Use the built preview (
📝 License
MIT
Upgrading to 1.0.2
- Back up the SQLite database before upgrading. Stop the old container before copying the database and its WAL files, or use SQLite's online backup command. The JSON export in older versions omits archived notes.
- Keep the same mounted data directory. Schema migrations add note revisions and session versions without replacing accounts or notes.
- Version 1.0.3 removes the JWT secret startup requirement. Keep your existing secret to preserve sessions; no JWT configuration change is required. Rotate any old default administrator password.
- Initial administrator credentials are required only when the database has no users.
- Reload all open browser/PWA windows after upgrading. Older clients cannot save without a revision; the server returns 428 instead of accepting an unsafe overwrite.
- Authenticated API responses are no longer service-worker cached. Old shared API caches are deleted at startup and service-worker activation. Version 1.0.4 adds per-account IndexedDB snapshots and a persistent queue for offline edits.
- Version 2 JSON exports preserve archived notes and attachments. Restoring merges copies into the signed-in user's account; sharing permissions are intentionally not recreated.
- A recovery key grants sign-in access; it is not an encryption key. Existing recovery keys migrate after their next successful use.
Validation
Run npm test for API/security tests and npm run build for the production bundle. Run node --test tests/browser.test.mjs for the browser regression check (Microsoft Edge installed). Tests create temporary databases and do not use your notes.
Upgrading to 1.0.3
Pull nikunjsingh/glass-keep:1.0.3 (or latest) and recreate the container with its existing environment and database volume. Short, legacy placeholder, and unset JWT secrets no longer block startup. No account or password changes are required for an existing database.
Upgrading to 1.0.4
Use nikunjsingh/glass-keep:1.0.4 for a fixed release, or latest for the newest published release. Both Linux AMD64 and ARM64 are supported. Keep your existing database volume and JWT secret, back up the database, then recreate the container. Open /api/health to check the running version (this release returns 1.0.4). Reload browser/PWA windows so they load the matching client.
Nginx Proxy Manager
With one Nginx Proxy Manager in front of Glass Keep, add this environment variable to the Glass Keep container and recreate it:
environment:
TRUST_PROXY: "1"
This lets sign-in rate limiting identify individual users from the forwarded client address and resolves ERR_ERL_UNEXPECTED_X_FORWARDED_FOR. Only expose the app through that proxy; direct access to the app port would allow a caller to supply its own forwarded address. Leave this variable unset for direct access without a proxy. Other installations can specify trusted proxy IPs/subnets as a comma-separated list. Do not set it to true, which would trust every supplied proxy address.
Web features
- Language: choose English, Deutsch, हिन्दी, Français or Русский on the sign-in screen or in Settings (also on the native server-connection screen). The choice is remembered on this device, including offline use. Notes are kept in their original language.
- Grid: recent notes start left to right, with subsequent notes filling the shortest column to avoid blank row spaces. Pinned notes remain in their own section.
- Tags: existing tags appear as suggestions in the editor. Select several tags in the sidebar to show notes matching all selected tags. Choose Notes (All) to clear the filter.
- Selection: Menu → Multi select → Select all filtered selects the current search/tag results. Changing the search or tags clears the selection. Review the confirmation before bulk deletion.
- Copies: open a note → three-dot menu → Make a copy. This creates a separate, unpinned note owned by you, without copying collaboration permissions.
- Checklists: use arrow controls to reorder a complete branch, indent/outdent items, add sub-items, and hide completed items. Checking a parent also checks its descendants.
- Google Keep: Settings → Import Google Keep accepts a Takeout ZIP, a folder, or JSON files. ZIP/folder imports include supported image attachments (PNG, JPEG, GIF, WebP). Missing or unsupported attachments are reported. Import is limited to 100 MB decompressed and 5,000 ZIP entries. Notes owned by another person are skipped by default; enter your Keep email when identifying an owner explicitly listed in the export. Sharing restoration is optional and matches existing Glass Keep usernames exactly to sharee emails; unmatched users are reported. Review the preview before importing.
- Duplicates: imports skip notes with matching type, trimmed title, content, checklist structure, tags and image contents by default. Disable that option to deliberately create copies. Settings → Find duplicates shows duplicate groups and requires confirmation before deletion. Color, pin state, timestamps and archive state are not part of duplicate matching.
- Links: in the note's three-dot menu, Copy note link creates a private deep link; readers still need an account with access. Public sharing creates an optional read-only link that anyone holding it can open. Public links include the current note content and attachments, offer expiry choices of 1, 7, 30 or 90 days, 1 year, or Never, can be replaced/revoked by the owner, and do not grant editing access. Never means the link stays active until revoked, replaced, or the note is deleted.
Offline editing
Sign in and open the app online at least once on the device. Visited notes are stored separately for each account. Creating, editing, checking items, copying, deleting and archiving notes can then queue locally while offline. Keep the browser's site data until synchronization finishes; clearing site data removes unsynced drafts. New sign-ins, imports, sharing changes and AI require a connection.
The queue survives a reload and synchronizes after reconnecting or signing in again to the same account. Replayed operations are recorded by the server so a lost acknowledgment does not apply a write twice. If the server copy changed, both versions are preserved for review: download the local draft, use the server version, or explicitly keep your changes. An expired session requires signing in again before synchronization resumes.
Release checks
Run npm test, npm run build, then node --test tests/browser.test.mjs tests/web-features.browser.mjs (Microsoft Edge installed). tests/docker-smoke.ps1 checks the final image on both architectures. Native clients have separate builds and checks documented in the native app guide. Home-screen widgets are not included.