From af69f637cc474325d9d8a6b468816778b08e600d Mon Sep 17 00:00:00 2001 From: Mohamed Bassem Date: Sat, 13 Dec 2025 11:05:05 +0000 Subject: docs: restructure the docs --- docs/docs/01-getting-started/01-intro.md | 54 +++++ docs/docs/01-getting-started/02-screenshots.md | 34 +++ docs/docs/01-getting-started/_category_.json | 3 + docs/docs/01-intro.md | 54 ----- docs/docs/02-installation/01-docker.md | 10 +- docs/docs/02-installation/03-archlinux.md | 4 +- docs/docs/02-installation/04-kubernetes.md | 6 +- docs/docs/02-installation/06-debuntu.md | 2 +- docs/docs/02-installation/07-minimal-install.md | 4 +- docs/docs/03-configuration.md | 239 --------------------- .../03-configuration/01-environment-variables.md | 239 +++++++++++++++++++++ docs/docs/03-configuration/_category_.json | 3 + docs/docs/04-screenshots.md | 34 --- docs/docs/04-using-karakeep/01-quick-sharing.md | 21 ++ docs/docs/04-using-karakeep/02-import.md | 49 +++++ .../04-using-karakeep/03-search-query-language.md | 76 +++++++ docs/docs/04-using-karakeep/_category_.json | 3 + docs/docs/05-integrations/01-openai.md | 11 + docs/docs/05-integrations/02-command-line.md | 114 ++++++++++ docs/docs/05-integrations/03-mcp.md | 65 ++++++ .../05-integrations/04-different-ai-providers.md | 88 ++++++++ docs/docs/05-integrations/05-singlefile.md | 46 ++++ docs/docs/05-integrations/_category_.json | 3 + docs/docs/05-quick-sharing.md | 21 -- .../01-security-considerations.md | 14 ++ docs/docs/06-administration/02-FAQ.md | 60 ++++++ docs/docs/06-administration/03-troubleshooting.md | 46 ++++ docs/docs/06-administration/04-server-migration.md | 71 ++++++ .../05-legacy-container-upgrade.md | 66 ++++++ .../06-hoarder-to-karakeep-migration.md | 28 +++ docs/docs/06-administration/_category_.json | 3 + docs/docs/06-openai.md | 11 - docs/docs/07-community/01-community-projects.md | 87 ++++++++ docs/docs/07-community/_category_.json | 3 + docs/docs/07-development/01-setup.md | 178 --------------- docs/docs/07-development/02-directories.md | 28 --- docs/docs/07-development/03-database.md | 10 - docs/docs/07-development/04-architecture.md | 9 - docs/docs/07-development/_category_.json | 3 - docs/docs/08-development/01-setup.md | 178 +++++++++++++++ docs/docs/08-development/02-directories.md | 28 +++ docs/docs/08-development/03-database.md | 10 + docs/docs/08-development/04-architecture.md | 9 + docs/docs/08-development/_category_.json | 3 + docs/docs/08-security-considerations.md | 14 -- docs/docs/09-command-line.md | 114 ---------- docs/docs/09-mcp.md | 65 ------ docs/docs/10-import.md | 49 ----- docs/docs/11-FAQ.md | 60 ------ docs/docs/12-troubleshooting.md | 46 ---- docs/docs/13-community-projects.md | 87 -------- docs/docs/14-guides/01-legacy-container-upgrade.md | 66 ------ docs/docs/14-guides/02-search-query-language.md | 76 ------- docs/docs/14-guides/03-singlefile.md | 46 ---- .../14-guides/04-hoarder-to-karakeep-migration.md | 28 --- docs/docs/14-guides/05-different-ai-providers.md | 88 -------- docs/docs/14-guides/06-server-migration.md | 71 ------ docs/docs/14-guides/_category_.json | 3 - docs/docusaurus.config.ts | 87 +++++++- docs/package.json | 1 + pnpm-lock.yaml | 172 ++++++++++++++- 61 files changed, 1676 insertions(+), 1425 deletions(-) create mode 100644 docs/docs/01-getting-started/01-intro.md create mode 100644 docs/docs/01-getting-started/02-screenshots.md create mode 100644 docs/docs/01-getting-started/_category_.json delete mode 100644 docs/docs/01-intro.md delete mode 100644 docs/docs/03-configuration.md create mode 100644 docs/docs/03-configuration/01-environment-variables.md create mode 100644 docs/docs/03-configuration/_category_.json delete mode 100644 docs/docs/04-screenshots.md create mode 100644 docs/docs/04-using-karakeep/01-quick-sharing.md create mode 100644 docs/docs/04-using-karakeep/02-import.md create mode 100644 docs/docs/04-using-karakeep/03-search-query-language.md create mode 100644 docs/docs/04-using-karakeep/_category_.json create mode 100644 docs/docs/05-integrations/01-openai.md create mode 100644 docs/docs/05-integrations/02-command-line.md create mode 100644 docs/docs/05-integrations/03-mcp.md create mode 100644 docs/docs/05-integrations/04-different-ai-providers.md create mode 100644 docs/docs/05-integrations/05-singlefile.md create mode 100644 docs/docs/05-integrations/_category_.json delete mode 100644 docs/docs/05-quick-sharing.md create mode 100644 docs/docs/06-administration/01-security-considerations.md create mode 100644 docs/docs/06-administration/02-FAQ.md create mode 100644 docs/docs/06-administration/03-troubleshooting.md create mode 100644 docs/docs/06-administration/04-server-migration.md create mode 100644 docs/docs/06-administration/05-legacy-container-upgrade.md create mode 100644 docs/docs/06-administration/06-hoarder-to-karakeep-migration.md create mode 100644 docs/docs/06-administration/_category_.json delete mode 100644 docs/docs/06-openai.md create mode 100644 docs/docs/07-community/01-community-projects.md create mode 100644 docs/docs/07-community/_category_.json delete mode 100644 docs/docs/07-development/01-setup.md delete mode 100644 docs/docs/07-development/02-directories.md delete mode 100644 docs/docs/07-development/03-database.md delete mode 100644 docs/docs/07-development/04-architecture.md delete mode 100644 docs/docs/07-development/_category_.json create mode 100644 docs/docs/08-development/01-setup.md create mode 100644 docs/docs/08-development/02-directories.md create mode 100644 docs/docs/08-development/03-database.md create mode 100644 docs/docs/08-development/04-architecture.md create mode 100644 docs/docs/08-development/_category_.json delete mode 100644 docs/docs/08-security-considerations.md delete mode 100644 docs/docs/09-command-line.md delete mode 100644 docs/docs/09-mcp.md delete mode 100644 docs/docs/10-import.md delete mode 100644 docs/docs/11-FAQ.md delete mode 100644 docs/docs/12-troubleshooting.md delete mode 100644 docs/docs/13-community-projects.md delete mode 100644 docs/docs/14-guides/01-legacy-container-upgrade.md delete mode 100644 docs/docs/14-guides/02-search-query-language.md delete mode 100644 docs/docs/14-guides/03-singlefile.md delete mode 100644 docs/docs/14-guides/04-hoarder-to-karakeep-migration.md delete mode 100644 docs/docs/14-guides/05-different-ai-providers.md delete mode 100644 docs/docs/14-guides/06-server-migration.md delete mode 100644 docs/docs/14-guides/_category_.json diff --git a/docs/docs/01-getting-started/01-intro.md b/docs/docs/01-getting-started/01-intro.md new file mode 100644 index 00000000..1c99f4c0 --- /dev/null +++ b/docs/docs/01-getting-started/01-intro.md @@ -0,0 +1,54 @@ +--- +slug: / +--- + +# Introduction + +Karakeep (previously Hoarder) is an open source "Bookmark Everything" app that uses AI for automatically tagging the content you throw at it. The app is built with self-hosting as a first class citizen. + +![Screenshot](https://raw.githubusercontent.com/karakeep-app/karakeep/main/screenshots/homepage.png) + + +## Features + +- 🔗 Bookmark links, take simple notes and store images and pdfs. +- ⬇️ Automatic fetching for link titles, descriptions and images. +- 📋 Sort your bookmarks into lists. +- 👥 Collaborate with others on the same list. +- 🔎 Full text search of all the content stored. +- ✨ AI-based (aka chatgpt) automatic tagging and summarization. With supports for local models using ollama! +- 🤖 Rule-based engine for customized management. +- 🎆 OCR for extracting text from images. +- 🔖 [Chrome plugin](https://chromewebstore.google.com/detail/karakeep/kgcjekpmcjjogibpjebkhaanilehneje) and [Firefox addon](https://addons.mozilla.org/en-US/firefox/addon/karakeep/) for quick bookmarking. +- 📱 An [iOS app](https://apps.apple.com/us/app/karakeep-app/id6479258022), and an [Android app](https://play.google.com/store/apps/details?id=app.hoarder.hoardermobile&pcampaignid=web_share). +- 📰 Auto hoarding from RSS feeds. +- 🔌 REST API and multiple clients. +- 🌐 Multi-language support. +- 🖍️ Mark and store highlights from your hoarded content. +- 🗄️ Full page archival (using [monolith](https://github.com/Y2Z/monolith)) to protect against link rot. +- ▶️ Auto video archiving using [yt-dlp](https://github.com/yt-dlp/yt-dlp). +- ☑️ Bulk actions support. +- 🔐 SSO support. +- 🌙 Dark mode support. +- 💾 Self-hosting first. +- ⬇️ Bookmark importers from Chrome, Pocket, Linkwarden, Omnivore, Tab Session Manager. +- 🔄 Automatic sync with browser bookmarks via [floccus](https://floccus.org/). +- [Planned] Offline reading on mobile, semantic search across bookmarks, ... + +**⚠️ This app is under heavy development.** + + +## Demo + +You can access the demo at [https://try.karakeep.app](https://try.karakeep.app). Login with the following creds: + +``` +email: demo@karakeep.app +password: demodemo +``` + +The demo is seeded with some content, but it's in read-only mode to prevent abuse. + +## About the name + +The name Karakeep is inspired by the Arabic word "كراكيب" (karakeeb), a colloquial term commonly used to refer to miscellaneous clutter, odds and ends, or items that may seem disorganized but often hold personal value or hidden usefulness. It evokes the image of a messy drawer or forgotten box, full of stuff you can't quite throw away—because somehow, it matters (or more likely, because you're a hoarder!). diff --git a/docs/docs/01-getting-started/02-screenshots.md b/docs/docs/01-getting-started/02-screenshots.md new file mode 100644 index 00000000..07830566 --- /dev/null +++ b/docs/docs/01-getting-started/02-screenshots.md @@ -0,0 +1,34 @@ +# Screenshots + +## Homepage + +![Homepage](/img/screenshots/homepage.png) + +## Homepage (Dark Mode) + +![Homepage](/img/screenshots/homepage-dark.png) + +## Tags + +![All Tags](/img/screenshots/all-tags.png) + +## Lists + +![All Lists](/img/screenshots/all-lists.png) + +## Bookmark Preview + +![Bookmark Preview](/img/screenshots/bookmark-preview.png) + +## Settings + +![Settings](/img/screenshots/settings.png) + +## Admin Panel + +![Ammin](/img/screenshots/admin.png) + + +## iOS Sharing + + diff --git a/docs/docs/01-getting-started/_category_.json b/docs/docs/01-getting-started/_category_.json new file mode 100644 index 00000000..41f4c00e --- /dev/null +++ b/docs/docs/01-getting-started/_category_.json @@ -0,0 +1,3 @@ +{ + "label": "Getting Started" +} diff --git a/docs/docs/01-intro.md b/docs/docs/01-intro.md deleted file mode 100644 index 1c99f4c0..00000000 --- a/docs/docs/01-intro.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -slug: / ---- - -# Introduction - -Karakeep (previously Hoarder) is an open source "Bookmark Everything" app that uses AI for automatically tagging the content you throw at it. The app is built with self-hosting as a first class citizen. - -![Screenshot](https://raw.githubusercontent.com/karakeep-app/karakeep/main/screenshots/homepage.png) - - -## Features - -- 🔗 Bookmark links, take simple notes and store images and pdfs. -- ⬇️ Automatic fetching for link titles, descriptions and images. -- 📋 Sort your bookmarks into lists. -- 👥 Collaborate with others on the same list. -- 🔎 Full text search of all the content stored. -- ✨ AI-based (aka chatgpt) automatic tagging and summarization. With supports for local models using ollama! -- 🤖 Rule-based engine for customized management. -- 🎆 OCR for extracting text from images. -- 🔖 [Chrome plugin](https://chromewebstore.google.com/detail/karakeep/kgcjekpmcjjogibpjebkhaanilehneje) and [Firefox addon](https://addons.mozilla.org/en-US/firefox/addon/karakeep/) for quick bookmarking. -- 📱 An [iOS app](https://apps.apple.com/us/app/karakeep-app/id6479258022), and an [Android app](https://play.google.com/store/apps/details?id=app.hoarder.hoardermobile&pcampaignid=web_share). -- 📰 Auto hoarding from RSS feeds. -- 🔌 REST API and multiple clients. -- 🌐 Multi-language support. -- 🖍️ Mark and store highlights from your hoarded content. -- 🗄️ Full page archival (using [monolith](https://github.com/Y2Z/monolith)) to protect against link rot. -- ▶️ Auto video archiving using [yt-dlp](https://github.com/yt-dlp/yt-dlp). -- ☑️ Bulk actions support. -- 🔐 SSO support. -- 🌙 Dark mode support. -- 💾 Self-hosting first. -- ⬇️ Bookmark importers from Chrome, Pocket, Linkwarden, Omnivore, Tab Session Manager. -- 🔄 Automatic sync with browser bookmarks via [floccus](https://floccus.org/). -- [Planned] Offline reading on mobile, semantic search across bookmarks, ... - -**⚠️ This app is under heavy development.** - - -## Demo - -You can access the demo at [https://try.karakeep.app](https://try.karakeep.app). Login with the following creds: - -``` -email: demo@karakeep.app -password: demodemo -``` - -The demo is seeded with some content, but it's in read-only mode to prevent abuse. - -## About the name - -The name Karakeep is inspired by the Arabic word "كراكيب" (karakeeb), a colloquial term commonly used to refer to miscellaneous clutter, odds and ends, or items that may seem disorganized but often hold personal value or hidden usefulness. It evokes the image of a messy drawer or forgotten box, full of stuff you can't quite throw away—because somehow, it matters (or more likely, because you're a hoarder!). diff --git a/docs/docs/02-installation/01-docker.md b/docs/docs/02-installation/01-docker.md index ff508b73..1a89796c 100644 --- a/docs/docs/02-installation/01-docker.md +++ b/docs/docs/02-installation/01-docker.md @@ -44,7 +44,7 @@ Persistent storage and the wiring between the different services is already take Keep in mind that every time you change the `.env` file, you'll need to re-run `docker compose up`. -If you want more config params, check the config documentation [here](/configuration). +If you want more config params, check the config documentation [here](../configuration/environment-variables). ### 4. Setup OpenAI @@ -57,7 +57,7 @@ To enable automatic tagging, you'll need to configure OpenAI. This is optional t OPENAI_API_KEY= ``` -Learn more about the costs of using openai [here](/openai). +Learn more about the costs of using openai [here](../integrations/openai).
If you want to use Ollama (https://ollama.com/) instead for local inference. @@ -85,11 +85,11 @@ Then visit `http://localhost:3000` and you should be greeted with the Sign In pa ### [Optional] 6. Enable optional features -Check the [configuration docs](/configuration) for extra features to enable such as full page archival, full page screenshots, inference languages, etc. +Check the [configuration docs](../configuration/environment-variables) for extra features to enable such as full page archival, full page screenshots, inference languages, etc. ### [Optional] 7. Setup quick sharing extensions -Go to the [quick sharing page](/quick-sharing) to install the mobile apps and the browser extensions. Those will help you hoard things faster! +Go to the [quick sharing page](../using-karakeep/quick-sharing) to install the mobile apps and the browser extensions. Those will help you hoard things faster! ## Updating @@ -98,4 +98,4 @@ Updating Karakeep will depend on what you used for the `KARAKEEP_VERSION` env va - If you pinned the app to a specific version, bump the version and re-run `docker compose up -d`. This should pull the new version for you. - If you used `KARAKEEP_VERSION=release`, you'll need to force docker to pull the latest version by running `docker compose up --pull always -d`. -Note that if you want to upgrade/migrate `Meilisearch` versions, refer to the [troubleshooting](/troubleshooting) page. +Note that if you want to upgrade/migrate `Meilisearch` versions, refer to the [troubleshooting](../administration/troubleshooting) page. diff --git a/docs/docs/02-installation/03-archlinux.md b/docs/docs/02-installation/03-archlinux.md index 63db9d75..b8433374 100644 --- a/docs/docs/02-installation/03-archlinux.md +++ b/docs/docs/02-installation/03-archlinux.md @@ -27,7 +27,7 @@ 3. Set up - Environment variables can be set in `/etc/karakeep/karakeep.env` according to [configuration page](/configuration). **The environment variables that are not specified in `/etc/karakeep/karakeep.env` need to be added by yourself.** + Environment variables can be set in `/etc/karakeep/karakeep.env` according to [configuration page](../configuration/environment-variables). **The environment variables that are not specified in `/etc/karakeep/karakeep.env` need to be added by yourself.** 4. Enable service @@ -82,7 +82,7 @@ sudo chown -R karakeep:karakeep /var/lib/karakeep ``` **6. Set Karakeep** -Edit `/etc/karakeep/karakeep.env` according to [configuration page](/configuration). **The environment variables that are not specified in `/etc/karakeep/karakeep.env` need to be added by yourself.** +Edit `/etc/karakeep/karakeep.env` according to [configuration page](../configuration/environment-variables). **The environment variables that are not specified in `/etc/karakeep/karakeep.env` need to be added by yourself.** Or you can copy old hoarder env file to karakeep: ```shell diff --git a/docs/docs/02-installation/04-kubernetes.md b/docs/docs/02-installation/04-kubernetes.md index b8c40551..b3a42d84 100644 --- a/docs/docs/02-installation/04-kubernetes.md +++ b/docs/docs/02-installation/04-kubernetes.md @@ -18,7 +18,7 @@ You should also change the `NEXTAUTH_URL` variable to point to your server addre Using `KARAKEEP_VERSION=release` will pull the latest stable version. You might want to pin the version instead to control the upgrades (e.g. `KARAKEEP_VERSION=0.10.0`). Check the latest versions [here](https://github.com/karakeep-app/karakeep/pkgs/container/karakeep). -To see all available configuration options check the [documentation](https://docs.karakeep.app/configuration). +To see all available configuration options check the [documentation](../configuration/environment-variables). To configure the neccessary secrets for the application copy the `.secrets_sample` file to `.secrets` and change the sample secrets to your generated secrets. @@ -35,7 +35,7 @@ To enable automatic tagging, you'll need to configure OpenAI. This is optional t OPENAI_API_KEY= ``` -Learn more about the costs of using openai [here](/openai). +Learn more about the costs of using openai [here](../integrations/openai).
[EXPERIMENTAL] If you want to use Ollama (https://ollama.com/) instead for local inference. @@ -103,7 +103,7 @@ If the secret is successfully created you can now configure the Ingress to use T ### [Optional] 6. Setup quick sharing extensions -Go to the [quick sharing page](/quick-sharing) to install the mobile apps and the browser extensions. Those will help you hoard things faster! +Go to the [quick sharing page](../using-karakeep/quick-sharing) to install the mobile apps and the browser extensions. Those will help you hoard things faster! ## Updating diff --git a/docs/docs/02-installation/06-debuntu.md b/docs/docs/02-installation/06-debuntu.md index 2f3d1113..55984728 100644 --- a/docs/docs/02-installation/06-debuntu.md +++ b/docs/docs/02-installation/06-debuntu.md @@ -71,4 +71,4 @@ During installation, the script created a configuration file for `meilisearch`, ## Still Running Hoarder? -There is a way to upgrade. Please see [Guides > Hoarder to Karakeep Migration](https://docs.karakeep.app/Guides/hoarder-to-karakeep-migration) +There is a way to upgrade. Please see [Hoarder to Karakeep Migration](../administration/hoarder-to-karakeep-migration) diff --git a/docs/docs/02-installation/07-minimal-install.md b/docs/docs/02-installation/07-minimal-install.md index 5c2ee399..e5720df1 100644 --- a/docs/docs/02-installation/07-minimal-install.md +++ b/docs/docs/02-installation/07-minimal-install.md @@ -44,6 +44,4 @@ docker run -d \ You **MUST** change the `super_random_string` to a true random string which you can generate with `openssl rand -hex 32`. ::: -Check the [configuration docs](/configuration) for extra features to enable such as full page archival, full page screenshots, inference languages, etc. - - +Check the [configuration docs](../configuration/environment-variables) for extra features to enable such as full page archival, full page screenshots, inference languages, etc. diff --git a/docs/docs/03-configuration.md b/docs/docs/03-configuration.md deleted file mode 100644 index b89460e6..00000000 --- a/docs/docs/03-configuration.md +++ /dev/null @@ -1,239 +0,0 @@ -# Configuration - -The app is mainly configured by environment variables. All the used environment variables are listed in [packages/shared/config.ts](https://github.com/karakeep-app/karakeep/blob/main/packages/shared/config.ts). The most important ones are: - -| Name | Required | Default | Description | -| -------------------------------------- | ------------------------------------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| PORT | No | 3000 | The port on which the web server will listen. DON'T CHANGE THIS IF YOU'RE USING DOCKER, instead changed the docker bound external port. | -| WORKERS_PORT | No | 0 (Random Port) | The port on which the worker will export its prometheus metrics on `/metrics`. By default it's a random unused port. If you want to utilize those metrics, fix the port to a value (and export it in docker if you're using docker). | -| WORKERS_HOST | No | 127.0.0.1 | Host to listen to for requests to WORKERS_PORT. You will need to set this if running in a container, since localhost will not be reachable from outside | -| WORKERS_ENABLED_WORKERS | No | Not set | Comma separated list of worker names to enable. If set, only these workers will run. Valid values: crawler,inference,search,adminMaintenance,video,feed,assetPreprocessing,webhook,ruleEngine. | -| WORKERS_DISABLED_WORKERS | No | Not set | Comma separated list of worker names to disable. Takes precedence over `WORKERS_ENABLED_WORKERS`. | -| LOG_LEVEL | No | debug | The application log level as defined in the [winston documentation](https://github.com/winstonjs/winston?tab=readme-ov-file#logging-levels). You may want to set this to `notice` or `warning` when running Karakeep in a production environment. | -| DATA_DIR | Yes | Not set | The path for the persistent data directory. This is where the db lives. Assets are stored here by default unless `ASSETS_DIR` is set. | -| ASSETS_DIR | No | Not set | The path where crawled assets will be stored. If not set, defaults to `${DATA_DIR}/assets`. | -| NEXTAUTH_URL | Yes | Not set | Should point to the address of your server. The app will function without it, but will redirect you to wrong addresses on signout for example. | -| NEXTAUTH_SECRET | Yes | Not set | Random string used to sign the JWT tokens. Generate one with `openssl rand -base64 36`. | -| MEILI_ADDR | No | Not set | The address of meilisearch. If not set, Search will be disabled. E.g. (`http://meilisearch:7700`) | -| MEILI_MASTER_KEY | Only in Prod and if search is enabled | Not set | The master key configured for meilisearch. Not needed in development environment. Generate one with `openssl rand -base64 36 \| tr -dc 'A-Za-z0-9'` | -| MAX_ASSET_SIZE_MB | No | 50 | Sets the maximum allowed asset size (in MB) to be uploaded | -| DISABLE_NEW_RELEASE_CHECK | No | false | If set to true, latest release check will be disabled in the admin panel. | -| PROMETHEUS_AUTH_TOKEN | No | Random | Enable a prometheus metrics endpoint at `/api/metrics`. This endpoint will require this token being passed in the Authorization header as a Bearer token. If not set, a new random token is generated everytime at startup. This cannot contain any special characters or you may encounter a 400 Bad Request response. | -| RATE_LIMITING_ENABLED | No | false | If set to true, API rate limiting will be enabled. | -| CRAWLER_DOMAIN_RATE_LIMIT_WINDOW_MS | No | Not set | Time window in milliseconds for per-domain crawler rate limiting. | -| CRAWLER_DOMAIN_RATE_LIMIT_MAX_REQUESTS | No | Not set | Maximum crawler requests allowed per domain inside the configured window. | -| DB_WAL_MODE | No | false | Enables WAL mode for the sqlite database. This should improve the performance of the database. There's no reason why you shouldn't set this to true unless you're running the db on a network attached drive. This will become the default at some time in the future. | -| SEARCH_NUM_WORKERS | No | 1 | Number of concurrent workers for search indexing tasks. Increase this if you have a high volume of content being indexed for search. | -| SEARCH_JOB_TIMEOUT_SEC | No | 30 | How long to wait for a search indexing job to finish before timing out. Increase this if you have large bookmarks with extensive content that takes longer to index. | -| WEBHOOK_NUM_WORKERS | No | 1 | Number of concurrent workers for webhook delivery. Increase this if you have multiple webhook endpoints or high webhook traffic. | -| ASSET_PREPROCESSING_NUM_WORKERS | No | 1 | Number of concurrent workers for asset preprocessing tasks (image processing, OCR, etc.). Increase this if you have many images or documents that need processing. | -| ASSET_PREPROCESSING_JOB_TIMEOUT_SEC | No | 60 | How long to wait for an asset preprocessing job to finish before timing out. Increase this if you have large images or PDFs that take longer to process. | -| RULE_ENGINE_NUM_WORKERS | No | 1 | Number of concurrent workers for rule engine processing. Increase this if you have complex automation rules that need to be processed quickly. | - -## Asset Storage - -Karakeep supports two storage backends for assets: local filesystem (default) and S3-compatible object storage. S3 storage is automatically detected when an S3 endpoint is passed. - -| Name | Required | Default | Description | -| -------------------------------- | ----------------- | ------- | --------------------------------------------------------------------------------------------------------- | -| ASSET_STORE_S3_ENDPOINT | No | Not set | The S3 endpoint URL. Required for S3-compatible services like MinIO. **Setting this enables S3 storage**. | -| ASSET_STORE_S3_REGION | No | Not set | The S3 region to use. | -| ASSET_STORE_S3_BUCKET | Yes when using S3 | Not set | The S3 bucket name where assets will be stored. | -| ASSET_STORE_S3_ACCESS_KEY_ID | Yes when using S3 | Not set | The S3 access key ID for authentication. | -| ASSET_STORE_S3_SECRET_ACCESS_KEY | Yes when using S3 | Not set | The S3 secret access key for authentication. | -| ASSET_STORE_S3_FORCE_PATH_STYLE | No | false | Whether to force path-style URLs for S3 requests. Set to true for MinIO and other S3-compatible services. | - -:::info -When using S3 storage, make sure the bucket exists and the provided credentials have the necessary permissions to read, write, and delete objects in the bucket. -::: - -:::warning -Switching between storage backends after data has been stored will require manual migration of existing assets. Plan your storage backend choice carefully before deploying. -::: - -## Authentication / Signup - -By default, Karakeep uses the database to store users, but it is possible to also use OAuth. -The flags need to be provided to the `web` container. - -:::info -Only OIDC compliant OAuth providers are supported! For information on how to set it up, consult the documentation of your provider. -::: - -:::info -When setting up OAuth, the allowed redirect URLs configured at the provider should be set to `/api/auth/callback/custom` where `` is the address you configured in `NEXTAUTH_URL` (for example: `https://try.karakeep.app/api/auth/callback/custom`). -::: - -| Name | Required | Default | Description | -| ------------------------------------------- | -------- | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| DISABLE_SIGNUPS | No | false | If enabled, no new signups will be allowed and the signup button will be disabled in the UI | -| DISABLE_PASSWORD_AUTH | No | false | If enabled, only signups and logins using OAuth are allowed and the signup button and login form for local accounts will be disabled in the UI | -| EMAIL_VERIFICATION_REQUIRED | No | false | Whether email verification is required during user signup. If enabled, users must verify their email address before they can use their account. If you enable this, you must configure SMTP settings. | -| OAUTH_WELLKNOWN_URL | No | Not set | The "wellknown Url" for openid-configuration as provided by the OAuth provider | -| OAUTH_CLIENT_SECRET | No | Not set | The "Client Secret" as provided by the OAuth provider | -| OAUTH_CLIENT_ID | No | Not set | The "Client ID" as provided by the OAuth provider | -| OAUTH_SCOPE | No | "openid email profile" | "Full list of scopes to request (space delimited)" | -| OAUTH_PROVIDER_NAME | No | "Custom Provider" | The name of your provider. Will be shown on the signup page as "Sign in with ``" | -| OAUTH_ALLOW_DANGEROUS_EMAIL_ACCOUNT_LINKING | No | false | Whether existing accounts in karakeep stored in the database should automatically be linked with your OAuth account. Only enable it if you trust the OAuth provider! | -| OAUTH_TIMEOUT | No | 3500 | The wait time in milliseconds for the OAuth provider response. Increase this if you are having `outgoing request timed out` errors | - -For more information on `OAUTH_ALLOW_DANGEROUS_EMAIL_ACCOUNT_LINKING`, check the [next-auth.js documentation](https://next-auth.js.org/configuration/providers/oauth#allowdangerousemailaccountlinking-option). - -## Inference Configs (For automatic tagging) - -Either `OPENAI_API_KEY` or `OLLAMA_BASE_URL` need to be set for automatic tagging to be enabled. Otherwise, automatic tagging will be skipped. - -:::warning - -- The quality of the tags you'll get will depend on the quality of the model you choose. -- You might want to tune the `INFERENCE_CONTEXT_LENGTH` as the default is quite small. The larger the value, the better the quality of the tags, but the more expensive the inference will be (money-wise on OpenAI and resource-wise on ollama). - ::: - -| Name | Required | Default | Description | -| ------------------------------------ | -------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| OPENAI_API_KEY | No | Not set | The OpenAI key used for automatic tagging. More on that in [here](/openai). | -| OPENAI_BASE_URL | No | Not set | If you just want to use OpenAI you don't need to pass this variable. If, however, you want to use some other openai compatible API (e.g. azure openai service), set this to the url of the API. | -| OLLAMA_BASE_URL | No | Not set | If you want to use ollama for local inference, set the address of ollama API here. | -| OLLAMA_KEEP_ALIVE | No | Not set | Controls how long the model will stay loaded into memory following the request (example value: "5m"). | -| INFERENCE_TEXT_MODEL | No | gpt-4.1-mini | The model to use for text inference. You'll need to change this to some other model if you're using ollama. | -| INFERENCE_IMAGE_MODEL | No | gpt-4o-mini | The model to use for image inference. You'll need to change this to some other model if you're using ollama and that model needs to support vision APIs (e.g. llava). | -| EMBEDDING_TEXT_MODEL | No | text-embedding-3-small | The model to be used for generating embeddings for the text. | -| INFERENCE_CONTEXT_LENGTH | No | 2048 | The max number of tokens that we'll pass to the inference model. If your content is larger than this size, it'll be truncated to fit. The larger this value, the more of the content will be used in tag inference, but the more expensive the inference will be (money-wise on openAI and resource-wise on ollama). Check the model you're using for its max supported content size. | -| INFERENCE_MAX_OUTPUT_TOKENS | No | 2048 | The maximum number of tokens that the inference model is allowed to generate in its response. This controls the length of AI-generated content like tags and summaries. Increase this if you need longer responses, but be aware that higher values will increase costs (for OpenAI) and processing time. | -| INFERENCE_USE_MAX_COMPLETION_TOKENS | No | false | \[OpenAI Only\] Whether to use the newer `max_completion_tokens` parameter instead of the deprecated `max_tokens` parameter. Set to `true` if using GPT-5 or o-series models which require this. Will become the default in a future release. | -| INFERENCE_LANG | No | english | The language in which the tags will be generated. | -| INFERENCE_NUM_WORKERS | No | 1 | Number of concurrent workers for AI inference tasks (tagging and summarization). Increase this if you have multiple AI inference requests and want to process them in parallel. | -| INFERENCE_ENABLE_AUTO_TAGGING | No | true | Whether automatic AI tagging is enabled or disabled. | -| INFERENCE_ENABLE_AUTO_SUMMARIZATION | No | false | Whether automatic AI summarization is enabled or disabled. | -| INFERENCE_JOB_TIMEOUT_SEC | No | 30 | How long to wait for the inference job to finish before timing out. If you're running ollama without powerful GPUs, you might want to increase the timeout a bit. | -| INFERENCE_FETCH_TIMEOUT_SEC | No | 300 | \[Ollama Only\] The timeout of the fetch request to the ollama server. If your inference requests take longer than the default 5mins, you might want to increase this timeout. | -| INFERENCE_SUPPORTS_STRUCTURED_OUTPUT | No | Not set | \[DEPRECATED\] Whether the inference model supports structured output or not. Use INFERENCE_OUTPUT_SCHEMA instead. Setting this to true translates to INFERENCE_OUTPUT_SCHEMA=structured, and to false translates to INFERENCE_OUTPUT_SCHEMA=plain. | -| INFERENCE_OUTPUT_SCHEMA | No | structured | Possible values are "structured", "json", "plain". Structured is the preferred option, but if your model doesn't support it, you can use "json" if your model supports JSON mode, otherwise "plain" which should be supported by all the models but the model might not output the data in the correct format. | - -:::info - -- You can append additional instructions to the prompt used for automatic tagging, in the `AI Settings` (in the `User Settings` screen) -- You can use the placeholders `$tags`, `$aiTags`, `$userTags` in the prompt. These placeholders will be replaced with all tags, ai generated tags or human created tags when automatic tagging is performed (e.g. `[karakeep, computer, ai]`) - ::: - -## Crawler Configs - -| Name | Required | Default | Description | -| ---------------------------------------- | -------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| CRAWLER_NUM_WORKERS | No | 1 | Number of allowed concurrent crawling jobs. By default, we're only doing one crawling request at a time to avoid consuming a lot of resources. | -| BROWSER_WEB_URL | No | Not set | The browser's http debugging address. The worker will talk to this endpoint to resolve the debugging console's websocket address. If you already have the websocket address, use `BROWSER_WEBSOCKET_URL` instead. If neither `BROWSER_WEB_URL` nor `BROWSER_WEBSOCKET_URL` are set, the worker will use plain http requests skipping screenshotting and javascript execution. | -| BROWSER_WEBSOCKET_URL | No | Not set | The websocket address of browser's debugging console. If you want to use [browserless](https://browserless.io), use their websocket address here. If neither `BROWSER_WEB_URL` nor `BROWSER_WEBSOCKET_URL` are set, the worker will use plain http requests skipping screenshotting and javascript execution. | -| BROWSER_CONNECT_ONDEMAND | No | false | If set to false, the crawler will proactively connect to the browser instance and always maintain an active connection. If set to true, the browser will be launched on demand only whenever a crawling is requested. Set to true if you're using a service that provides you with browser instances on demand. | -| CRAWLER_DOWNLOAD_BANNER_IMAGE | No | true | Whether to cache the banner image used in the cards locally or fetch it each time directly from the website. Caching it consumes more storage space, but is more resilient against link rot and rate limits from websites. | -| CRAWLER_STORE_SCREENSHOT | No | true | Whether to store a screenshot from the crawled website or not. Screenshots act as a fallback for when we fail to extract an image from a website. You can also view the stored screenshots for any link. | -| CRAWLER_FULL_PAGE_SCREENSHOT | No | false | Whether to store a screenshot of the full page or not. Disabled by default, as it can lead to much higher disk usage. If disabled, the screenshot will only include the visible part of the page | -| CRAWLER_SCREENSHOT_TIMEOUT_SEC | No | 5 | How long to wait for the screenshot finish before timing out. If you are capturing full-page screenshots of long webpages, consider increasing this value. | -| CRAWLER_FULL_PAGE_ARCHIVE | No | false | Whether to store a full local copy of the page or not. Disabled by default, as it can lead to much higher disk usage. If disabled, only the readable text of the page is archived. | -| CRAWLER_JOB_TIMEOUT_SEC | No | 60 | How long to wait for the crawler job to finish before timing out. If you have a slow internet connection or a low powered device, you might want to bump this up a bit | -| CRAWLER_NAVIGATE_TIMEOUT_SEC | No | 30 | How long to spend navigating to the page (along with its redirects). Increase this if you have a slow internet connection | -| CRAWLER_VIDEO_DOWNLOAD | No | false | Whether to download videos from the page or not (using yt-dlp) | -| CRAWLER_VIDEO_DOWNLOAD_MAX_SIZE | No | 50 | The maximum file size for the downloaded video. The quality will be chosen accordingly. Use -1 to disable the limit. | -| CRAWLER_VIDEO_DOWNLOAD_TIMEOUT_SEC | No | 600 | How long to wait for the video download to finish | -| CRAWLER_ENABLE_ADBLOCKER | No | true | Whether to enable an adblocker in the crawler or not. If you're facing troubles downloading the adblocking lists on worker startup, you can disable this. | -| CRAWLER_YTDLP_ARGS | No | [] | Include additional yt-dlp arguments to be passed at crawl time separated by %%: https://github.com/yt-dlp/yt-dlp?tab=readme-ov-file#general-options | -| BROWSER_COOKIE_PATH | No | Not set | Path to a JSON file containing cookies to be loaded into the browser context. The file should be an array of cookie objects, each with name and value (required), and optional fields like domain, path, expires, httpOnly, secure, and sameSite (e.g., `[{"name": "session", "value": "xxx", "domain": ".example.com"}`]). | -| HTML_CONTENT_SIZE_INLINE_THRESHOLD_BYTES | No | 5 \* 1024 | The thresholds in bytes after which larger assets will be stored in the assetdb (folder/s3) instead of inline in the database. | - -
- - More info on BROWSER_COOKIE_PATH - -BROWSER_COOKIE_PATH specifies the path to a JSON file containing cookies to be loaded into the browser context for crawling. - -The JSON file must be an array of cookie objects, each with: - -- name: The cookie name (required). -- value: The cookie value (required). -- Optional fields: domain, path, expires, httpOnly, secure, sameSite (values: "Strict", "Lax", or "None"). - -Example JSON file: - -```json -[ - { - "name": "session", - "value": "xxx", - "domain": ".example.com", - "path": "/", - "expires": 1735689600, - "httpOnly": true, - "secure": true, - "sameSite": "Lax" - } -] -``` - -
- -## OCR Configs - -Karakeep uses [tesseract.js](https://github.com/naptha/tesseract.js) to extract text from images. - -| Name | Required | Default | Description | -| ------------------------ | -------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| OCR_CACHE_DIR | No | $TEMP_DIR | The dir where tesseract will download its models. By default, those models are not persisted and stored in the OS' temp dir. | -| OCR_LANGS | No | eng | Comma separated list of the language codes that you want tesseract to support. You can find the language codes [here](https://tesseract-ocr.github.io/tessdoc/Data-Files-in-different-versions.html). Set to empty string to disable OCR. | -| OCR_CONFIDENCE_THRESHOLD | No | 50 | A number between 0 and 100 indicating the minimum acceptable confidence from tessaract. If tessaract's confidence is lower than this value, extracted text won't be stored. | - -## Webhook Configs - -You can use webhooks to trigger actions when bookmarks are created, changed or crawled. - -| Name | Required | Default | Description | -| ------------------- | -------- | ------- | ------------------------------------------------- | -| WEBHOOK_TIMEOUT_SEC | No | 5 | The timeout for the webhook request in seconds. | -| WEBHOOK_RETRY_TIMES | No | 3 | The number of times to retry the webhook request. | - -:::info - -- The WEBHOOK_TOKEN is used for authentication. It will appear in the Authorization header as Bearer token. - ``` - Authorization: Bearer - ``` -- The webhook will be triggered with the job id (used for idempotence), bookmark id, bookmark type, the user id, the url and the operation in JSON format in the body. - - ```json - { - "jobId": "123", - "type": "link", - "bookmarkId": "exampleBookmarkId", - "userId": "exampleUserId", - "url": "https://example.com", - "operation": "crawled" - } - ``` - - ::: - -## SMTP Configuration - -Karakeep can send emails for various purposes such as email verification during signup. Configure these settings to enable email functionality. - -| Name | Required | Default | Description | -| ------------- | -------- | ------- | ----------------------------------------------------------------------------------------------- | -| SMTP_HOST | No | Not set | The SMTP server hostname or IP address. Required if you want to enable email functionality. | -| SMTP_PORT | No | 587 | The SMTP server port. Common values are 587 (STARTTLS), 465 (SSL/TLS), or 25 (unencrypted). | -| SMTP_SECURE | No | false | Whether to use SSL/TLS encryption. Set to true for port 465, false for port 587 with STARTTLS. | -| SMTP_USER | No | Not set | The username for SMTP authentication. Usually your email address. | -| SMTP_PASSWORD | No | Not set | The password for SMTP authentication. For services like Gmail, use an app-specific password. | -| SMTP_FROM | No | Not set | The "from" email address that will appear in sent emails. This should be a valid email address. | - -## Proxy Configuration - -If your Karakeep instance needs to connect through a proxy server, you can configure the following settings: - -| Name | Required | Default | Description | -| ---------------------------------- | -------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| CRAWLER_HTTP_PROXY | No | Not set | HTTP proxy server URL for outgoing HTTP requests (e.g., `http://proxy.example.com:8080`). You can pass multiple comma separated proxies and the used one will be chosen at random. The proxy is used for crawling, RSS feed fetches and webhooks. | -| CRAWLER_HTTPS_PROXY | No | Not set | HTTPS proxy server URL for outgoing HTTPS requests (e.g., `http://proxy.example.com:8080`). You can pass multiple comma separated proxies and the used one will be chosen at random. The proxy is used for crawling, RSS feed fetches and webhooks. | -| CRAWLER_NO_PROXY | No | Not set | Comma-separated list of hostnames/IPs that should bypass the proxy (e.g., `localhost,127.0.0.1,.local`) | -| CRAWLER_ALLOWED_INTERNAL_HOSTNAMES | No | Not set | By default, Karakeep blocks worker-initiated requests whose DNS resolves to private, loopback, or link-local IP addresses. Use this to allowlist specific hostnames for internal access (e.g., `internal.company.com,.local`). Supports domain wildcards by prefixing with a dot (e.g., `.internal.company.com`). Passing `.` allowlists all domains. Note: Internal IP validation is bypassed when a proxy is configured for the URL as the local DNS resolver won't necessarily be the same as the one used by the proxy. | - -:::info -These proxy settings will be used by the crawler and other components that make outgoing HTTP requests. -::: diff --git a/docs/docs/03-configuration/01-environment-variables.md b/docs/docs/03-configuration/01-environment-variables.md new file mode 100644 index 00000000..ff9721e8 --- /dev/null +++ b/docs/docs/03-configuration/01-environment-variables.md @@ -0,0 +1,239 @@ +# Configuration + +The app is mainly configured by environment variables. All the used environment variables are listed in [packages/shared/config.ts](https://github.com/karakeep-app/karakeep/blob/main/packages/shared/config.ts). The most important ones are: + +| Name | Required | Default | Description | +| -------------------------------------- | ------------------------------------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| PORT | No | 3000 | The port on which the web server will listen. DON'T CHANGE THIS IF YOU'RE USING DOCKER, instead changed the docker bound external port. | +| WORKERS_PORT | No | 0 (Random Port) | The port on which the worker will export its prometheus metrics on `/metrics`. By default it's a random unused port. If you want to utilize those metrics, fix the port to a value (and export it in docker if you're using docker). | +| WORKERS_HOST | No | 127.0.0.1 | Host to listen to for requests to WORKERS_PORT. You will need to set this if running in a container, since localhost will not be reachable from outside | +| WORKERS_ENABLED_WORKERS | No | Not set | Comma separated list of worker names to enable. If set, only these workers will run. Valid values: crawler,inference,search,adminMaintenance,video,feed,assetPreprocessing,webhook,ruleEngine. | +| WORKERS_DISABLED_WORKERS | No | Not set | Comma separated list of worker names to disable. Takes precedence over `WORKERS_ENABLED_WORKERS`. | +| LOG_LEVEL | No | debug | The application log level as defined in the [winston documentation](https://github.com/winstonjs/winston?tab=readme-ov-file#logging-levels). You may want to set this to `notice` or `warning` when running Karakeep in a production environment. | +| DATA_DIR | Yes | Not set | The path for the persistent data directory. This is where the db lives. Assets are stored here by default unless `ASSETS_DIR` is set. | +| ASSETS_DIR | No | Not set | The path where crawled assets will be stored. If not set, defaults to `${DATA_DIR}/assets`. | +| NEXTAUTH_URL | Yes | Not set | Should point to the address of your server. The app will function without it, but will redirect you to wrong addresses on signout for example. | +| NEXTAUTH_SECRET | Yes | Not set | Random string used to sign the JWT tokens. Generate one with `openssl rand -base64 36`. | +| MEILI_ADDR | No | Not set | The address of meilisearch. If not set, Search will be disabled. E.g. (`http://meilisearch:7700`) | +| MEILI_MASTER_KEY | Only in Prod and if search is enabled | Not set | The master key configured for meilisearch. Not needed in development environment. Generate one with `openssl rand -base64 36 \| tr -dc 'A-Za-z0-9'` | +| MAX_ASSET_SIZE_MB | No | 50 | Sets the maximum allowed asset size (in MB) to be uploaded | +| DISABLE_NEW_RELEASE_CHECK | No | false | If set to true, latest release check will be disabled in the admin panel. | +| PROMETHEUS_AUTH_TOKEN | No | Random | Enable a prometheus metrics endpoint at `/api/metrics`. This endpoint will require this token being passed in the Authorization header as a Bearer token. If not set, a new random token is generated everytime at startup. This cannot contain any special characters or you may encounter a 400 Bad Request response. | +| RATE_LIMITING_ENABLED | No | false | If set to true, API rate limiting will be enabled. | +| CRAWLER_DOMAIN_RATE_LIMIT_WINDOW_MS | No | Not set | Time window in milliseconds for per-domain crawler rate limiting. | +| CRAWLER_DOMAIN_RATE_LIMIT_MAX_REQUESTS | No | Not set | Maximum crawler requests allowed per domain inside the configured window. | +| DB_WAL_MODE | No | false | Enables WAL mode for the sqlite database. This should improve the performance of the database. There's no reason why you shouldn't set this to true unless you're running the db on a network attached drive. This will become the default at some time in the future. | +| SEARCH_NUM_WORKERS | No | 1 | Number of concurrent workers for search indexing tasks. Increase this if you have a high volume of content being indexed for search. | +| SEARCH_JOB_TIMEOUT_SEC | No | 30 | How long to wait for a search indexing job to finish before timing out. Increase this if you have large bookmarks with extensive content that takes longer to index. | +| WEBHOOK_NUM_WORKERS | No | 1 | Number of concurrent workers for webhook delivery. Increase this if you have multiple webhook endpoints or high webhook traffic. | +| ASSET_PREPROCESSING_NUM_WORKERS | No | 1 | Number of concurrent workers for asset preprocessing tasks (image processing, OCR, etc.). Increase this if you have many images or documents that need processing. | +| ASSET_PREPROCESSING_JOB_TIMEOUT_SEC | No | 60 | How long to wait for an asset preprocessing job to finish before timing out. Increase this if you have large images or PDFs that take longer to process. | +| RULE_ENGINE_NUM_WORKERS | No | 1 | Number of concurrent workers for rule engine processing. Increase this if you have complex automation rules that need to be processed quickly. | + +## Asset Storage + +Karakeep supports two storage backends for assets: local filesystem (default) and S3-compatible object storage. S3 storage is automatically detected when an S3 endpoint is passed. + +| Name | Required | Default | Description | +| -------------------------------- | ----------------- | ------- | --------------------------------------------------------------------------------------------------------- | +| ASSET_STORE_S3_ENDPOINT | No | Not set | The S3 endpoint URL. Required for S3-compatible services like MinIO. **Setting this enables S3 storage**. | +| ASSET_STORE_S3_REGION | No | Not set | The S3 region to use. | +| ASSET_STORE_S3_BUCKET | Yes when using S3 | Not set | The S3 bucket name where assets will be stored. | +| ASSET_STORE_S3_ACCESS_KEY_ID | Yes when using S3 | Not set | The S3 access key ID for authentication. | +| ASSET_STORE_S3_SECRET_ACCESS_KEY | Yes when using S3 | Not set | The S3 secret access key for authentication. | +| ASSET_STORE_S3_FORCE_PATH_STYLE | No | false | Whether to force path-style URLs for S3 requests. Set to true for MinIO and other S3-compatible services. | + +:::info +When using S3 storage, make sure the bucket exists and the provided credentials have the necessary permissions to read, write, and delete objects in the bucket. +::: + +:::warning +Switching between storage backends after data has been stored will require manual migration of existing assets. Plan your storage backend choice carefully before deploying. +::: + +## Authentication / Signup + +By default, Karakeep uses the database to store users, but it is possible to also use OAuth. +The flags need to be provided to the `web` container. + +:::info +Only OIDC compliant OAuth providers are supported! For information on how to set it up, consult the documentation of your provider. +::: + +:::info +When setting up OAuth, the allowed redirect URLs configured at the provider should be set to `/api/auth/callback/custom` where `` is the address you configured in `NEXTAUTH_URL` (for example: `https://try.karakeep.app/api/auth/callback/custom`). +::: + +| Name | Required | Default | Description | +| ------------------------------------------- | -------- | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| DISABLE_SIGNUPS | No | false | If enabled, no new signups will be allowed and the signup button will be disabled in the UI | +| DISABLE_PASSWORD_AUTH | No | false | If enabled, only signups and logins using OAuth are allowed and the signup button and login form for local accounts will be disabled in the UI | +| EMAIL_VERIFICATION_REQUIRED | No | false | Whether email verification is required during user signup. If enabled, users must verify their email address before they can use their account. If you enable this, you must configure SMTP settings. | +| OAUTH_WELLKNOWN_URL | No | Not set | The "wellknown Url" for openid-configuration as provided by the OAuth provider | +| OAUTH_CLIENT_SECRET | No | Not set | The "Client Secret" as provided by the OAuth provider | +| OAUTH_CLIENT_ID | No | Not set | The "Client ID" as provided by the OAuth provider | +| OAUTH_SCOPE | No | "openid email profile" | "Full list of scopes to request (space delimited)" | +| OAUTH_PROVIDER_NAME | No | "Custom Provider" | The name of your provider. Will be shown on the signup page as "Sign in with ``" | +| OAUTH_ALLOW_DANGEROUS_EMAIL_ACCOUNT_LINKING | No | false | Whether existing accounts in karakeep stored in the database should automatically be linked with your OAuth account. Only enable it if you trust the OAuth provider! | +| OAUTH_TIMEOUT | No | 3500 | The wait time in milliseconds for the OAuth provider response. Increase this if you are having `outgoing request timed out` errors | + +For more information on `OAUTH_ALLOW_DANGEROUS_EMAIL_ACCOUNT_LINKING`, check the [next-auth.js documentation](https://next-auth.js.org/configuration/providers/oauth#allowdangerousemailaccountlinking-option). + +## Inference Configs (For automatic tagging) + +Either `OPENAI_API_KEY` or `OLLAMA_BASE_URL` need to be set for automatic tagging to be enabled. Otherwise, automatic tagging will be skipped. + +:::warning + +- The quality of the tags you'll get will depend on the quality of the model you choose. +- You might want to tune the `INFERENCE_CONTEXT_LENGTH` as the default is quite small. The larger the value, the better the quality of the tags, but the more expensive the inference will be (money-wise on OpenAI and resource-wise on ollama). + ::: + +| Name | Required | Default | Description | +| ------------------------------------ | -------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| OPENAI_API_KEY | No | Not set | The OpenAI key used for automatic tagging. More on that in [here](../integrations/openai). | +| OPENAI_BASE_URL | No | Not set | If you just want to use OpenAI you don't need to pass this variable. If, however, you want to use some other openai compatible API (e.g. azure openai service), set this to the url of the API. | +| OLLAMA_BASE_URL | No | Not set | If you want to use ollama for local inference, set the address of ollama API here. | +| OLLAMA_KEEP_ALIVE | No | Not set | Controls how long the model will stay loaded into memory following the request (example value: "5m"). | +| INFERENCE_TEXT_MODEL | No | gpt-4.1-mini | The model to use for text inference. You'll need to change this to some other model if you're using ollama. | +| INFERENCE_IMAGE_MODEL | No | gpt-4o-mini | The model to use for image inference. You'll need to change this to some other model if you're using ollama and that model needs to support vision APIs (e.g. llava). | +| EMBEDDING_TEXT_MODEL | No | text-embedding-3-small | The model to be used for generating embeddings for the text. | +| INFERENCE_CONTEXT_LENGTH | No | 2048 | The max number of tokens that we'll pass to the inference model. If your content is larger than this size, it'll be truncated to fit. The larger this value, the more of the content will be used in tag inference, but the more expensive the inference will be (money-wise on openAI and resource-wise on ollama). Check the model you're using for its max supported content size. | +| INFERENCE_MAX_OUTPUT_TOKENS | No | 2048 | The maximum number of tokens that the inference model is allowed to generate in its response. This controls the length of AI-generated content like tags and summaries. Increase this if you need longer responses, but be aware that higher values will increase costs (for OpenAI) and processing time. | +| INFERENCE_USE_MAX_COMPLETION_TOKENS | No | false | \[OpenAI Only\] Whether to use the newer `max_completion_tokens` parameter instead of the deprecated `max_tokens` parameter. Set to `true` if using GPT-5 or o-series models which require this. Will become the default in a future release. | +| INFERENCE_LANG | No | english | The language in which the tags will be generated. | +| INFERENCE_NUM_WORKERS | No | 1 | Number of concurrent workers for AI inference tasks (tagging and summarization). Increase this if you have multiple AI inference requests and want to process them in parallel. | +| INFERENCE_ENABLE_AUTO_TAGGING | No | true | Whether automatic AI tagging is enabled or disabled. | +| INFERENCE_ENABLE_AUTO_SUMMARIZATION | No | false | Whether automatic AI summarization is enabled or disabled. | +| INFERENCE_JOB_TIMEOUT_SEC | No | 30 | How long to wait for the inference job to finish before timing out. If you're running ollama without powerful GPUs, you might want to increase the timeout a bit. | +| INFERENCE_FETCH_TIMEOUT_SEC | No | 300 | \[Ollama Only\] The timeout of the fetch request to the ollama server. If your inference requests take longer than the default 5mins, you might want to increase this timeout. | +| INFERENCE_SUPPORTS_STRUCTURED_OUTPUT | No | Not set | \[DEPRECATED\] Whether the inference model supports structured output or not. Use INFERENCE_OUTPUT_SCHEMA instead. Setting this to true translates to INFERENCE_OUTPUT_SCHEMA=structured, and to false translates to INFERENCE_OUTPUT_SCHEMA=plain. | +| INFERENCE_OUTPUT_SCHEMA | No | structured | Possible values are "structured", "json", "plain". Structured is the preferred option, but if your model doesn't support it, you can use "json" if your model supports JSON mode, otherwise "plain" which should be supported by all the models but the model might not output the data in the correct format. | + +:::info + +- You can append additional instructions to the prompt used for automatic tagging, in the `AI Settings` (in the `User Settings` screen) +- You can use the placeholders `$tags`, `$aiTags`, `$userTags` in the prompt. These placeholders will be replaced with all tags, ai generated tags or human created tags when automatic tagging is performed (e.g. `[karakeep, computer, ai]`) + ::: + +## Crawler Configs + +| Name | Required | Default | Description | +| ---------------------------------------- | -------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| CRAWLER_NUM_WORKERS | No | 1 | Number of allowed concurrent crawling jobs. By default, we're only doing one crawling request at a time to avoid consuming a lot of resources. | +| BROWSER_WEB_URL | No | Not set | The browser's http debugging address. The worker will talk to this endpoint to resolve the debugging console's websocket address. If you already have the websocket address, use `BROWSER_WEBSOCKET_URL` instead. If neither `BROWSER_WEB_URL` nor `BROWSER_WEBSOCKET_URL` are set, the worker will use plain http requests skipping screenshotting and javascript execution. | +| BROWSER_WEBSOCKET_URL | No | Not set | The websocket address of browser's debugging console. If you want to use [browserless](https://browserless.io), use their websocket address here. If neither `BROWSER_WEB_URL` nor `BROWSER_WEBSOCKET_URL` are set, the worker will use plain http requests skipping screenshotting and javascript execution. | +| BROWSER_CONNECT_ONDEMAND | No | false | If set to false, the crawler will proactively connect to the browser instance and always maintain an active connection. If set to true, the browser will be launched on demand only whenever a crawling is requested. Set to true if you're using a service that provides you with browser instances on demand. | +| CRAWLER_DOWNLOAD_BANNER_IMAGE | No | true | Whether to cache the banner image used in the cards locally or fetch it each time directly from the website. Caching it consumes more storage space, but is more resilient against link rot and rate limits from websites. | +| CRAWLER_STORE_SCREENSHOT | No | true | Whether to store a screenshot from the crawled website or not. Screenshots act as a fallback for when we fail to extract an image from a website. You can also view the stored screenshots for any link. | +| CRAWLER_FULL_PAGE_SCREENSHOT | No | false | Whether to store a screenshot of the full page or not. Disabled by default, as it can lead to much higher disk usage. If disabled, the screenshot will only include the visible part of the page | +| CRAWLER_SCREENSHOT_TIMEOUT_SEC | No | 5 | How long to wait for the screenshot finish before timing out. If you are capturing full-page screenshots of long webpages, consider increasing this value. | +| CRAWLER_FULL_PAGE_ARCHIVE | No | false | Whether to store a full local copy of the page or not. Disabled by default, as it can lead to much higher disk usage. If disabled, only the readable text of the page is archived. | +| CRAWLER_JOB_TIMEOUT_SEC | No | 60 | How long to wait for the crawler job to finish before timing out. If you have a slow internet connection or a low powered device, you might want to bump this up a bit | +| CRAWLER_NAVIGATE_TIMEOUT_SEC | No | 30 | How long to spend navigating to the page (along with its redirects). Increase this if you have a slow internet connection | +| CRAWLER_VIDEO_DOWNLOAD | No | false | Whether to download videos from the page or not (using yt-dlp) | +| CRAWLER_VIDEO_DOWNLOAD_MAX_SIZE | No | 50 | The maximum file size for the downloaded video. The quality will be chosen accordingly. Use -1 to disable the limit. | +| CRAWLER_VIDEO_DOWNLOAD_TIMEOUT_SEC | No | 600 | How long to wait for the video download to finish | +| CRAWLER_ENABLE_ADBLOCKER | No | true | Whether to enable an adblocker in the crawler or not. If you're facing troubles downloading the adblocking lists on worker startup, you can disable this. | +| CRAWLER_YTDLP_ARGS | No | [] | Include additional yt-dlp arguments to be passed at crawl time separated by %%: https://github.com/yt-dlp/yt-dlp?tab=readme-ov-file#general-options | +| BROWSER_COOKIE_PATH | No | Not set | Path to a JSON file containing cookies to be loaded into the browser context. The file should be an array of cookie objects, each with name and value (required), and optional fields like domain, path, expires, httpOnly, secure, and sameSite (e.g., `[{"name": "session", "value": "xxx", "domain": ".example.com"}`]). | +| HTML_CONTENT_SIZE_INLINE_THRESHOLD_BYTES | No | 5 \* 1024 | The thresholds in bytes after which larger assets will be stored in the assetdb (folder/s3) instead of inline in the database. | + +
+ + More info on BROWSER_COOKIE_PATH + +BROWSER_COOKIE_PATH specifies the path to a JSON file containing cookies to be loaded into the browser context for crawling. + +The JSON file must be an array of cookie objects, each with: + +- name: The cookie name (required). +- value: The cookie value (required). +- Optional fields: domain, path, expires, httpOnly, secure, sameSite (values: "Strict", "Lax", or "None"). + +Example JSON file: + +```json +[ + { + "name": "session", + "value": "xxx", + "domain": ".example.com", + "path": "/", + "expires": 1735689600, + "httpOnly": true, + "secure": true, + "sameSite": "Lax" + } +] +``` + +
+ +## OCR Configs + +Karakeep uses [tesseract.js](https://github.com/naptha/tesseract.js) to extract text from images. + +| Name | Required | Default | Description | +| ------------------------ | -------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| OCR_CACHE_DIR | No | $TEMP_DIR | The dir where tesseract will download its models. By default, those models are not persisted and stored in the OS' temp dir. | +| OCR_LANGS | No | eng | Comma separated list of the language codes that you want tesseract to support. You can find the language codes [here](https://tesseract-ocr.github.io/tessdoc/Data-Files-in-different-versions.html). Set to empty string to disable OCR. | +| OCR_CONFIDENCE_THRESHOLD | No | 50 | A number between 0 and 100 indicating the minimum acceptable confidence from tessaract. If tessaract's confidence is lower than this value, extracted text won't be stored. | + +## Webhook Configs + +You can use webhooks to trigger actions when bookmarks are created, changed or crawled. + +| Name | Required | Default | Description | +| ------------------- | -------- | ------- | ------------------------------------------------- | +| WEBHOOK_TIMEOUT_SEC | No | 5 | The timeout for the webhook request in seconds. | +| WEBHOOK_RETRY_TIMES | No | 3 | The number of times to retry the webhook request. | + +:::info + +- The WEBHOOK_TOKEN is used for authentication. It will appear in the Authorization header as Bearer token. + ``` + Authorization: Bearer + ``` +- The webhook will be triggered with the job id (used for idempotence), bookmark id, bookmark type, the user id, the url and the operation in JSON format in the body. + + ```json + { + "jobId": "123", + "type": "link", + "bookmarkId": "exampleBookmarkId", + "userId": "exampleUserId", + "url": "https://example.com", + "operation": "crawled" + } + ``` + + ::: + +## SMTP Configuration + +Karakeep can send emails for various purposes such as email verification during signup. Configure these settings to enable email functionality. + +| Name | Required | Default | Description | +| ------------- | -------- | ------- | ----------------------------------------------------------------------------------------------- | +| SMTP_HOST | No | Not set | The SMTP server hostname or IP address. Required if you want to enable email functionality. | +| SMTP_PORT | No | 587 | The SMTP server port. Common values are 587 (STARTTLS), 465 (SSL/TLS), or 25 (unencrypted). | +| SMTP_SECURE | No | false | Whether to use SSL/TLS encryption. Set to true for port 465, false for port 587 with STARTTLS. | +| SMTP_USER | No | Not set | The username for SMTP authentication. Usually your email address. | +| SMTP_PASSWORD | No | Not set | The password for SMTP authentication. For services like Gmail, use an app-specific password. | +| SMTP_FROM | No | Not set | The "from" email address that will appear in sent emails. This should be a valid email address. | + +## Proxy Configuration + +If your Karakeep instance needs to connect through a proxy server, you can configure the following settings: + +| Name | Required | Default | Description | +| ---------------------------------- | -------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| CRAWLER_HTTP_PROXY | No | Not set | HTTP proxy server URL for outgoing HTTP requests (e.g., `http://proxy.example.com:8080`). You can pass multiple comma separated proxies and the used one will be chosen at random. The proxy is used for crawling, RSS feed fetches and webhooks. | +| CRAWLER_HTTPS_PROXY | No | Not set | HTTPS proxy server URL for outgoing HTTPS requests (e.g., `http://proxy.example.com:8080`). You can pass multiple comma separated proxies and the used one will be chosen at random. The proxy is used for crawling, RSS feed fetches and webhooks. | +| CRAWLER_NO_PROXY | No | Not set | Comma-separated list of hostnames/IPs that should bypass the proxy (e.g., `localhost,127.0.0.1,.local`) | +| CRAWLER_ALLOWED_INTERNAL_HOSTNAMES | No | Not set | By default, Karakeep blocks worker-initiated requests whose DNS resolves to private, loopback, or link-local IP addresses. Use this to allowlist specific hostnames for internal access (e.g., `internal.company.com,.local`). Supports domain wildcards by prefixing with a dot (e.g., `.internal.company.com`). Passing `.` allowlists all domains. Note: Internal IP validation is bypassed when a proxy is configured for the URL as the local DNS resolver won't necessarily be the same as the one used by the proxy. | + +:::info +These proxy settings will be used by the crawler and other components that make outgoing HTTP requests. +::: diff --git a/docs/docs/03-configuration/_category_.json b/docs/docs/03-configuration/_category_.json new file mode 100644 index 00000000..78e56008 --- /dev/null +++ b/docs/docs/03-configuration/_category_.json @@ -0,0 +1,3 @@ +{ + "label": "Configuration" +} diff --git a/docs/docs/04-screenshots.md b/docs/docs/04-screenshots.md deleted file mode 100644 index 07830566..00000000 --- a/docs/docs/04-screenshots.md +++ /dev/null @@ -1,34 +0,0 @@ -# Screenshots - -## Homepage - -![Homepage](/img/screenshots/homepage.png) - -## Homepage (Dark Mode) - -![Homepage](/img/screenshots/homepage-dark.png) - -## Tags - -![All Tags](/img/screenshots/all-tags.png) - -## Lists - -![All Lists](/img/screenshots/all-lists.png) - -## Bookmark Preview - -![Bookmark Preview](/img/screenshots/bookmark-preview.png) - -## Settings - -![Settings](/img/screenshots/settings.png) - -## Admin Panel - -![Ammin](/img/screenshots/admin.png) - - -## iOS Sharing - - diff --git a/docs/docs/04-using-karakeep/01-quick-sharing.md b/docs/docs/04-using-karakeep/01-quick-sharing.md new file mode 100644 index 00000000..254bec84 --- /dev/null +++ b/docs/docs/04-using-karakeep/01-quick-sharing.md @@ -0,0 +1,21 @@ +# Quick Sharing Extensions + +The whole point of Karakeep is making it easy to hoard the content. That's why there are a couple of + +## Mobile Apps + +mobile screenshot + + +- **iOS app**: [App Store Link](https://apps.apple.com/us/app/karakeep-app/id6479258022). +- **Android App**: [Play Store link](https://play.google.com/store/apps/details?id=app.hoarder.hoardermobile&pcampaignid=web_share). + +## Browser Extensions + +mobile screenshot + +- **Chrome extension**: [here](https://chromewebstore.google.com/detail/karakeep/kgcjekpmcjjogibpjebkhaanilehneje). +- **Firefox addon**: [here](https://addons.mozilla.org/en-US/firefox/addon/karakeep/). + +- ## Community Extensions +- **Safari extension**: [App Store Link](https://apps.apple.com/us/app/karakeeper-bookmarker/id6746722790). For macOS and iOS to allow a simple way to add your bookmarks to your self hosted karakeep instance. diff --git a/docs/docs/04-using-karakeep/02-import.md b/docs/docs/04-using-karakeep/02-import.md new file mode 100644 index 00000000..4114ff79 --- /dev/null +++ b/docs/docs/04-using-karakeep/02-import.md @@ -0,0 +1,49 @@ +# Importing Bookmarks + + +Karakeep supports importing bookmarks using the Netscape HTML Format, Pocket's new CSV format & Omnivore's JSONs. Titles, tags and addition date will be preserved during the import. An automatically created list will contain all the imported bookmarks. + +:::info +All the URLs in the bookmarks file will be added automatically, you will not be able to pick and choose which bookmarks to import! +::: + +## Import from Chrome + +- Open Chrome and go to `chrome://bookmarks` +- Click on the three dots on the top right corner and choose `Export bookmarks` +- This will download an html file with all of your bookmarks. +- To import the bookmark file, go to the settings and click "Import Bookmarks from HTML file". + +## Import from Firefox +- Open Firefox and click on the menu button (☰) in the top right corner. +- Navigate to Bookmarks > Manage bookmarks (or press Ctrl + Shift + O / Cmd + Shift + O to open the Bookmarks Library). +- In the Bookmarks Library, click the Import and Backup button at the top. Select Export Bookmarks to HTML... to save your bookmarks as an HTML file. +- To import a bookmark file, go back to the Import and Backup menu, then select Import Bookmarks from HTML... and choose your saved HTML file. + +## Import from Pocket + +- Go to the [Pocket export page](https://getpocket.com/export) and follow the instructions to export your bookmarks. +- Pocket after a couple of minutes will mail you a zip file with all the bookmarks. +- Unzip the file and you'll get a CSV file. +- To import the bookmark file, go to the settings and click "Import Bookmarks from Pocket export". + +## Import from Omnivore + +- Follow Omnivore's [documentation](https://docs.omnivore.app/using/exporting.html) to export your bookmarks. +- This will give you a zip file with all your data. +- The zip file contains a lot of JSONs in the format `metadata_*.json`. You can either import every JSON file manually, or merge the JSONs into a single JSON file and import that. +- To merge the JSONs into a single JSON file, you can use the following command in the unzipped directory: `jq -r '.[]' metadata_*.json | jq -s > omnivore.json` and then import the `omnivore.json` file. You'll need to have the [jq](https://github.com/jqlang/jq) tool installed. + +## Import using the CLI + +:::warning +Importing bookmarks using the CLI requires some technical knowledge and might not be very straightforward for non-technical users. Don't hesitate to ask questions in github discussions or discord though. +::: + +If you can get your bookmarks in a text file with one link per line, you can use the following command to import them using the [karakeep cli](../integrations/command-line): + +``` +while IFS= read -r url; do + karakeep --api-key "" --server-addr "" bookmarks add --link "$url" +done < all_links.txt +``` diff --git a/docs/docs/04-using-karakeep/03-search-query-language.md b/docs/docs/04-using-karakeep/03-search-query-language.md new file mode 100644 index 00000000..8f55ec2f --- /dev/null +++ b/docs/docs/04-using-karakeep/03-search-query-language.md @@ -0,0 +1,76 @@ +# Search Query Language + +Karakeep provides a search query language to filter and find bookmarks. Here are all the supported qualifiers and how to use them: + +## Basic Syntax + +- Use spaces to separate multiple conditions (implicit AND) +- Use `and`/`or` keywords for explicit boolean logic +- Prefix qualifiers with `-` to negate them +- Use parentheses `()` for grouping conditions (note that groups can't be negated) + +## Qualifiers + +Here's a comprehensive table of all supported qualifiers: + +| Qualifier | Description | Example Usage | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------- | +| `is:fav` | Favorited bookmarks | `is:fav` | +| `is:archived` | Archived bookmarks | `-is:archived` | +| `is:tagged` | Bookmarks that has one or more tags | `is:tagged` | +| `is:inlist` | Bookmarks that are in one or more lists | `is:inlist` | +| `is:link`, `is:text`, `is:media` | Bookmarks that are of type link, text or media | `is:link` | +| `is:broken` | Bookmarks with broken/failed links (crawl failures or non-2xx status codes) | `is:broken` | +| `url:` | Match bookmarks with URL substring | `url:example.com` | +| `title:` | Match bookmarks with title substring | `title:example` | +| | Supports quoted strings for titles with spaces | `title:"my title"` | +| `#` | Match bookmarks with specific tag | `#important` | +| | Supports quoted strings for tags with spaces | `#"work in progress"` | +| `list:` | Match bookmarks in specific list | `list:reading` | +| | Supports quoted strings for list names with spaces | `list:"to review"` | +| `after:` | Bookmarks created on or after date (YYYY-MM-DD) | `after:2023-01-01` | +| `before:` | Bookmarks created on or before date (YYYY-MM-DD) | `before:2023-12-31` | +| `feed:` | Bookmarks imported from a particular rss feed | `feed:Hackernews` | +| `age:` | Match bookmarks based on how long ago they were created. Use `<` or `>` to indicate the maximum / minimum age of the bookmarks. Supported units: `d` (days), `w` (weeks), `m` (months), `y` (years). | `age:<1d` `age:>2w` `age:<6m` `age:>3y` | + +### Examples + +```plaintext +# Find favorited bookmarks from 2023 that are tagged "important" +is:fav after:2023-01-01 before:2023-12-31 #important + +# Find archived bookmarks that are either in "reading" list or tagged "work" +is:archived and (list:reading or #work) + +# Find bookmarks that are not tagged or not in any list +-is:tagged or -is:inlist +# Find bookmarks with "React" in the title +title:React +``` + +## Combining Conditions + +You can combine multiple conditions using boolean logic: + +```plaintext +# Find favorited bookmarks from 2023 that are tagged "important" +is:fav after:2023-01-01 before:2023-12-31 #important + +# Find archived bookmarks that are either in "reading" list or tagged "work" +is:archived and (list:reading or #work) + +# Find bookmarks that are not favorited and not archived +-is:fav -is:archived +``` + +## Text Search + +Any text not part of a qualifier will be treated as a full-text search: + +```plaintext +# Search for "machine learning" in bookmark content +machine learning + +# Combine text search with qualifiers +machine learning is:fav +``` diff --git a/docs/docs/04-using-karakeep/_category_.json b/docs/docs/04-using-karakeep/_category_.json new file mode 100644 index 00000000..96a7071a --- /dev/null +++ b/docs/docs/04-using-karakeep/_category_.json @@ -0,0 +1,3 @@ +{ + "label": "Using Karakeep" +} diff --git a/docs/docs/05-integrations/01-openai.md b/docs/docs/05-integrations/01-openai.md new file mode 100644 index 00000000..32218da8 --- /dev/null +++ b/docs/docs/05-integrations/01-openai.md @@ -0,0 +1,11 @@ +# OpenAI Costs + +This service uses OpenAI for automatic tagging. This means that you'll incur some costs if automatic tagging is enabled. There are two type of inferences that we do: + +## Text Tagging + +For text tagging, we use the `gpt-4.1-mini` model. This model is [extremely cheap](https://openai.com/api/pricing). Cost per inference varies depending on the content size per article. Though, roughly, You'll be able to generate tags for almost 3000+ bookmarks for less than $1. + +## Image Tagging + +For image uploads, we use the `gpt-4o-mini` model for extracting tags from the image. You can learn more about the costs of using this model [here](https://platform.openai.com/docs/guides/images?api-mode=chat#calculating-costs). To lower the costs, we're using the low resolution mode (fixed number of tokens regardless of image size). You'll be able to run inference for 1000+ images for less than a $1. diff --git a/docs/docs/05-integrations/02-command-line.md b/docs/docs/05-integrations/02-command-line.md new file mode 100644 index 00000000..c8b00696 --- /dev/null +++ b/docs/docs/05-integrations/02-command-line.md @@ -0,0 +1,114 @@ +# Command Line Tool (CLI) + +Karakeep comes with a simple CLI for those users who want to do more advanced manipulation. + +## Features + +- Manipulate bookmarks, lists and tags +- Mass import/export of bookmarks + +## Installation (NPM) + +``` +npm install -g @karakeep/cli +``` + + +## Installation (Docker) + +``` +docker run --rm ghcr.io/karakeep-app/karakeep-cli:release --help +``` + +## Usage + +``` +karakeep +``` + +``` +Usage: karakeep [options] [command] + +A CLI interface to interact with the karakeep api + +Options: + --api-key the API key to interact with the API (env: KARAKEEP_API_KEY) + --server-addr the address of the server to connect to (env: KARAKEEP_SERVER_ADDR) + -V, --version output the version number + -h, --help display help for command + +Commands: + bookmarks manipulating bookmarks + lists manipulating lists + tags manipulating tags + whoami returns info about the owner of this API key + help [command] display help for command +``` + +And some of the subcommands: + +``` +karakeep bookmarks +``` + +``` +Usage: karakeep bookmarks [options] [command] + +Manipulating bookmarks + +Options: + -h, --help display help for command + +Commands: + add [options] creates a new bookmark + get fetch information about a bookmark + update [options] updates bookmark + list [options] list all bookmarks + delete delete a bookmark + help [command] display help for command + +``` + +``` +karakeep lists +``` + +``` +Usage: karakeep lists [options] [command] + +Manipulating lists + +Options: + -h, --help display help for command + +Commands: + list lists all lists + delete deletes a list + add-bookmark [options] add a bookmark to list + remove-bookmark [options] remove a bookmark from list + help [command] display help for command +``` + +## Obtaining an API Key + +To use the CLI, you'll need to get an API key from your karakeep settings. You can validate that it's working by running: + +``` +karakeep --api-key --server-addr whoami +``` + +For example: + +``` +karakeep --api-key mysupersecretkey --server-addr https://try.karakeep.app whoami +{ + id: 'j29gnbzxxd01q74j2lu88tnb', + name: 'Test User', + email: 'test@gmail.com' +} +``` + + +## Other clients + +There also exists a **non-official**, community-maintained, python package called [karakeep-python-api](https://github.com/thiswillbeyourgithub/karakeep_python_api) that can be accessed from the CLI, but is **not** official. diff --git a/docs/docs/05-integrations/03-mcp.md b/docs/docs/05-integrations/03-mcp.md new file mode 100644 index 00000000..514332de --- /dev/null +++ b/docs/docs/05-integrations/03-mcp.md @@ -0,0 +1,65 @@ +# Model Context Protocol Server (MCP) + +Karakeep comes with a Model Context Protocol server that can be used to interact with it through LLMs. + +## Supported Tools + +- Searching bookmarks +- Adding and removing bookmarks from lists +- Attaching and detaching tags to bookmarks +- Creating new lists +- Creating text and URL bookmarks + + +## Usage with Claude Desktop + +From NPM: + +```json +{ + "mcpServers": { + "karakeep": { + "command": "npx", + "args": [ + "@karakeep/mcp" + ], + "env": { + "KARAKEEP_API_ADDR": "https://", + "KARAKEEP_API_KEY": "" + } + } + } +} +``` + +From Docker: + +```json +{ + "mcpServers": { + "karakeep": { + "command": "docker", + "args": [ + "run", + "-e", + "KARAKEEP_API_ADDR=https://", + "-e", + "KARAKEEP_API_KEY=", + "ghcr.io/karakeep-app/karakeep-mcp:latest" + ] + } + } +} +``` + + +### Demo + +#### Search +![mcp-1](/img/mcp-1.gif) + +#### Adding Text Bookmarks +![mcp-2](/img/mcp-2.gif) + +#### Adding URL Bookmarks +![mcp-2](/img/mcp-3.gif) diff --git a/docs/docs/05-integrations/04-different-ai-providers.md b/docs/docs/05-integrations/04-different-ai-providers.md new file mode 100644 index 00000000..9a86e04f --- /dev/null +++ b/docs/docs/05-integrations/04-different-ai-providers.md @@ -0,0 +1,88 @@ +# Configuring different AI Providers + +Karakeep uses LLM providers for AI tagging and summarization. We support OpenAI-compatible providers and ollama. This guide will show you how to configure different providers. + +## OpenAI + +If you want to use OpenAI itself, you just need to pass in the OPENAI_API_KEY environment variable. + +``` +OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + +# You can change the default models by uncommenting the following lines, and choosing your model. +# INFERENCE_TEXT_MODEL=gpt-4.1-mini +# INFERENCE_IMAGE_MODEL=gpt-4o-mini +``` + +## Ollama + +Ollama is a local LLM provider that you can use to run your own LLM server. You'll need to pass ollama's address to karakeep and you need to ensure that it's accessible from within the karakeep container (e.g. no localhost addresses). + +``` +# MAKE SURE YOU DON'T HAVE OPENAI_API_KEY set, otherwise it takes precedence. + +OLLAMA_BASE_URL=http://ollama.mylab.com:11434 + +# Make sure to pull the models in ollama first. Example models: +INFERENCE_TEXT_MODEL=gemma3 +INFERENCE_IMAGE_MODEL=llava + +# If the model you're using doesn't support structured output, you also need: +# INFERENCE_OUTPUT_SCHEMA=plain +``` + +## Gemini + +Gemini has an OpenAI-compatible API. You need to get an api key from Google AI Studio. + +``` + +OPENAI_BASE_URL=https://generativelanguage.googleapis.com/v1beta +OPENAI_API_KEY=YOUR_API_KEY + +# Example models: +INFERENCE_TEXT_MODEL=gemini-2.0-flash +INFERENCE_IMAGE_MODEL=gemini-2.0-flash +``` + +## OpenRouter + +``` +OPENAI_BASE_URL=https://openrouter.ai/api/v1 +OPENAI_API_KEY=YOUR_API_KEY + +# Example models: +INFERENCE_TEXT_MODEL=meta-llama/llama-4-scout +INFERENCE_IMAGE_MODEL=meta-llama/llama-4-scout +``` + +## Perplexity + +``` +OPENAI_BASE_URL: https://api.perplexity.ai +OPENAI_API_KEY: Your Perplexity API Key +INFERENCE_TEXT_MODEL: sonar-pro +INFERENCE_IMAGE_MODEL: sonar-pro +``` + +## Azure + +Azure has an OpenAI-compatible API. + +You can get your API key from the Overview page of the Azure AI Foundry Portal or via "Keys + Endpoints" on the resource in the Azure Portal. + +:::warning +The [model name is the deployment name](https://learn.microsoft.com/en-us/azure/ai-foundry/openai/how-to/switching-endpoints#keyword-argument-for-model) you specified when deploying the model, which may differ from the base model name. +::: + +``` +# Deployed via Azure AI Foundry: +OPENAI_BASE_URL=https://{your-azure-ai-foundry-resource-name}.cognitiveservices.azure.com/openai/v1/ + +# Deployed via Azure OpenAI Service: +OPENAI_BASE_URL=https://{your-azure-openai-resource-name}.openai.azure.com/openai/v1/ + +OPENAI_API_KEY=YOUR_API_KEY +INFERENCE_TEXT_MODEL=YOUR_DEPLOYMENT_NAME +INFERENCE_IMAGE_MODEL=YOUR_DEPLOYMENT_NAME +``` diff --git a/docs/docs/05-integrations/05-singlefile.md b/docs/docs/05-integrations/05-singlefile.md new file mode 100644 index 00000000..c0f4e174 --- /dev/null +++ b/docs/docs/05-integrations/05-singlefile.md @@ -0,0 +1,46 @@ +# Using Karakeep with SingleFile Extension + +Karakeep supports being a destination for the [SingleFile extension](https://github.com/gildas-lormeau/SingleFile). This has the benefit of allowing you to use the singlefile extension to hoard links as you're seeing them in the browser. This is perfect for websites that don't like to get crawled, has annoying cookie banner or require authentication. + +## Setup + +1. Install the [SingleFile extension](https://github.com/gildas-lormeau/SingleFile). +2. In the extension settings, select `Destinations`. +3. Select `upload to a REST Form API`. +4. In the URL, insert the address: `https://YOUR_SERVER_ADDRESS/api/v1/bookmarks/singlefile`. +5. In the `authorization token` field, paste an API key that you can get from your karakeep settings. +6. Set `data field name` to `file`. +7. Set `URL field name` to `url`. +8. (Optional) Add `&ifexists=MODE` to the URL where MODE is one of `skip`, `overwrite`, `overwrite-recrawl`, `append`, or `append-recrawl`. See "Handling Existing Bookmarks" section below for details. + +Now, go to any page and click the singlefile extension icon. Once it's done with the upload, the bookmark should show up in your karakeep instance. Note that the singlefile extension doesn't show any progress on the upload. Given that archives are typically large, it might take 30+ seconds until the upload is done and starts showing up in Karakeep. + +## Handling Existing Bookmarks + +When uploading a page that already exists in your archive (same URL), you can control the behavior by setting the `ifexists` query parameter in the upload URL. The available modes are: + +- `skip` (default): If the bookmark already exists, skip creating a new one +- `overwrite`: Replace existing precrawled archive (only the most recent archive is kept) +- `overwrite-recrawl`: Replace existing archive and queue a recrawl to update content +- `append`: Add new archive version alongside existing ones +- `append-recrawl`: Add new archive and queue a recrawl + +To use these modes, append `?ifexists=MODE` to your upload URL, replacing `MODE` with your desired behavior. + +For example: +`https://YOUR_SERVER_ADDRESS/api/v1/bookmarks/singlefile?ifexists=overwrite` + + +## Recommended settings + +In the singlefile extension, you probably will want to change the following settings for better experience: +* Stylesheets > compress CSS content: on +* Stylesheets > group duplicate stylesheets together: on +* HTML content > remove frames: on + +Also, you most likely will want to change the default `MAX_ASSET_SIZE_MB` in karakeep to something higher, for example `100`. + +:::info +Currently, we don't support screenshots for singlefile uploads, but this will change in the future. +::: + diff --git a/docs/docs/05-integrations/_category_.json b/docs/docs/05-integrations/_category_.json new file mode 100644 index 00000000..e37aa473 --- /dev/null +++ b/docs/docs/05-integrations/_category_.json @@ -0,0 +1,3 @@ +{ + "label": "Integrations" +} diff --git a/docs/docs/05-quick-sharing.md b/docs/docs/05-quick-sharing.md deleted file mode 100644 index 254bec84..00000000 --- a/docs/docs/05-quick-sharing.md +++ /dev/null @@ -1,21 +0,0 @@ -# Quick Sharing Extensions - -The whole point of Karakeep is making it easy to hoard the content. That's why there are a couple of - -## Mobile Apps - -mobile screenshot - - -- **iOS app**: [App Store Link](https://apps.apple.com/us/app/karakeep-app/id6479258022). -- **Android App**: [Play Store link](https://play.google.com/store/apps/details?id=app.hoarder.hoardermobile&pcampaignid=web_share). - -## Browser Extensions - -mobile screenshot - -- **Chrome extension**: [here](https://chromewebstore.google.com/detail/karakeep/kgcjekpmcjjogibpjebkhaanilehneje). -- **Firefox addon**: [here](https://addons.mozilla.org/en-US/firefox/addon/karakeep/). - -- ## Community Extensions -- **Safari extension**: [App Store Link](https://apps.apple.com/us/app/karakeeper-bookmarker/id6746722790). For macOS and iOS to allow a simple way to add your bookmarks to your self hosted karakeep instance. diff --git a/docs/docs/06-administration/01-security-considerations.md b/docs/docs/06-administration/01-security-considerations.md new file mode 100644 index 00000000..5a295526 --- /dev/null +++ b/docs/docs/06-administration/01-security-considerations.md @@ -0,0 +1,14 @@ +# Security Considerations + +If you're going to give app access to untrusted users, there's some security considerations that you'll need to be aware of given how the crawler works. The crawler is basically running a browser to fetch the content of the bookmarks. Any untrusted user can submit bookmarks to be crawled from your server and they'll be able to see the crawling result. This can be abused in multiple ways: + +1. Untrusted users can submit crawl requests to websites that you don't want to be coming out of your IPs. +2. Crawling user controlled websites can expose your origin IP (and location) even if your service is hosted behind cloudflare for example. +3. The crawling requests will be coming out from your own network, which untrusted users can leverage to crawl internal non-internet exposed endpoints. + +To mitigate those risks, you can do one of the following: + +1. Limit access to trusted users +2. Let the browser traffic go through some VPN with restricted network policies. +3. Host the browser container outside of your network. +4. Use a hosted browser as a service (e.g. [browserless](https://browserless.io)). Note: I've never used them before. diff --git a/docs/docs/06-administration/02-FAQ.md b/docs/docs/06-administration/02-FAQ.md new file mode 100644 index 00000000..e6f59801 --- /dev/null +++ b/docs/docs/06-administration/02-FAQ.md @@ -0,0 +1,60 @@ +# Frequently Asked Questions (FAQ) + +## User Management + +### Lost password + +#### If you are not an administrator + +Administrators can reset the password of any user. Contact an administrator to reset the password for you. + +- Navigate to the `Admin Settings` page +- Find the user in the `Users List` +- In the `Actions` column, there is a button to reset the password +- Enter a new password and press `Reset` +- The new password is now set +- If required, you can change your password again (so the admin does not know your password) in the `User Settings` + +#### If you are an administrator + +If you are an administrator and lost your password, you have to reset the password in the database. + +To reset the password: + +- Acquire some kind of tools that helps you to connect to the database: + - `sqlite3` on Linux: run `apt-get install sqlite3` (depending on your package manager) + - e.g. `dbeaver` on Windows +- Shut down Karakeep +- Connect to the `db.db` database, which is located in the `data` directory you have mounted to your docker container: + - by e.g. running `sqlite3 db.db` (in your `data` directory) + - or going through e.g. the `dbeaver` UI to locate the file in the data directory and connecting to it +- Update the password in the database by running: + - `update user set password='$2a$10$5u40XUq/cD/TmLdCOyZ82ePENE6hpkbodJhsp7.e/BgZssUO5DDTa', salt='' where email='';` + - (don't forget to put your email address into the command) +- The new password for your user is now `adminadmin`. +- Start Karakeep again +- Log in with your email address and the password `adminadmin` and change the password to whatever you want in the `User Settings` + +### Adding another administrator + +By default, the first user to sign up gets promoted to administrator automatically. + +In case you want to grant those permissions to another user: + +- Navigate to the `Admin Settings` page +- Find the user in the `Users List` +- In the `Actions` column, there is a button to change the Role +- Change the Role to `Admin` +- Press `Change` +- The new administrator has to log out and log in again to get the new role assigned + +### Adding new users, when signups are disabled + +Administrators can create new accounts any time: + +- Navigate to the `Admin Settings` page +- Go to the `Users List` +- Press the `Create User` Button. +- Enter the information for the user +- Press `create` +- The new user can now log in diff --git a/docs/docs/06-administration/03-troubleshooting.md b/docs/docs/06-administration/03-troubleshooting.md new file mode 100644 index 00000000..4072442b --- /dev/null +++ b/docs/docs/06-administration/03-troubleshooting.md @@ -0,0 +1,46 @@ +# Troubleshooting + +## SqliteError: no such table: user + +This usually means that there's something wrong with the database setup (more concretely, it means that the database is not initialized). This can be caused by multiple problems: +1. **Wiped DATA_DIR:** Your `DATA_DIR` got wiped (or the backing storage dir changed). If you did this intentionally, restart the container so that it can re-initalize the database. +2. **Missing DATA_DIR**: You're not using the default docker compose file, and you forgot to configure the `DATA_DIR` env var. This will result into the database getting set up in a different directory than the one used by the service. + +## Chrome Failed to Read DnsConfig + +If you see this error in the logs of the chrome container, it's a benign error and you can safely ignore it. Whatever problems you're having, is unrelated to this error. + +## AI Tagging not working (when using OpenAI) + +Check the logs of the container and this will usually tell you what's wrong. Common problems are: +1. Typo in the env variable `OPENAI_API_KEY` name resulting into logs saying something like "skipping inference as it's not configured". +2. You forgot to call `docker compose up` after configuring open ai. +3. OpenAI requires pre-charging the account with credits before using it, otherwise you'll get an error like "insufficient funds". + +## AI Tagging not working (when using Ollama) + +Check the logs of the container and this will usually tell you what's wrong. Common problems are: +1. Typo in the env variable `OLLAMA_BASE_URL` name resulting into logs saying something like "skipping inference as it's not configured". +2. You forgot to call `docker compose up` after configuring ollama. +3. You didn't change the `INFERENCE_TEXT_MODEL` env variable, resulting into karakeep attempting to use gpt models with ollama which won't work. +4. Ollama server is not reachable by the karakeep container. This can be caused by: + 1. Ollama server being in a different docker network than the karakeep container. + 2. You're using `localhost` as the `OLLAMA_BASE_URL` instead of the actual address of the ollama server. `localhost` points to the container itself, not the docker host. Check this [stackoverflow answer](https://stackoverflow.com/questions/24319662/from-inside-of-a-docker-container-how-do-i-connect-to-the-localhost-of-the-mach) to find how to correctly point to the docker host address instead. + +## Crawling not working + +Check the logs of the container and this will usually tell you what's wrong. Common problems are: +1. You changed the name of the chrome container but didn't change the `BROWSER_WEB_URL` env variable. + +## Upgrading Meilisearch - Migrating the Meilisearch db version + +[Meilisearch](https://www.meilisearch.com/) is the database used by karakeep for searching in your bookmarks. The version used by karakeep is `1.13.3` and it is advised not to upgrade it without good reasons. If you do, you might see errors like `Your database version (1.11.1) is incompatible with your current engine version (1.13.3). To migrate data between Meilisearch versions, please follow our guide on https://www.meilisearch.com/docs/learn/update_and_migration/updating.`. + +Luckily we can easily workaround this: +1. Stop the Meilisearch container. +2. Inside the Meilisearch volume bound to `/meili_data`, erase/rename the folder called `data.ms`. +3. Launch Meilisearch again. +4. Login to karakeep as administrator and go to (as of v0.24.1) `Admin Settings > Background Jobs` then click on `Reindex All Bookmarks`. +5. When the reindexing has finished, Meilisearch should be working as usual. + +If you run into issues, the official documentation can be found [there](https://www.meilisearch.com/docs/learn/update_and_migration/updating). diff --git a/docs/docs/06-administration/04-server-migration.md b/docs/docs/06-administration/04-server-migration.md new file mode 100644 index 00000000..147ae1ec --- /dev/null +++ b/docs/docs/06-administration/04-server-migration.md @@ -0,0 +1,71 @@ +# Migrating Between Servers + +This guide explains how to migrate all of your data from one Karakeep server to another using the official CLI. + +## What the command does + +The migration copies user-owned data from a source server to a destination server in this order: + +- User settings +- Lists (preserving hierarchy and settings) +- RSS feeds +- AI prompts (custom prompts and their enabled state) +- Webhooks (URL and events) +- Tags (ensures tags by name exist) +- Rule engine rules (IDs remapped to destination equivalents) +- Bookmarks (links, text, and assets) + - After creation, attaches the correct tags and adds to the correct lists + +Notes: +- Webhook tokens cannot be read via the API, so tokens are not migrated. Re‑add them on the destination if needed. +- Asset bookmarks are migrated by downloading the original asset and re‑uploading it to the destination. Only images and PDFs are supported for asset bookmarks. +- Link bookmarks on the destination may be de‑duplicated if the same URL already exists. + +## Prerequisites + +- Install the CLI: + - NPM: `npm install -g @karakeep/cli` + - Docker: `docker run --rm ghcr.io/karakeep-app/karakeep-cli:release --help` +- Collect API keys and base URLs for both servers: + - Source: `--server-addr`, `--api-key` + - Destination: `--dest-server`, `--dest-api-key` + +## Quick start + +``` +karakeep --server-addr https://src.example.com --api-key migrate \ + --dest-server https://dest.example.com \ + --dest-api-key +``` + +The command is long‑running and shows live progress for each phase. You will be prompted for confirmation; pass `--yes` to skip the prompt. + +### Options + +- `--server-addr `: Source server base URL +- `--api-key `: API key for the source server +- `--dest-server `: Destination server base URL +- `--dest-api-key `: API key for the destination server +- `--batch-size `: Page size for bookmark migration (default 50, max 100) +- `-y`, `--yes`: Skip the confirmation prompt + +## What to expect + +- Lists are recreated parent‑first and retain their hierarchy. +- Feeds, prompts, webhooks, and tags are recreated by value. +- Rules are recreated after IDs (tags, lists, feeds) are remapped to their corresponding destination IDs. +- After each bookmark is created, the command attaches the correct tags and adds it to the correct lists. + +## Caveats and tips + +- Webhook auth tokens must be re‑entered on the destination after migration. +- If your destination already contains data, duplicate links may be de‑duplicated; tags and list membership are still applied to the existing bookmark. + +## Troubleshooting + +- If the command exits early, you can re‑run it, but note: + - Tags and lists that already exist are reused. + - Link de‑duplication avoids duplicate link bookmarks. Notes and assets will get re-created. + - Rules, webhooks, rss feeds will get re-created and you'll have to manually clean them up afterwards. + - The progress log indicates how far it got. +- Use a smaller `--batch-size` if your source or destination is under heavy load. diff --git a/docs/docs/06-administration/05-legacy-container-upgrade.md b/docs/docs/06-administration/05-legacy-container-upgrade.md new file mode 100644 index 00000000..d95c1c1e --- /dev/null +++ b/docs/docs/06-administration/05-legacy-container-upgrade.md @@ -0,0 +1,66 @@ +# Legacy Container Upgrade + +Karakeep's 0.16 release consolidated the web and worker containers into a single container and also dropped the need for the redis container. The legacy containers will stop being supported soon, to upgrade to the new container do the following: + +1. Remove the redis container and its volume if it had one. +2. Move the environment variables that you've set exclusively to the `workers` container to the `web` container. +3. Delete the `workers` container. +4. Rename the web container image from `hoarder-app/hoarder-web` to `hoarder-app/hoarder`. + +```diff +diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml +index cdfc908..6297563 100644 +--- a/docker/docker-compose.yml ++++ b/docker/docker-compose.yml +@@ -1,7 +1,7 @@ + version: "3.8" + services: + web: +- image: ghcr.io/hoarder-app/hoarder-web:${KARAKEEP_VERSION:-release} ++ image: ghcr.io/karakeep-app/karakeep:${KARAKEEP_VERSION:-release} + restart: unless-stopped + volumes: + - data:/data +@@ -10,14 +10,10 @@ services: + env_file: + - .env + environment: +- REDIS_HOST: redis + MEILI_ADDR: http://meilisearch:7700 ++ BROWSER_WEB_URL: http://chrome:9222 ++ # OPENAI_API_KEY: ... + DATA_DIR: /data +- redis: +- image: redis:7.2-alpine +- restart: unless-stopped +- volumes: +- - redis:/data + chrome: + image: gcr.io/zenika-hub/alpine-chrome:123 + restart: unless-stopped +@@ -37,24 +33,7 @@ services: + MEILI_NO_ANALYTICS: "true" + volumes: + - meilisearch:/meili_data +- workers: +- image: ghcr.io/hoarder-app/hoarder-workers:${KARAKEEP_VERSION:-release} +- restart: unless-stopped +- volumes: +- - data:/data +- env_file: +- - .env +- environment: +- REDIS_HOST: redis +- MEILI_ADDR: http://meilisearch:7700 +- BROWSER_WEB_URL: http://chrome:9222 +- DATA_DIR: /data +- # OPENAI_API_KEY: ... +- depends_on: +- web: +- condition: service_started + + volumes: +- redis: + meilisearch: + data: +``` diff --git a/docs/docs/06-administration/06-hoarder-to-karakeep-migration.md b/docs/docs/06-administration/06-hoarder-to-karakeep-migration.md new file mode 100644 index 00000000..4e309408 --- /dev/null +++ b/docs/docs/06-administration/06-hoarder-to-karakeep-migration.md @@ -0,0 +1,28 @@ +# Hoarder to Karakeep Migration + +Hoarder is rebranding to Karakeep. Due to github limitations, the old docker image might not be getting new updates after the rebranding. You might need to update your docker image to point to the new karakeep image instead by applying the following change in the docker compose file. + +```diff +diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml +index cdfc908..6297563 100644 +--- a/docker/docker-compose.yml ++++ b/docker/docker-compose.yml +@@ -1,7 +1,7 @@ + version: "3.8" + services: + web: +- image: ghcr.io/hoarder-app/hoarder:${HOARDER_VERSION:-release} ++ image: ghcr.io/karakeep-app/karakeep:${HOARDER_VERSION:-release} +``` + +You can also change the `HOARDER_VERSION` environment variable but if you do so remember to change it in the `.env` file as well. + +## Migrating a Baremetal Installation + +If you previously used the [Debian/Ubuntu install script](../installation/debuntu) to install Hoarder, there is an option to migrate your installation to Karakeep. + +```bash +bash karakeep-linux.sh migrate +``` + +This will migrate your installation with no user input required. After the migration, the script will also check for an update. diff --git a/docs/docs/06-administration/_category_.json b/docs/docs/06-administration/_category_.json new file mode 100644 index 00000000..5b581902 --- /dev/null +++ b/docs/docs/06-administration/_category_.json @@ -0,0 +1,3 @@ +{ + "label": "Administration" +} diff --git a/docs/docs/06-openai.md b/docs/docs/06-openai.md deleted file mode 100644 index 32218da8..00000000 --- a/docs/docs/06-openai.md +++ /dev/null @@ -1,11 +0,0 @@ -# OpenAI Costs - -This service uses OpenAI for automatic tagging. This means that you'll incur some costs if automatic tagging is enabled. There are two type of inferences that we do: - -## Text Tagging - -For text tagging, we use the `gpt-4.1-mini` model. This model is [extremely cheap](https://openai.com/api/pricing). Cost per inference varies depending on the content size per article. Though, roughly, You'll be able to generate tags for almost 3000+ bookmarks for less than $1. - -## Image Tagging - -For image uploads, we use the `gpt-4o-mini` model for extracting tags from the image. You can learn more about the costs of using this model [here](https://platform.openai.com/docs/guides/images?api-mode=chat#calculating-costs). To lower the costs, we're using the low resolution mode (fixed number of tokens regardless of image size). You'll be able to run inference for 1000+ images for less than a $1. diff --git a/docs/docs/07-community/01-community-projects.md b/docs/docs/07-community/01-community-projects.md new file mode 100644 index 00000000..828d545f --- /dev/null +++ b/docs/docs/07-community/01-community-projects.md @@ -0,0 +1,87 @@ +# Community Projects + +This page lists community projects that are built around Karakeep, but not officially supported by the development team. + +:::warning +This list comes with no guarantees about security, performance, reliability, or accuracy. Use at your own risk. +::: + +### Raycast Extension + +_By [@luolei](https://github.com/foru17)._ + +A user-friendly Raycast extension that seamlessly integrates with Karakeep, bringing powerful bookmark management to your fingertips. Quickly save, search, and organize your bookmarks, texts, and images—all through Raycast's intuitive interface. + +Get it [here](https://www.raycast.com/luolei/karakeep). + +### Alfred Workflow + +_By [@yinan-c](https://github.com/yinan-c)_ + +An Alfred workflow to quickly hoard stuff or access your hoarded bookmarks! + +Get it [here](https://www.alfredforum.com/topic/22528-hoarder-workflow-for-self-hosted-bookmark-management/). + +### Obsidian Plugin + +_By [@jhofker](https://github.com/jhofker)_ + +An Obsidian plugin that syncs your Karakeep bookmarks with Obsidian, creating markdown notes for each bookmark in a designated folder. + +Get it [here](https://github.com/jhofker/obsidian-hoarder/), or install it directly from Obsidian's community plugin store ([link](https://obsidian.md/plugins?id=hoarder-sync)). + +### Telegram Bot + +_By [@Madh93](https://github.com/Madh93)_ + +A Telegram Bot for saving bookmarks to Karakeep directly through Telegram. + +Get it [here](https://github.com/Madh93/karakeepbot). + +### Hoarder's Pipette + +_By [@DanSnow](https://github.com/DanSnow)_ + +A chrome extension that injects karakeep's bookmarks into your search results. + +Get it [here](https://dansnow.github.io/hoarder-pipette/guides/installation/). + +### Karakeep-Python-API + +_By [@thiswillbeyourgithub](https://github.com/thiswillbeyourgithub/)_ + +A python package to simplify access to the karakeep API. Can be used as a library or from the CLI. Aims for feature completeness and high test coverage but do check its feature matrix before relying too much on it. + +Its repository also hosts the [Community Script](https://github.com/thiswillbeyourgithub/karakeep_python_api/tree/main/community_scripts), for example: + +| Community Script | Description | Documentation | +|----------------|-------------|---------------| +| **Karakeep-Time-Tagger** | Automatically adds time-to-read tags (`0-5m`, `5-10m`, etc.) to bookmarks based on content length analysis. Includes systemd service and timer files for automated periodic execution. | [`Link`](https://github.com/thiswillbeyourgithub/karakeep_python_api/tree/main/community_scripts/karakeep-time-tagger) | +| **Karakeep-List-To-Tag** | Converts a Karakeep list into tags by adding a specified tag to all bookmarks within that list. | [`Link`](https://github.com/thiswillbeyourgithub/karakeep_python_api/tree/main/community_scripts/karakeep-list-to-tag) | +| **Omnivore2Karakeep-Highlights** | Imports highlights from Omnivore export data to Karakeep, with intelligent position detection and bookmark matching. Supports dry-run mode for testing. | [`Link`](https://github.com/thiswillbeyourgithub/karakeep_python_api/tree/main/community_scripts/omnivore2karakeep-highlights) | + + +Get it [here](https://github.com/thiswillbeyourgithub/karakeep_python_api). + +### FreshRSS_to_Karakeep + +_By [@thiswillbeyourgithub](https://github.com/thiswillbeyourgithub/)_ + +A python script to automatically create Karakeep bookmarks from your [FreshRSS](https://github.com/FreshRSS/FreshRSS) *favourites/saved* RSS item. Made to be called periodically. Based on the community project `Karakeep-Python-API` above, by the same author. + +Get it [here](https://github.com/thiswillbeyourgithub/freshrss_to_karakeep). + +### karakeep-sync +_By [@sidoshi](https://github.com/sidoshi/)_ + +Sync links from Hacker News upvotes, Reddit Saves to Karakeep for centralized bookmark management. + +Get it [here](https://github.com/sidoshi/karakeep-sync) + +### Home Assistant Integration + +_By [@sli-cka](https://github.com/sli-cka)_ + +A custom integration that brings Karakeep data into Home Assistant. It exposes your Karakeep statistics data (like lists, bookmarks, tag, etc.) as Home Assistant entities, enabling dashboards, automations, and notifications based on your Karakeep data. + +Get it [here](https://github.com/sli-cka/karakeep-homeassistant) diff --git a/docs/docs/07-community/_category_.json b/docs/docs/07-community/_category_.json new file mode 100644 index 00000000..b9240603 --- /dev/null +++ b/docs/docs/07-community/_category_.json @@ -0,0 +1,3 @@ +{ + "label": "Community" +} diff --git a/docs/docs/07-development/01-setup.md b/docs/docs/07-development/01-setup.md deleted file mode 100644 index 1c98a675..00000000 --- a/docs/docs/07-development/01-setup.md +++ /dev/null @@ -1,178 +0,0 @@ -# Setup - -## Quick Start - -For the fastest way to get started with development, use the one-command setup script: - -```bash -./start-dev.sh -``` - -This script will automatically: -- Start Meilisearch in Docker (on port 7700) -- Start headless Chrome in Docker (on port 9222) -- Install dependencies with `pnpm install` if needed -- Start both the web app and workers in parallel -- Provide cleanup when you stop with Ctrl+C - -**Prerequisites:** -- Docker installed and running -- pnpm installed (see manual setup below for installation instructions) - -The script will output the running services: -- Web app: http://localhost:3000 -- Meilisearch: http://localhost:7700 -- Chrome debugger: http://localhost:9222 - -Press Ctrl+C to stop all services and clean up Docker containers. - -## Manual Setup - -Karakeep uses `node` version 24. To install it, you can use `nvm` [^1] - -``` -$ nvm install 24 -``` - -Verify node version using this command: -``` -$ node --version -v24.14.0 -``` - -Karakeep also makes use of `corepack`[^2]. If you have `node` installed, then `corepack` should already be -installed on your machine, and you don't need to do anything. To verify the `corepack` is installed run: - -``` -$ command -v corepack -/home//.nvm/versions/node/v24.14.0/bin/corepack -``` - -To enable `corepack` run the following command: - -``` -$ corepack enable -``` - -Then, from the root of the repository, install the packages and dependencies using: - -``` -$ pnpm install -``` - -Output of a successful `pnpm install` run should look something like: - -``` -Scope: all 20 workspace projects -Lockfile is up to date, resolution step is skipped -Packages: +3129 -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -Progress: resolved 0, reused 2699, downloaded 0, added 3129, done - -devDependencies: -+ @karakeep/prettier-config 0.1.0 <- tooling/prettier - -. prepare$ husky -└─ Done in 45ms -Done in 5.5s -``` - -You can now continue with the rest of this documentation. - -### First Setup - -- You'll need to prepare the environment variables for the dev env. -- Easiest would be to set it up once in the root of the repo and then symlink it in each app directory (e.g. `/apps/web`, `/apps/workers`) and also `/packages/db`. -- Start by copying the template by `cp .env.sample .env`. -- The most important env variables to set are: - - `DATA_DIR`: Where the database and assets will be stored. This is the only required env variable. You can use an absolute path so that all apps point to the same dir. - - `NEXTAUTH_SECRET`: Random string used to sign the JWT tokens. Generate one with `openssl rand -base64 36`. Logging in will not work if this is missing! - - `MEILI_ADDR`: If not set, search will be disabled. You can set it to `http://127.0.0.1:7700` if you run meilisearch using the command below. - - `OPENAI_API_KEY`: If you want to enable auto tag inference in the dev env. -- run `pnpm run db:migrate` in the root of the repo to set up the database. - -### Dependencies - -#### Meilisearch - -Meilisearch is the provider for the full text search (and at some point embeddings search too). You can get it running with `docker run -p 7700:7700 getmeili/meilisearch:v1.13.3`. - -Mount persistent volume if you want to keep index data across restarts. You can trigger a re-index for the entire items collection in the admin panel in the web app. - -#### Chrome - -The worker app will automatically start headless chrome on startup for crawling pages. You don't need to do anything there. - -### Web App - -- Run `pnpm web` in the root of the repo. -- Go to `http://localhost:3000`. - -> NOTE: The web app kinda works without any dependencies. However, search won't work unless meilisearch is running. Also, new items added won't get crawled/indexed unless workers are running. - -### Workers - -- Run `pnpm workers` in the root of the repo. - -### Mobile App (iOS & Android) - -#### Prerequisites - -To build and run the mobile app locally, you'll need: - -- **For iOS development**: - - macOS computer - - Xcode installed from the App Store - - iOS Simulator (comes with Xcode) - -- **For Android development**: - - Android Studio installed - - Android SDK configured - - Android Emulator or physical device - -For detailed setup instructions, refer to the [Expo documentation](https://docs.expo.dev/guides/local-app-development/). - -#### Running the app - -- `cd apps/mobile` -- `pnpm exec expo prebuild --no-install` to build the app. - -**For iOS:** -- `pnpm exec expo run:ios` -- The app will be installed and started in the simulator. - -**Troubleshooting iOS Setup:** -If you encounter an error like `xcrun: error: SDK "iphoneos" cannot be located`, you may need to set the correct Xcode developer directory: -```bash -sudo xcode-select -s /Applications/Xcode.app/Contents/Developer -``` - -**For Android:** -- Start the Android emulator or connect a physical device. -- `pnpm exec expo run:android` -- The app will be installed and started on the emulator/device. - -Changing the code will hot reload the app. However, installing new packages requires restarting the expo server. - -### Browser Extension - -- `cd apps/browser-extension` -- `pnpm dev` -- This will generate a `dist` package -- Go to extension settings in chrome and enable developer mode. -- Press `Load unpacked` and point it to the `dist` directory. -- The plugin will pop up in the plugin list. - -In dev mode, opening and closing the plugin menu should reload the code. - - -## Docker Dev Env - -If the manual setup is too much hassle for you. You can use a docker based dev environment by running `docker compose -f docker/docker-compose.dev.yml up` in the root of the repo. This setup wasn't super reliable for me though. - - -[^1]: [nvm](https://github.com/nvm-sh/nvm) is a node version manager. You can install it following [these -instructions](https://github.com/nvm-sh/nvm?tab=readme-ov-file#installing-and-updating). - -[^2]: [corepack](https://nodejs.org/api/corepack.html) is an experimental tool to help with managing versions of your -package managers. diff --git a/docs/docs/07-development/02-directories.md b/docs/docs/07-development/02-directories.md deleted file mode 100644 index 712e86a1..00000000 --- a/docs/docs/07-development/02-directories.md +++ /dev/null @@ -1,28 +0,0 @@ -# Directory Structure - -## Apps - -| Directory | Description | -| ------------------------ | ------------------------------------------------------ | -| `apps/web` | The main web app | -| `apps/workers` | The background workers logic | -| `apps/mobile` | The react native based mobile app | -| `apps/browser-extension` | The browser extension | -| `apps/landing` | The landing page of [karakeep.app](https://karakeep.app) | - -## Shared Packages - -| Directory | Description | -| ----------------- | ---------------------------------------------------------------------------- | -| `packages/db` | The database schema and migrations | -| `packages/trpc` | Where most of the business logic lies built as TRPC routes | -| `packages/shared` | Some shared code between the different apps (e.g. loggers, configs, assetdb) | - -## Toolings - -| Directory | Description | -| -------------------- | ----------------------- | -| `tooling/typescript` | The shared tsconfigs | -| `tooling/eslint` | ESlint configs | -| `tooling/prettier` | Prettier configs | -| `tooling/tailwind` | Shared tailwind configs | diff --git a/docs/docs/07-development/03-database.md b/docs/docs/07-development/03-database.md deleted file mode 100644 index d7a15b62..00000000 --- a/docs/docs/07-development/03-database.md +++ /dev/null @@ -1,10 +0,0 @@ -# Database Migrations - -- The database schema lives in `packages/db/schema.ts`. -- Changing the schema, requires a migration. -- You can generate the migration by running `pnpm run db:generate --name description_of_schema_change` in the root dir. -- You can then apply the migration by running `pnpm run db:migrate`. - -## Drizzle Studio - -You can start the drizzle studio by running `pnpm run db:studio` in the root of the repo. diff --git a/docs/docs/07-development/04-architecture.md b/docs/docs/07-development/04-architecture.md deleted file mode 100644 index 5a864034..00000000 --- a/docs/docs/07-development/04-architecture.md +++ /dev/null @@ -1,9 +0,0 @@ -# Architecture - -![Architecture Diagram](/img/architecture/arch.png) - -- Webapp: NextJS based using sqlite for data storage. -- Workers: Consume the jobs from sqlite based job queue and executes them, there are three job types: - 1. Crawling: Fetches the content of links using a headless chrome browser running in the workers container. - 2. OpenAI: Uses OpenAI APIs to infer the tags of the content. - 3. Indexing: Indexes the content in meilisearch for faster retrieval during search. diff --git a/docs/docs/07-development/_category_.json b/docs/docs/07-development/_category_.json deleted file mode 100644 index 73dd67ec..00000000 --- a/docs/docs/07-development/_category_.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "label": "Development", -} diff --git a/docs/docs/08-development/01-setup.md b/docs/docs/08-development/01-setup.md new file mode 100644 index 00000000..1c98a675 --- /dev/null +++ b/docs/docs/08-development/01-setup.md @@ -0,0 +1,178 @@ +# Setup + +## Quick Start + +For the fastest way to get started with development, use the one-command setup script: + +```bash +./start-dev.sh +``` + +This script will automatically: +- Start Meilisearch in Docker (on port 7700) +- Start headless Chrome in Docker (on port 9222) +- Install dependencies with `pnpm install` if needed +- Start both the web app and workers in parallel +- Provide cleanup when you stop with Ctrl+C + +**Prerequisites:** +- Docker installed and running +- pnpm installed (see manual setup below for installation instructions) + +The script will output the running services: +- Web app: http://localhost:3000 +- Meilisearch: http://localhost:7700 +- Chrome debugger: http://localhost:9222 + +Press Ctrl+C to stop all services and clean up Docker containers. + +## Manual Setup + +Karakeep uses `node` version 24. To install it, you can use `nvm` [^1] + +``` +$ nvm install 24 +``` + +Verify node version using this command: +``` +$ node --version +v24.14.0 +``` + +Karakeep also makes use of `corepack`[^2]. If you have `node` installed, then `corepack` should already be +installed on your machine, and you don't need to do anything. To verify the `corepack` is installed run: + +``` +$ command -v corepack +/home//.nvm/versions/node/v24.14.0/bin/corepack +``` + +To enable `corepack` run the following command: + +``` +$ corepack enable +``` + +Then, from the root of the repository, install the packages and dependencies using: + +``` +$ pnpm install +``` + +Output of a successful `pnpm install` run should look something like: + +``` +Scope: all 20 workspace projects +Lockfile is up to date, resolution step is skipped +Packages: +3129 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +Progress: resolved 0, reused 2699, downloaded 0, added 3129, done + +devDependencies: ++ @karakeep/prettier-config 0.1.0 <- tooling/prettier + +. prepare$ husky +└─ Done in 45ms +Done in 5.5s +``` + +You can now continue with the rest of this documentation. + +### First Setup + +- You'll need to prepare the environment variables for the dev env. +- Easiest would be to set it up once in the root of the repo and then symlink it in each app directory (e.g. `/apps/web`, `/apps/workers`) and also `/packages/db`. +- Start by copying the template by `cp .env.sample .env`. +- The most important env variables to set are: + - `DATA_DIR`: Where the database and assets will be stored. This is the only required env variable. You can use an absolute path so that all apps point to the same dir. + - `NEXTAUTH_SECRET`: Random string used to sign the JWT tokens. Generate one with `openssl rand -base64 36`. Logging in will not work if this is missing! + - `MEILI_ADDR`: If not set, search will be disabled. You can set it to `http://127.0.0.1:7700` if you run meilisearch using the command below. + - `OPENAI_API_KEY`: If you want to enable auto tag inference in the dev env. +- run `pnpm run db:migrate` in the root of the repo to set up the database. + +### Dependencies + +#### Meilisearch + +Meilisearch is the provider for the full text search (and at some point embeddings search too). You can get it running with `docker run -p 7700:7700 getmeili/meilisearch:v1.13.3`. + +Mount persistent volume if you want to keep index data across restarts. You can trigger a re-index for the entire items collection in the admin panel in the web app. + +#### Chrome + +The worker app will automatically start headless chrome on startup for crawling pages. You don't need to do anything there. + +### Web App + +- Run `pnpm web` in the root of the repo. +- Go to `http://localhost:3000`. + +> NOTE: The web app kinda works without any dependencies. However, search won't work unless meilisearch is running. Also, new items added won't get crawled/indexed unless workers are running. + +### Workers + +- Run `pnpm workers` in the root of the repo. + +### Mobile App (iOS & Android) + +#### Prerequisites + +To build and run the mobile app locally, you'll need: + +- **For iOS development**: + - macOS computer + - Xcode installed from the App Store + - iOS Simulator (comes with Xcode) + +- **For Android development**: + - Android Studio installed + - Android SDK configured + - Android Emulator or physical device + +For detailed setup instructions, refer to the [Expo documentation](https://docs.expo.dev/guides/local-app-development/). + +#### Running the app + +- `cd apps/mobile` +- `pnpm exec expo prebuild --no-install` to build the app. + +**For iOS:** +- `pnpm exec expo run:ios` +- The app will be installed and started in the simulator. + +**Troubleshooting iOS Setup:** +If you encounter an error like `xcrun: error: SDK "iphoneos" cannot be located`, you may need to set the correct Xcode developer directory: +```bash +sudo xcode-select -s /Applications/Xcode.app/Contents/Developer +``` + +**For Android:** +- Start the Android emulator or connect a physical device. +- `pnpm exec expo run:android` +- The app will be installed and started on the emulator/device. + +Changing the code will hot reload the app. However, installing new packages requires restarting the expo server. + +### Browser Extension + +- `cd apps/browser-extension` +- `pnpm dev` +- This will generate a `dist` package +- Go to extension settings in chrome and enable developer mode. +- Press `Load unpacked` and point it to the `dist` directory. +- The plugin will pop up in the plugin list. + +In dev mode, opening and closing the plugin menu should reload the code. + + +## Docker Dev Env + +If the manual setup is too much hassle for you. You can use a docker based dev environment by running `docker compose -f docker/docker-compose.dev.yml up` in the root of the repo. This setup wasn't super reliable for me though. + + +[^1]: [nvm](https://github.com/nvm-sh/nvm) is a node version manager. You can install it following [these +instructions](https://github.com/nvm-sh/nvm?tab=readme-ov-file#installing-and-updating). + +[^2]: [corepack](https://nodejs.org/api/corepack.html) is an experimental tool to help with managing versions of your +package managers. diff --git a/docs/docs/08-development/02-directories.md b/docs/docs/08-development/02-directories.md new file mode 100644 index 00000000..712e86a1 --- /dev/null +++ b/docs/docs/08-development/02-directories.md @@ -0,0 +1,28 @@ +# Directory Structure + +## Apps + +| Directory | Description | +| ------------------------ | ------------------------------------------------------ | +| `apps/web` | The main web app | +| `apps/workers` | The background workers logic | +| `apps/mobile` | The react native based mobile app | +| `apps/browser-extension` | The browser extension | +| `apps/landing` | The landing page of [karakeep.app](https://karakeep.app) | + +## Shared Packages + +| Directory | Description | +| ----------------- | ---------------------------------------------------------------------------- | +| `packages/db` | The database schema and migrations | +| `packages/trpc` | Where most of the business logic lies built as TRPC routes | +| `packages/shared` | Some shared code between the different apps (e.g. loggers, configs, assetdb) | + +## Toolings + +| Directory | Description | +| -------------------- | ----------------------- | +| `tooling/typescript` | The shared tsconfigs | +| `tooling/eslint` | ESlint configs | +| `tooling/prettier` | Prettier configs | +| `tooling/tailwind` | Shared tailwind configs | diff --git a/docs/docs/08-development/03-database.md b/docs/docs/08-development/03-database.md new file mode 100644 index 00000000..d7a15b62 --- /dev/null +++ b/docs/docs/08-development/03-database.md @@ -0,0 +1,10 @@ +# Database Migrations + +- The database schema lives in `packages/db/schema.ts`. +- Changing the schema, requires a migration. +- You can generate the migration by running `pnpm run db:generate --name description_of_schema_change` in the root dir. +- You can then apply the migration by running `pnpm run db:migrate`. + +## Drizzle Studio + +You can start the drizzle studio by running `pnpm run db:studio` in the root of the repo. diff --git a/docs/docs/08-development/04-architecture.md b/docs/docs/08-development/04-architecture.md new file mode 100644 index 00000000..5a864034 --- /dev/null +++ b/docs/docs/08-development/04-architecture.md @@ -0,0 +1,9 @@ +# Architecture + +![Architecture Diagram](/img/architecture/arch.png) + +- Webapp: NextJS based using sqlite for data storage. +- Workers: Consume the jobs from sqlite based job queue and executes them, there are three job types: + 1. Crawling: Fetches the content of links using a headless chrome browser running in the workers container. + 2. OpenAI: Uses OpenAI APIs to infer the tags of the content. + 3. Indexing: Indexes the content in meilisearch for faster retrieval during search. diff --git a/docs/docs/08-development/_category_.json b/docs/docs/08-development/_category_.json new file mode 100644 index 00000000..73dd67ec --- /dev/null +++ b/docs/docs/08-development/_category_.json @@ -0,0 +1,3 @@ +{ + "label": "Development", +} diff --git a/docs/docs/08-security-considerations.md b/docs/docs/08-security-considerations.md deleted file mode 100644 index 5a295526..00000000 --- a/docs/docs/08-security-considerations.md +++ /dev/null @@ -1,14 +0,0 @@ -# Security Considerations - -If you're going to give app access to untrusted users, there's some security considerations that you'll need to be aware of given how the crawler works. The crawler is basically running a browser to fetch the content of the bookmarks. Any untrusted user can submit bookmarks to be crawled from your server and they'll be able to see the crawling result. This can be abused in multiple ways: - -1. Untrusted users can submit crawl requests to websites that you don't want to be coming out of your IPs. -2. Crawling user controlled websites can expose your origin IP (and location) even if your service is hosted behind cloudflare for example. -3. The crawling requests will be coming out from your own network, which untrusted users can leverage to crawl internal non-internet exposed endpoints. - -To mitigate those risks, you can do one of the following: - -1. Limit access to trusted users -2. Let the browser traffic go through some VPN with restricted network policies. -3. Host the browser container outside of your network. -4. Use a hosted browser as a service (e.g. [browserless](https://browserless.io)). Note: I've never used them before. diff --git a/docs/docs/09-command-line.md b/docs/docs/09-command-line.md deleted file mode 100644 index c8b00696..00000000 --- a/docs/docs/09-command-line.md +++ /dev/null @@ -1,114 +0,0 @@ -# Command Line Tool (CLI) - -Karakeep comes with a simple CLI for those users who want to do more advanced manipulation. - -## Features - -- Manipulate bookmarks, lists and tags -- Mass import/export of bookmarks - -## Installation (NPM) - -``` -npm install -g @karakeep/cli -``` - - -## Installation (Docker) - -``` -docker run --rm ghcr.io/karakeep-app/karakeep-cli:release --help -``` - -## Usage - -``` -karakeep -``` - -``` -Usage: karakeep [options] [command] - -A CLI interface to interact with the karakeep api - -Options: - --api-key the API key to interact with the API (env: KARAKEEP_API_KEY) - --server-addr the address of the server to connect to (env: KARAKEEP_SERVER_ADDR) - -V, --version output the version number - -h, --help display help for command - -Commands: - bookmarks manipulating bookmarks - lists manipulating lists - tags manipulating tags - whoami returns info about the owner of this API key - help [command] display help for command -``` - -And some of the subcommands: - -``` -karakeep bookmarks -``` - -``` -Usage: karakeep bookmarks [options] [command] - -Manipulating bookmarks - -Options: - -h, --help display help for command - -Commands: - add [options] creates a new bookmark - get fetch information about a bookmark - update [options] updates bookmark - list [options] list all bookmarks - delete delete a bookmark - help [command] display help for command - -``` - -``` -karakeep lists -``` - -``` -Usage: karakeep lists [options] [command] - -Manipulating lists - -Options: - -h, --help display help for command - -Commands: - list lists all lists - delete deletes a list - add-bookmark [options] add a bookmark to list - remove-bookmark [options] remove a bookmark from list - help [command] display help for command -``` - -## Obtaining an API Key - -To use the CLI, you'll need to get an API key from your karakeep settings. You can validate that it's working by running: - -``` -karakeep --api-key --server-addr whoami -``` - -For example: - -``` -karakeep --api-key mysupersecretkey --server-addr https://try.karakeep.app whoami -{ - id: 'j29gnbzxxd01q74j2lu88tnb', - name: 'Test User', - email: 'test@gmail.com' -} -``` - - -## Other clients - -There also exists a **non-official**, community-maintained, python package called [karakeep-python-api](https://github.com/thiswillbeyourgithub/karakeep_python_api) that can be accessed from the CLI, but is **not** official. diff --git a/docs/docs/09-mcp.md b/docs/docs/09-mcp.md deleted file mode 100644 index 514332de..00000000 --- a/docs/docs/09-mcp.md +++ /dev/null @@ -1,65 +0,0 @@ -# Model Context Protocol Server (MCP) - -Karakeep comes with a Model Context Protocol server that can be used to interact with it through LLMs. - -## Supported Tools - -- Searching bookmarks -- Adding and removing bookmarks from lists -- Attaching and detaching tags to bookmarks -- Creating new lists -- Creating text and URL bookmarks - - -## Usage with Claude Desktop - -From NPM: - -```json -{ - "mcpServers": { - "karakeep": { - "command": "npx", - "args": [ - "@karakeep/mcp" - ], - "env": { - "KARAKEEP_API_ADDR": "https://", - "KARAKEEP_API_KEY": "" - } - } - } -} -``` - -From Docker: - -```json -{ - "mcpServers": { - "karakeep": { - "command": "docker", - "args": [ - "run", - "-e", - "KARAKEEP_API_ADDR=https://", - "-e", - "KARAKEEP_API_KEY=", - "ghcr.io/karakeep-app/karakeep-mcp:latest" - ] - } - } -} -``` - - -### Demo - -#### Search -![mcp-1](/img/mcp-1.gif) - -#### Adding Text Bookmarks -![mcp-2](/img/mcp-2.gif) - -#### Adding URL Bookmarks -![mcp-2](/img/mcp-3.gif) diff --git a/docs/docs/10-import.md b/docs/docs/10-import.md deleted file mode 100644 index 8ca8b1f9..00000000 --- a/docs/docs/10-import.md +++ /dev/null @@ -1,49 +0,0 @@ -# Importing Bookmarks - - -Karakeep supports importing bookmarks using the Netscape HTML Format, Pocket's new CSV format & Omnivore's JSONs. Titles, tags and addition date will be preserved during the import. An automatically created list will contain all the imported bookmarks. - -:::info -All the URLs in the bookmarks file will be added automatically, you will not be able to pick and choose which bookmarks to import! -::: - -## Import from Chrome - -- Open Chrome and go to `chrome://bookmarks` -- Click on the three dots on the top right corner and choose `Export bookmarks` -- This will download an html file with all of your bookmarks. -- To import the bookmark file, go to the settings and click "Import Bookmarks from HTML file". - -## Import from Firefox -- Open Firefox and click on the menu button (☰) in the top right corner. -- Navigate to Bookmarks > Manage bookmarks (or press Ctrl + Shift + O / Cmd + Shift + O to open the Bookmarks Library). -- In the Bookmarks Library, click the Import and Backup button at the top. Select Export Bookmarks to HTML... to save your bookmarks as an HTML file. -- To import a bookmark file, go back to the Import and Backup menu, then select Import Bookmarks from HTML... and choose your saved HTML file. - -## Import from Pocket - -- Go to the [Pocket export page](https://getpocket.com/export) and follow the instructions to export your bookmarks. -- Pocket after a couple of minutes will mail you a zip file with all the bookmarks. -- Unzip the file and you'll get a CSV file. -- To import the bookmark file, go to the settings and click "Import Bookmarks from Pocket export". - -## Import from Omnivore - -- Follow Omnivore's [documentation](https://docs.omnivore.app/using/exporting.html) to export your bookmarks. -- This will give you a zip file with all your data. -- The zip file contains a lot of JSONs in the format `metadata_*.json`. You can either import every JSON file manually, or merge the JSONs into a single JSON file and import that. -- To merge the JSONs into a single JSON file, you can use the following command in the unzipped directory: `jq -r '.[]' metadata_*.json | jq -s > omnivore.json` and then import the `omnivore.json` file. You'll need to have the [jq](https://github.com/jqlang/jq) tool installed. - -## Import using the CLI - -:::warning -Importing bookmarks using the CLI requires some technical knowledge and might not be very straightforward for non-technical users. Don't hesitate to ask questions in github discussions or discord though. -::: - -If you can get your bookmarks in a text file with one link per line, you can use the following command to import them using the [karakeep cli](https://docs.karakeep.app/command-line): - -``` -while IFS= read -r url; do - karakeep --api-key "" --server-addr "" bookmarks add --link "$url" -done < all_links.txt -``` diff --git a/docs/docs/11-FAQ.md b/docs/docs/11-FAQ.md deleted file mode 100644 index e6f59801..00000000 --- a/docs/docs/11-FAQ.md +++ /dev/null @@ -1,60 +0,0 @@ -# Frequently Asked Questions (FAQ) - -## User Management - -### Lost password - -#### If you are not an administrator - -Administrators can reset the password of any user. Contact an administrator to reset the password for you. - -- Navigate to the `Admin Settings` page -- Find the user in the `Users List` -- In the `Actions` column, there is a button to reset the password -- Enter a new password and press `Reset` -- The new password is now set -- If required, you can change your password again (so the admin does not know your password) in the `User Settings` - -#### If you are an administrator - -If you are an administrator and lost your password, you have to reset the password in the database. - -To reset the password: - -- Acquire some kind of tools that helps you to connect to the database: - - `sqlite3` on Linux: run `apt-get install sqlite3` (depending on your package manager) - - e.g. `dbeaver` on Windows -- Shut down Karakeep -- Connect to the `db.db` database, which is located in the `data` directory you have mounted to your docker container: - - by e.g. running `sqlite3 db.db` (in your `data` directory) - - or going through e.g. the `dbeaver` UI to locate the file in the data directory and connecting to it -- Update the password in the database by running: - - `update user set password='$2a$10$5u40XUq/cD/TmLdCOyZ82ePENE6hpkbodJhsp7.e/BgZssUO5DDTa', salt='' where email='';` - - (don't forget to put your email address into the command) -- The new password for your user is now `adminadmin`. -- Start Karakeep again -- Log in with your email address and the password `adminadmin` and change the password to whatever you want in the `User Settings` - -### Adding another administrator - -By default, the first user to sign up gets promoted to administrator automatically. - -In case you want to grant those permissions to another user: - -- Navigate to the `Admin Settings` page -- Find the user in the `Users List` -- In the `Actions` column, there is a button to change the Role -- Change the Role to `Admin` -- Press `Change` -- The new administrator has to log out and log in again to get the new role assigned - -### Adding new users, when signups are disabled - -Administrators can create new accounts any time: - -- Navigate to the `Admin Settings` page -- Go to the `Users List` -- Press the `Create User` Button. -- Enter the information for the user -- Press `create` -- The new user can now log in diff --git a/docs/docs/12-troubleshooting.md b/docs/docs/12-troubleshooting.md deleted file mode 100644 index 4072442b..00000000 --- a/docs/docs/12-troubleshooting.md +++ /dev/null @@ -1,46 +0,0 @@ -# Troubleshooting - -## SqliteError: no such table: user - -This usually means that there's something wrong with the database setup (more concretely, it means that the database is not initialized). This can be caused by multiple problems: -1. **Wiped DATA_DIR:** Your `DATA_DIR` got wiped (or the backing storage dir changed). If you did this intentionally, restart the container so that it can re-initalize the database. -2. **Missing DATA_DIR**: You're not using the default docker compose file, and you forgot to configure the `DATA_DIR` env var. This will result into the database getting set up in a different directory than the one used by the service. - -## Chrome Failed to Read DnsConfig - -If you see this error in the logs of the chrome container, it's a benign error and you can safely ignore it. Whatever problems you're having, is unrelated to this error. - -## AI Tagging not working (when using OpenAI) - -Check the logs of the container and this will usually tell you what's wrong. Common problems are: -1. Typo in the env variable `OPENAI_API_KEY` name resulting into logs saying something like "skipping inference as it's not configured". -2. You forgot to call `docker compose up` after configuring open ai. -3. OpenAI requires pre-charging the account with credits before using it, otherwise you'll get an error like "insufficient funds". - -## AI Tagging not working (when using Ollama) - -Check the logs of the container and this will usually tell you what's wrong. Common problems are: -1. Typo in the env variable `OLLAMA_BASE_URL` name resulting into logs saying something like "skipping inference as it's not configured". -2. You forgot to call `docker compose up` after configuring ollama. -3. You didn't change the `INFERENCE_TEXT_MODEL` env variable, resulting into karakeep attempting to use gpt models with ollama which won't work. -4. Ollama server is not reachable by the karakeep container. This can be caused by: - 1. Ollama server being in a different docker network than the karakeep container. - 2. You're using `localhost` as the `OLLAMA_BASE_URL` instead of the actual address of the ollama server. `localhost` points to the container itself, not the docker host. Check this [stackoverflow answer](https://stackoverflow.com/questions/24319662/from-inside-of-a-docker-container-how-do-i-connect-to-the-localhost-of-the-mach) to find how to correctly point to the docker host address instead. - -## Crawling not working - -Check the logs of the container and this will usually tell you what's wrong. Common problems are: -1. You changed the name of the chrome container but didn't change the `BROWSER_WEB_URL` env variable. - -## Upgrading Meilisearch - Migrating the Meilisearch db version - -[Meilisearch](https://www.meilisearch.com/) is the database used by karakeep for searching in your bookmarks. The version used by karakeep is `1.13.3` and it is advised not to upgrade it without good reasons. If you do, you might see errors like `Your database version (1.11.1) is incompatible with your current engine version (1.13.3). To migrate data between Meilisearch versions, please follow our guide on https://www.meilisearch.com/docs/learn/update_and_migration/updating.`. - -Luckily we can easily workaround this: -1. Stop the Meilisearch container. -2. Inside the Meilisearch volume bound to `/meili_data`, erase/rename the folder called `data.ms`. -3. Launch Meilisearch again. -4. Login to karakeep as administrator and go to (as of v0.24.1) `Admin Settings > Background Jobs` then click on `Reindex All Bookmarks`. -5. When the reindexing has finished, Meilisearch should be working as usual. - -If you run into issues, the official documentation can be found [there](https://www.meilisearch.com/docs/learn/update_and_migration/updating). diff --git a/docs/docs/13-community-projects.md b/docs/docs/13-community-projects.md deleted file mode 100644 index 828d545f..00000000 --- a/docs/docs/13-community-projects.md +++ /dev/null @@ -1,87 +0,0 @@ -# Community Projects - -This page lists community projects that are built around Karakeep, but not officially supported by the development team. - -:::warning -This list comes with no guarantees about security, performance, reliability, or accuracy. Use at your own risk. -::: - -### Raycast Extension - -_By [@luolei](https://github.com/foru17)._ - -A user-friendly Raycast extension that seamlessly integrates with Karakeep, bringing powerful bookmark management to your fingertips. Quickly save, search, and organize your bookmarks, texts, and images—all through Raycast's intuitive interface. - -Get it [here](https://www.raycast.com/luolei/karakeep). - -### Alfred Workflow - -_By [@yinan-c](https://github.com/yinan-c)_ - -An Alfred workflow to quickly hoard stuff or access your hoarded bookmarks! - -Get it [here](https://www.alfredforum.com/topic/22528-hoarder-workflow-for-self-hosted-bookmark-management/). - -### Obsidian Plugin - -_By [@jhofker](https://github.com/jhofker)_ - -An Obsidian plugin that syncs your Karakeep bookmarks with Obsidian, creating markdown notes for each bookmark in a designated folder. - -Get it [here](https://github.com/jhofker/obsidian-hoarder/), or install it directly from Obsidian's community plugin store ([link](https://obsidian.md/plugins?id=hoarder-sync)). - -### Telegram Bot - -_By [@Madh93](https://github.com/Madh93)_ - -A Telegram Bot for saving bookmarks to Karakeep directly through Telegram. - -Get it [here](https://github.com/Madh93/karakeepbot). - -### Hoarder's Pipette - -_By [@DanSnow](https://github.com/DanSnow)_ - -A chrome extension that injects karakeep's bookmarks into your search results. - -Get it [here](https://dansnow.github.io/hoarder-pipette/guides/installation/). - -### Karakeep-Python-API - -_By [@thiswillbeyourgithub](https://github.com/thiswillbeyourgithub/)_ - -A python package to simplify access to the karakeep API. Can be used as a library or from the CLI. Aims for feature completeness and high test coverage but do check its feature matrix before relying too much on it. - -Its repository also hosts the [Community Script](https://github.com/thiswillbeyourgithub/karakeep_python_api/tree/main/community_scripts), for example: - -| Community Script | Description | Documentation | -|----------------|-------------|---------------| -| **Karakeep-Time-Tagger** | Automatically adds time-to-read tags (`0-5m`, `5-10m`, etc.) to bookmarks based on content length analysis. Includes systemd service and timer files for automated periodic execution. | [`Link`](https://github.com/thiswillbeyourgithub/karakeep_python_api/tree/main/community_scripts/karakeep-time-tagger) | -| **Karakeep-List-To-Tag** | Converts a Karakeep list into tags by adding a specified tag to all bookmarks within that list. | [`Link`](https://github.com/thiswillbeyourgithub/karakeep_python_api/tree/main/community_scripts/karakeep-list-to-tag) | -| **Omnivore2Karakeep-Highlights** | Imports highlights from Omnivore export data to Karakeep, with intelligent position detection and bookmark matching. Supports dry-run mode for testing. | [`Link`](https://github.com/thiswillbeyourgithub/karakeep_python_api/tree/main/community_scripts/omnivore2karakeep-highlights) | - - -Get it [here](https://github.com/thiswillbeyourgithub/karakeep_python_api). - -### FreshRSS_to_Karakeep - -_By [@thiswillbeyourgithub](https://github.com/thiswillbeyourgithub/)_ - -A python script to automatically create Karakeep bookmarks from your [FreshRSS](https://github.com/FreshRSS/FreshRSS) *favourites/saved* RSS item. Made to be called periodically. Based on the community project `Karakeep-Python-API` above, by the same author. - -Get it [here](https://github.com/thiswillbeyourgithub/freshrss_to_karakeep). - -### karakeep-sync -_By [@sidoshi](https://github.com/sidoshi/)_ - -Sync links from Hacker News upvotes, Reddit Saves to Karakeep for centralized bookmark management. - -Get it [here](https://github.com/sidoshi/karakeep-sync) - -### Home Assistant Integration - -_By [@sli-cka](https://github.com/sli-cka)_ - -A custom integration that brings Karakeep data into Home Assistant. It exposes your Karakeep statistics data (like lists, bookmarks, tag, etc.) as Home Assistant entities, enabling dashboards, automations, and notifications based on your Karakeep data. - -Get it [here](https://github.com/sli-cka/karakeep-homeassistant) diff --git a/docs/docs/14-guides/01-legacy-container-upgrade.md b/docs/docs/14-guides/01-legacy-container-upgrade.md deleted file mode 100644 index d95c1c1e..00000000 --- a/docs/docs/14-guides/01-legacy-container-upgrade.md +++ /dev/null @@ -1,66 +0,0 @@ -# Legacy Container Upgrade - -Karakeep's 0.16 release consolidated the web and worker containers into a single container and also dropped the need for the redis container. The legacy containers will stop being supported soon, to upgrade to the new container do the following: - -1. Remove the redis container and its volume if it had one. -2. Move the environment variables that you've set exclusively to the `workers` container to the `web` container. -3. Delete the `workers` container. -4. Rename the web container image from `hoarder-app/hoarder-web` to `hoarder-app/hoarder`. - -```diff -diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml -index cdfc908..6297563 100644 ---- a/docker/docker-compose.yml -+++ b/docker/docker-compose.yml -@@ -1,7 +1,7 @@ - version: "3.8" - services: - web: -- image: ghcr.io/hoarder-app/hoarder-web:${KARAKEEP_VERSION:-release} -+ image: ghcr.io/karakeep-app/karakeep:${KARAKEEP_VERSION:-release} - restart: unless-stopped - volumes: - - data:/data -@@ -10,14 +10,10 @@ services: - env_file: - - .env - environment: -- REDIS_HOST: redis - MEILI_ADDR: http://meilisearch:7700 -+ BROWSER_WEB_URL: http://chrome:9222 -+ # OPENAI_API_KEY: ... - DATA_DIR: /data -- redis: -- image: redis:7.2-alpine -- restart: unless-stopped -- volumes: -- - redis:/data - chrome: - image: gcr.io/zenika-hub/alpine-chrome:123 - restart: unless-stopped -@@ -37,24 +33,7 @@ services: - MEILI_NO_ANALYTICS: "true" - volumes: - - meilisearch:/meili_data -- workers: -- image: ghcr.io/hoarder-app/hoarder-workers:${KARAKEEP_VERSION:-release} -- restart: unless-stopped -- volumes: -- - data:/data -- env_file: -- - .env -- environment: -- REDIS_HOST: redis -- MEILI_ADDR: http://meilisearch:7700 -- BROWSER_WEB_URL: http://chrome:9222 -- DATA_DIR: /data -- # OPENAI_API_KEY: ... -- depends_on: -- web: -- condition: service_started - - volumes: -- redis: - meilisearch: - data: -``` diff --git a/docs/docs/14-guides/02-search-query-language.md b/docs/docs/14-guides/02-search-query-language.md deleted file mode 100644 index 8f55ec2f..00000000 --- a/docs/docs/14-guides/02-search-query-language.md +++ /dev/null @@ -1,76 +0,0 @@ -# Search Query Language - -Karakeep provides a search query language to filter and find bookmarks. Here are all the supported qualifiers and how to use them: - -## Basic Syntax - -- Use spaces to separate multiple conditions (implicit AND) -- Use `and`/`or` keywords for explicit boolean logic -- Prefix qualifiers with `-` to negate them -- Use parentheses `()` for grouping conditions (note that groups can't be negated) - -## Qualifiers - -Here's a comprehensive table of all supported qualifiers: - -| Qualifier | Description | Example Usage | -| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------- | -| `is:fav` | Favorited bookmarks | `is:fav` | -| `is:archived` | Archived bookmarks | `-is:archived` | -| `is:tagged` | Bookmarks that has one or more tags | `is:tagged` | -| `is:inlist` | Bookmarks that are in one or more lists | `is:inlist` | -| `is:link`, `is:text`, `is:media` | Bookmarks that are of type link, text or media | `is:link` | -| `is:broken` | Bookmarks with broken/failed links (crawl failures or non-2xx status codes) | `is:broken` | -| `url:` | Match bookmarks with URL substring | `url:example.com` | -| `title:` | Match bookmarks with title substring | `title:example` | -| | Supports quoted strings for titles with spaces | `title:"my title"` | -| `#` | Match bookmarks with specific tag | `#important` | -| | Supports quoted strings for tags with spaces | `#"work in progress"` | -| `list:` | Match bookmarks in specific list | `list:reading` | -| | Supports quoted strings for list names with spaces | `list:"to review"` | -| `after:` | Bookmarks created on or after date (YYYY-MM-DD) | `after:2023-01-01` | -| `before:` | Bookmarks created on or before date (YYYY-MM-DD) | `before:2023-12-31` | -| `feed:` | Bookmarks imported from a particular rss feed | `feed:Hackernews` | -| `age:` | Match bookmarks based on how long ago they were created. Use `<` or `>` to indicate the maximum / minimum age of the bookmarks. Supported units: `d` (days), `w` (weeks), `m` (months), `y` (years). | `age:<1d` `age:>2w` `age:<6m` `age:>3y` | - -### Examples - -```plaintext -# Find favorited bookmarks from 2023 that are tagged "important" -is:fav after:2023-01-01 before:2023-12-31 #important - -# Find archived bookmarks that are either in "reading" list or tagged "work" -is:archived and (list:reading or #work) - -# Find bookmarks that are not tagged or not in any list --is:tagged or -is:inlist -# Find bookmarks with "React" in the title -title:React -``` - -## Combining Conditions - -You can combine multiple conditions using boolean logic: - -```plaintext -# Find favorited bookmarks from 2023 that are tagged "important" -is:fav after:2023-01-01 before:2023-12-31 #important - -# Find archived bookmarks that are either in "reading" list or tagged "work" -is:archived and (list:reading or #work) - -# Find bookmarks that are not favorited and not archived --is:fav -is:archived -``` - -## Text Search - -Any text not part of a qualifier will be treated as a full-text search: - -```plaintext -# Search for "machine learning" in bookmark content -machine learning - -# Combine text search with qualifiers -machine learning is:fav -``` diff --git a/docs/docs/14-guides/03-singlefile.md b/docs/docs/14-guides/03-singlefile.md deleted file mode 100644 index c0f4e174..00000000 --- a/docs/docs/14-guides/03-singlefile.md +++ /dev/null @@ -1,46 +0,0 @@ -# Using Karakeep with SingleFile Extension - -Karakeep supports being a destination for the [SingleFile extension](https://github.com/gildas-lormeau/SingleFile). This has the benefit of allowing you to use the singlefile extension to hoard links as you're seeing them in the browser. This is perfect for websites that don't like to get crawled, has annoying cookie banner or require authentication. - -## Setup - -1. Install the [SingleFile extension](https://github.com/gildas-lormeau/SingleFile). -2. In the extension settings, select `Destinations`. -3. Select `upload to a REST Form API`. -4. In the URL, insert the address: `https://YOUR_SERVER_ADDRESS/api/v1/bookmarks/singlefile`. -5. In the `authorization token` field, paste an API key that you can get from your karakeep settings. -6. Set `data field name` to `file`. -7. Set `URL field name` to `url`. -8. (Optional) Add `&ifexists=MODE` to the URL where MODE is one of `skip`, `overwrite`, `overwrite-recrawl`, `append`, or `append-recrawl`. See "Handling Existing Bookmarks" section below for details. - -Now, go to any page and click the singlefile extension icon. Once it's done with the upload, the bookmark should show up in your karakeep instance. Note that the singlefile extension doesn't show any progress on the upload. Given that archives are typically large, it might take 30+ seconds until the upload is done and starts showing up in Karakeep. - -## Handling Existing Bookmarks - -When uploading a page that already exists in your archive (same URL), you can control the behavior by setting the `ifexists` query parameter in the upload URL. The available modes are: - -- `skip` (default): If the bookmark already exists, skip creating a new one -- `overwrite`: Replace existing precrawled archive (only the most recent archive is kept) -- `overwrite-recrawl`: Replace existing archive and queue a recrawl to update content -- `append`: Add new archive version alongside existing ones -- `append-recrawl`: Add new archive and queue a recrawl - -To use these modes, append `?ifexists=MODE` to your upload URL, replacing `MODE` with your desired behavior. - -For example: -`https://YOUR_SERVER_ADDRESS/api/v1/bookmarks/singlefile?ifexists=overwrite` - - -## Recommended settings - -In the singlefile extension, you probably will want to change the following settings for better experience: -* Stylesheets > compress CSS content: on -* Stylesheets > group duplicate stylesheets together: on -* HTML content > remove frames: on - -Also, you most likely will want to change the default `MAX_ASSET_SIZE_MB` in karakeep to something higher, for example `100`. - -:::info -Currently, we don't support screenshots for singlefile uploads, but this will change in the future. -::: - diff --git a/docs/docs/14-guides/04-hoarder-to-karakeep-migration.md b/docs/docs/14-guides/04-hoarder-to-karakeep-migration.md deleted file mode 100644 index 289a091c..00000000 --- a/docs/docs/14-guides/04-hoarder-to-karakeep-migration.md +++ /dev/null @@ -1,28 +0,0 @@ -# Hoarder to Karakeep Migration - -Hoarder is rebranding to Karakeep. Due to github limitations, the old docker image might not be getting new updates after the rebranding. You might need to update your docker image to point to the new karakeep image instead by applying the following change in the docker compose file. - -```diff -diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml -index cdfc908..6297563 100644 ---- a/docker/docker-compose.yml -+++ b/docker/docker-compose.yml -@@ -1,7 +1,7 @@ - version: "3.8" - services: - web: -- image: ghcr.io/hoarder-app/hoarder:${HOARDER_VERSION:-release} -+ image: ghcr.io/karakeep-app/karakeep:${HOARDER_VERSION:-release} -``` - -You can also change the `HOARDER_VERSION` environment variable but if you do so remember to change it in the `.env` file as well. - -## Migrating a Baremetal Installation - -If you previously used the [Debian/Ubuntu install script](https://docs.karakeep.app/Installation/debuntu) to install Hoarder, there is an option to migrate your installation to Karakeep. - -```bash -bash karakeep-linux.sh migrate -``` - -This will migrate your installation with no user input required. After the migration, the script will also check for an update. diff --git a/docs/docs/14-guides/05-different-ai-providers.md b/docs/docs/14-guides/05-different-ai-providers.md deleted file mode 100644 index 9a86e04f..00000000 --- a/docs/docs/14-guides/05-different-ai-providers.md +++ /dev/null @@ -1,88 +0,0 @@ -# Configuring different AI Providers - -Karakeep uses LLM providers for AI tagging and summarization. We support OpenAI-compatible providers and ollama. This guide will show you how to configure different providers. - -## OpenAI - -If you want to use OpenAI itself, you just need to pass in the OPENAI_API_KEY environment variable. - -``` -OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - -# You can change the default models by uncommenting the following lines, and choosing your model. -# INFERENCE_TEXT_MODEL=gpt-4.1-mini -# INFERENCE_IMAGE_MODEL=gpt-4o-mini -``` - -## Ollama - -Ollama is a local LLM provider that you can use to run your own LLM server. You'll need to pass ollama's address to karakeep and you need to ensure that it's accessible from within the karakeep container (e.g. no localhost addresses). - -``` -# MAKE SURE YOU DON'T HAVE OPENAI_API_KEY set, otherwise it takes precedence. - -OLLAMA_BASE_URL=http://ollama.mylab.com:11434 - -# Make sure to pull the models in ollama first. Example models: -INFERENCE_TEXT_MODEL=gemma3 -INFERENCE_IMAGE_MODEL=llava - -# If the model you're using doesn't support structured output, you also need: -# INFERENCE_OUTPUT_SCHEMA=plain -``` - -## Gemini - -Gemini has an OpenAI-compatible API. You need to get an api key from Google AI Studio. - -``` - -OPENAI_BASE_URL=https://generativelanguage.googleapis.com/v1beta -OPENAI_API_KEY=YOUR_API_KEY - -# Example models: -INFERENCE_TEXT_MODEL=gemini-2.0-flash -INFERENCE_IMAGE_MODEL=gemini-2.0-flash -``` - -## OpenRouter - -``` -OPENAI_BASE_URL=https://openrouter.ai/api/v1 -OPENAI_API_KEY=YOUR_API_KEY - -# Example models: -INFERENCE_TEXT_MODEL=meta-llama/llama-4-scout -INFERENCE_IMAGE_MODEL=meta-llama/llama-4-scout -``` - -## Perplexity - -``` -OPENAI_BASE_URL: https://api.perplexity.ai -OPENAI_API_KEY: Your Perplexity API Key -INFERENCE_TEXT_MODEL: sonar-pro -INFERENCE_IMAGE_MODEL: sonar-pro -``` - -## Azure - -Azure has an OpenAI-compatible API. - -You can get your API key from the Overview page of the Azure AI Foundry Portal or via "Keys + Endpoints" on the resource in the Azure Portal. - -:::warning -The [model name is the deployment name](https://learn.microsoft.com/en-us/azure/ai-foundry/openai/how-to/switching-endpoints#keyword-argument-for-model) you specified when deploying the model, which may differ from the base model name. -::: - -``` -# Deployed via Azure AI Foundry: -OPENAI_BASE_URL=https://{your-azure-ai-foundry-resource-name}.cognitiveservices.azure.com/openai/v1/ - -# Deployed via Azure OpenAI Service: -OPENAI_BASE_URL=https://{your-azure-openai-resource-name}.openai.azure.com/openai/v1/ - -OPENAI_API_KEY=YOUR_API_KEY -INFERENCE_TEXT_MODEL=YOUR_DEPLOYMENT_NAME -INFERENCE_IMAGE_MODEL=YOUR_DEPLOYMENT_NAME -``` diff --git a/docs/docs/14-guides/06-server-migration.md b/docs/docs/14-guides/06-server-migration.md deleted file mode 100644 index 147ae1ec..00000000 --- a/docs/docs/14-guides/06-server-migration.md +++ /dev/null @@ -1,71 +0,0 @@ -# Migrating Between Servers - -This guide explains how to migrate all of your data from one Karakeep server to another using the official CLI. - -## What the command does - -The migration copies user-owned data from a source server to a destination server in this order: - -- User settings -- Lists (preserving hierarchy and settings) -- RSS feeds -- AI prompts (custom prompts and their enabled state) -- Webhooks (URL and events) -- Tags (ensures tags by name exist) -- Rule engine rules (IDs remapped to destination equivalents) -- Bookmarks (links, text, and assets) - - After creation, attaches the correct tags and adds to the correct lists - -Notes: -- Webhook tokens cannot be read via the API, so tokens are not migrated. Re‑add them on the destination if needed. -- Asset bookmarks are migrated by downloading the original asset and re‑uploading it to the destination. Only images and PDFs are supported for asset bookmarks. -- Link bookmarks on the destination may be de‑duplicated if the same URL already exists. - -## Prerequisites - -- Install the CLI: - - NPM: `npm install -g @karakeep/cli` - - Docker: `docker run --rm ghcr.io/karakeep-app/karakeep-cli:release --help` -- Collect API keys and base URLs for both servers: - - Source: `--server-addr`, `--api-key` - - Destination: `--dest-server`, `--dest-api-key` - -## Quick start - -``` -karakeep --server-addr https://src.example.com --api-key migrate \ - --dest-server https://dest.example.com \ - --dest-api-key -``` - -The command is long‑running and shows live progress for each phase. You will be prompted for confirmation; pass `--yes` to skip the prompt. - -### Options - -- `--server-addr `: Source server base URL -- `--api-key `: API key for the source server -- `--dest-server `: Destination server base URL -- `--dest-api-key `: API key for the destination server -- `--batch-size `: Page size for bookmark migration (default 50, max 100) -- `-y`, `--yes`: Skip the confirmation prompt - -## What to expect - -- Lists are recreated parent‑first and retain their hierarchy. -- Feeds, prompts, webhooks, and tags are recreated by value. -- Rules are recreated after IDs (tags, lists, feeds) are remapped to their corresponding destination IDs. -- After each bookmark is created, the command attaches the correct tags and adds it to the correct lists. - -## Caveats and tips - -- Webhook auth tokens must be re‑entered on the destination after migration. -- If your destination already contains data, duplicate links may be de‑duplicated; tags and list membership are still applied to the existing bookmark. - -## Troubleshooting - -- If the command exits early, you can re‑run it, but note: - - Tags and lists that already exist are reused. - - Link de‑duplication avoids duplicate link bookmarks. Notes and assets will get re-created. - - Rules, webhooks, rss feeds will get re-created and you'll have to manually clean them up afterwards. - - The progress log indicates how far it got. -- Use a smaller `--batch-size` if your source or destination is under heavy load. diff --git a/docs/docs/14-guides/_category_.json b/docs/docs/14-guides/_category_.json deleted file mode 100644 index 117f7f1b..00000000 --- a/docs/docs/14-guides/_category_.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "label": "Guides", -} diff --git a/docs/docusaurus.config.ts b/docs/docusaurus.config.ts index 9de88d45..1ba393d1 100644 --- a/docs/docusaurus.config.ts +++ b/docs/docusaurus.config.ts @@ -19,7 +19,7 @@ const config: Config = { organizationName: "karakeep-app", // Usually your GitHub org/user name. projectName: "karakeep", // Usually your repo name. - onBrokenLinks: "throw", + onBrokenLinks: "warn", onBrokenMarkdownLinks: "warn", // Even if you don't use internationalization, you can use this field to set @@ -57,6 +57,85 @@ const config: Config = { ], ], plugins: [ + [ + "@docusaurus/plugin-client-redirects", + { + // redirects: [ + // { + // to: "/getting-started/intro", + // from: "/intro", + // }, + // { + // to: "/getting-started/screenshots", + // from: "/screenshots", + // }, + // { + // to: "/configuration/environment-variables", + // from: "/configuration", + // }, + // { + // to: "/using-karakeep/quick-sharing", + // from: "/quick-sharing", + // }, + // { + // to: "/using-karakeep/import", + // from: "/import", + // }, + // { + // to: "/using-karakeep/search-query-language", + // from: "/guides/search-query-language", + // }, + // { + // to: "/integrations/openai", + // from: "/openai", + // }, + // { + // to: "/integrations/command-line", + // from: "/command-line", + // }, + // { + // to: "/integrations/mcp", + // from: "/mcp", + // }, + // { + // to: "/integrations/different-ai-providers", + // from: "/guides/different-ai-providers", + // }, + // { + // to: "/integrations/singlefile", + // from: "/guides/singlefile", + // }, + // { + // to: "/administration/security-considerations", + // from: "/security-considerations", + // }, + // { + // to: "/administration/FAQ", + // from: "/FAQ", + // }, + // { + // to: "/administration/troubleshooting", + // from: "/troubleshooting", + // }, + // { + // to: "/administration/server-migration", + // from: "/guides/server-migration", + // }, + // { + // to: "/administration/legacy-container-upgrade", + // from: "/guides/legacy-container-upgrade", + // }, + // { + // to: "/administration/hoarder-to-karakeep-migration", + // from: "/guides/hoarder-to-karakeep-migration", + // }, + // { + // to: "/community/community-projects", + // from: "/community-projects", + // }, + // ], + }, + ], [ "docusaurus-plugin-openapi-docs", { @@ -110,10 +189,10 @@ const config: Config = { }, algolia: { - appId: 'V93C1M14G6', + appId: "V93C1M14G6", // Public API key: it is safe to commit it - apiKey: '0eb8853d9740822fb9d21620d5515f35', - indexName: 'karakeep', + apiKey: "0eb8853d9740822fb9d21620d5515f35", + indexName: "karakeep", contextualSearch: true, insights: true, }, diff --git a/docs/package.json b/docs/package.json index 06bc3ad5..e04dbda2 100644 --- a/docs/package.json +++ b/docs/package.json @@ -17,6 +17,7 @@ }, "dependencies": { "@docusaurus/core": "3.8.1", + "@docusaurus/plugin-client-redirects": "^3.8.1", "@docusaurus/preset-classic": "3.8.1", "@mdx-js/react": "^3.0.0", "clsx": "^2.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 86bd8236..5403cf04 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -959,6 +959,9 @@ importers: '@docusaurus/core': specifier: 3.8.1 version: 3.8.1(@mdx-js/react@3.1.0(@types/react@19.2.5)(react@19.1.0))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.3) + '@docusaurus/plugin-client-redirects': + specifier: ^3.8.1 + version: 3.8.1(@mdx-js/react@3.1.0(@types/react@19.2.5)(react@19.1.0))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.3) '@docusaurus/preset-classic': specifier: 3.8.1 version: 3.8.1(@algolia/client-search@5.27.0)(@mdx-js/react@3.1.0(@types/react@19.2.5)(react@19.1.0))(@types/react@19.2.5)(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(search-insights@2.17.3)(typescript@5.9.3) @@ -970,10 +973,10 @@ importers: version: 2.1.0 docusaurus-plugin-openapi-docs: specifier: ^4.3.7 - version: 4.4.0(@docusaurus/plugin-content-docs@3.8.1(@mdx-js/react@3.1.0(@types/react@19.2.5)(react@19.1.0))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.3))(@docusaurus/utils-validation@3.8.1(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@docusaurus/utils@3.8.1(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(encoding@0.1.13)(react@19.1.0) + version: 4.4.0(@docusaurus/plugin-content-docs@3.8.1(@mdx-js/react@3.1.0(@types/react@19.2.5)(react@19.1.0))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.3))(@docusaurus/utils-validation@3.9.2(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@docusaurus/utils@3.9.2(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(encoding@0.1.13)(react@19.1.0) docusaurus-theme-openapi-docs: specifier: ^4.4.0 - version: 4.4.0(@docusaurus/theme-common@3.8.1(@docusaurus/plugin-content-docs@3.8.1(@mdx-js/react@3.1.0(@types/react@19.2.5)(react@19.1.0))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.3))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@types/react@19.2.5)(docusaurus-plugin-openapi-docs@4.4.0(@docusaurus/plugin-content-docs@3.8.1(@mdx-js/react@3.1.0(@types/react@19.2.5)(react@19.1.0))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.3))(@docusaurus/utils-validation@3.8.1(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@docusaurus/utils@3.8.1(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(encoding@0.1.13)(react@19.1.0))(docusaurus-plugin-sass@0.2.6(@docusaurus/core@3.8.1(@mdx-js/react@3.1.0(@types/react@19.2.5)(react@19.1.0))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.3))(sass@1.89.1)(webpack@5.99.9))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(webpack@5.99.9) + version: 4.4.0(@docusaurus/theme-common@3.8.1(@docusaurus/plugin-content-docs@3.8.1(@mdx-js/react@3.1.0(@types/react@19.2.5)(react@19.1.0))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.3))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@types/react@19.2.5)(docusaurus-plugin-openapi-docs@4.4.0(@docusaurus/plugin-content-docs@3.8.1(@mdx-js/react@3.1.0(@types/react@19.2.5)(react@19.1.0))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.3))(@docusaurus/utils-validation@3.9.2(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@docusaurus/utils@3.9.2(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(encoding@0.1.13)(react@19.1.0))(docusaurus-plugin-sass@0.2.6(@docusaurus/core@3.8.1(@mdx-js/react@3.1.0(@types/react@19.2.5)(react@19.1.0))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.3))(sass@1.89.1)(webpack@5.99.9))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(webpack@5.99.9) prism-react-renderer: specifier: ^2.4.1 version: 2.4.1(react@19.1.0) @@ -2900,6 +2903,10 @@ packages: resolution: {integrity: sha512-2wjeGDhKcExEmjX8k1N/MRDiPKXGF2Pg+df/bDDPnnJWHXnVEZxXj80d6jcxp1Gpnksl0hF8t/ZQw9elqj2+ww==} engines: {node: '>=18.0'} + '@docusaurus/logger@3.9.2': + resolution: {integrity: sha512-/SVCc57ByARzGSU60c50rMyQlBuMIJCjcsJlkphxY6B0GV4UH3tcA1994N8fFfbJ9kX3jIBe/xg3XP5qBtGDbA==} + engines: {node: '>=20.0'} + '@docusaurus/mdx-loader@3.8.1': resolution: {integrity: sha512-DZRhagSFRcEq1cUtBMo4TKxSNo/W6/s44yhr8X+eoXqCLycFQUylebOMPseHi5tc4fkGJqwqpWJLz6JStU9L4w==} engines: {node: '>=18.0'} @@ -2913,6 +2920,13 @@ packages: react: '*' react-dom: '*' + '@docusaurus/plugin-client-redirects@3.8.1': + resolution: {integrity: sha512-F+86R7PBn6VNgy/Ux8w3ZRypJGJEzksbejQKlbTC8u6uhBUhfdXWkDp6qdOisIoW0buY5nLqucvZt1zNJzhJhA==} + engines: {node: '>=18.0'} + peerDependencies: + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + '@docusaurus/plugin-content-blog@3.8.1': resolution: {integrity: sha512-vNTpMmlvNP9n3hGEcgPaXyvTljanAKIUkuG9URQ1DeuDup0OR7Ltvoc8yrmH+iMZJbcQGhUJF+WjHLwuk8HSdw==} engines: {node: '>=18.0'} @@ -3028,18 +3042,36 @@ packages: react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 + '@docusaurus/types@3.9.2': + resolution: {integrity: sha512-Ux1JUNswg+EfUEmajJjyhIohKceitY/yzjRUpu04WXgvVz+fbhVC0p+R0JhvEu4ytw8zIAys2hrdpQPBHRIa8Q==} + peerDependencies: + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + '@docusaurus/utils-common@3.8.1': resolution: {integrity: sha512-zTZiDlvpvoJIrQEEd71c154DkcriBecm4z94OzEE9kz7ikS3J+iSlABhFXM45mZ0eN5pVqqr7cs60+ZlYLewtg==} engines: {node: '>=18.0'} + '@docusaurus/utils-common@3.9.2': + resolution: {integrity: sha512-I53UC1QctruA6SWLvbjbhCpAw7+X7PePoe5pYcwTOEXD/PxeP8LnECAhTHHwWCblyUX5bMi4QLRkxvyZ+IT8Aw==} + engines: {node: '>=20.0'} + '@docusaurus/utils-validation@3.8.1': resolution: {integrity: sha512-gs5bXIccxzEbyVecvxg6upTwaUbfa0KMmTj7HhHzc016AGyxH2o73k1/aOD0IFrdCsfJNt37MqNI47s2MgRZMA==} engines: {node: '>=18.0'} + '@docusaurus/utils-validation@3.9.2': + resolution: {integrity: sha512-l7yk3X5VnNmATbwijJkexdhulNsQaNDwoagiwujXoxFbWLcxHQqNQ+c/IAlzrfMMOfa/8xSBZ7KEKDesE/2J7A==} + engines: {node: '>=20.0'} + '@docusaurus/utils@3.8.1': resolution: {integrity: sha512-P1ml0nvOmEFdmu0smSXOqTS1sxU5tqvnc0dA4MTKV39kye+bhQnjkIKEE18fNOvxjyB86k8esoCIFM3x4RykOQ==} engines: {node: '>=18.0'} + '@docusaurus/utils@3.9.2': + resolution: {integrity: sha512-lBSBiRruFurFKXr5Hbsl2thmGweAPmddhF3jb99U4EMDA5L+e5Y1rAkOS07Nvrup7HUMBDrCV45meaxZnt28nQ==} + engines: {node: '>=20.0'} + '@drizzle-team/brocli@0.10.2': resolution: {integrity: sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==} @@ -17286,6 +17318,11 @@ snapshots: chalk: 4.1.2 tslib: 2.8.1 + '@docusaurus/logger@3.9.2': + dependencies: + chalk: 4.1.2 + tslib: 2.8.1 + '@docusaurus/mdx-loader@3.8.1(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@docusaurus/logger': 3.8.1 @@ -17341,6 +17378,38 @@ snapshots: - uglify-js - webpack-cli + '@docusaurus/plugin-client-redirects@3.8.1(@mdx-js/react@3.1.0(@types/react@19.2.5)(react@19.1.0))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.3)': + dependencies: + '@docusaurus/core': 3.8.1(@mdx-js/react@3.1.0(@types/react@19.2.5)(react@19.1.0))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.3) + '@docusaurus/logger': 3.8.1 + '@docusaurus/utils': 3.8.1(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@docusaurus/utils-common': 3.8.1(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@docusaurus/utils-validation': 3.8.1(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + eta: 2.2.0 + fs-extra: 11.3.0 + lodash: 4.17.21 + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + tslib: 2.8.1 + transitivePeerDependencies: + - '@docusaurus/faster' + - '@mdx-js/react' + - '@parcel/css' + - '@rspack/core' + - '@swc/core' + - '@swc/css' + - acorn + - bufferutil + - csso + - debug + - esbuild + - lightningcss + - supports-color + - typescript + - uglify-js + - utf-8-validate + - webpack-cli + '@docusaurus/plugin-content-blog@3.8.1(@docusaurus/plugin-content-docs@3.8.1(@mdx-js/react@3.1.0(@types/react@19.2.5)(react@19.1.0))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.3))(@mdx-js/react@3.1.0(@types/react@19.2.5)(react@19.1.0))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.3)': dependencies: '@docusaurus/core': 3.8.1(@mdx-js/react@3.1.0(@types/react@19.2.5)(react@19.1.0))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.3) @@ -17847,6 +17916,28 @@ snapshots: - uglify-js - webpack-cli + '@docusaurus/types@3.9.2(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@mdx-js/mdx': 3.1.0(acorn@8.15.0) + '@types/history': 4.7.11 + '@types/mdast': 4.0.4 + '@types/react': 19.2.5 + commander: 5.1.0 + joi: 17.13.3 + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + react-helmet-async: '@slorber/react-helmet-async@1.3.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)' + utility-types: 3.11.0 + webpack: 5.99.9 + webpack-merge: 5.10.0 + transitivePeerDependencies: + - '@swc/core' + - acorn + - esbuild + - supports-color + - uglify-js + - webpack-cli + '@docusaurus/utils-common@3.8.1(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@docusaurus/types': 3.8.1(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -17861,6 +17952,20 @@ snapshots: - uglify-js - webpack-cli + '@docusaurus/utils-common@3.9.2(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@docusaurus/types': 3.9.2(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + tslib: 2.8.1 + transitivePeerDependencies: + - '@swc/core' + - acorn + - esbuild + - react + - react-dom + - supports-color + - uglify-js + - webpack-cli + '@docusaurus/utils-validation@3.8.1(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@docusaurus/logger': 3.8.1 @@ -17881,6 +17986,26 @@ snapshots: - uglify-js - webpack-cli + '@docusaurus/utils-validation@3.9.2(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@docusaurus/logger': 3.9.2 + '@docusaurus/utils': 3.9.2(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@docusaurus/utils-common': 3.9.2(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + fs-extra: 11.3.0 + joi: 17.13.3 + js-yaml: 4.1.0 + lodash: 4.17.21 + tslib: 2.8.1 + transitivePeerDependencies: + - '@swc/core' + - acorn + - esbuild + - react + - react-dom + - supports-color + - uglify-js + - webpack-cli + '@docusaurus/utils@3.8.1(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@docusaurus/logger': 3.8.1 @@ -17914,6 +18039,39 @@ snapshots: - uglify-js - webpack-cli + '@docusaurus/utils@3.9.2(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@docusaurus/logger': 3.9.2 + '@docusaurus/types': 3.9.2(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@docusaurus/utils-common': 3.9.2(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + escape-string-regexp: 4.0.0 + execa: 5.1.1 + file-loader: 6.2.0(webpack@5.99.9) + fs-extra: 11.3.0 + github-slugger: 1.5.0 + globby: 11.1.0 + gray-matter: 4.0.3 + jiti: 1.21.7 + js-yaml: 4.1.0 + lodash: 4.17.21 + micromatch: 4.0.8 + p-queue: 6.6.2 + prompts: 2.4.2 + resolve-pathname: 3.0.0 + tslib: 2.8.1 + url-loader: 4.1.1(file-loader@6.2.0(webpack@5.99.9))(webpack@5.99.9) + utility-types: 3.11.0 + webpack: 5.99.9 + transitivePeerDependencies: + - '@swc/core' + - acorn + - esbuild + - react + - react-dom + - supports-color + - uglify-js + - webpack-cli + '@drizzle-team/brocli@0.10.2': {} '@egjs/hammerjs@2.0.17': @@ -23187,12 +23345,12 @@ snapshots: dependencies: '@leichtgewicht/ip-codec': 2.0.5 - docusaurus-plugin-openapi-docs@4.4.0(@docusaurus/plugin-content-docs@3.8.1(@mdx-js/react@3.1.0(@types/react@19.2.5)(react@19.1.0))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.3))(@docusaurus/utils-validation@3.8.1(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@docusaurus/utils@3.8.1(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(encoding@0.1.13)(react@19.1.0): + docusaurus-plugin-openapi-docs@4.4.0(@docusaurus/plugin-content-docs@3.8.1(@mdx-js/react@3.1.0(@types/react@19.2.5)(react@19.1.0))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.3))(@docusaurus/utils-validation@3.9.2(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@docusaurus/utils@3.9.2(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(encoding@0.1.13)(react@19.1.0): dependencies: '@apidevtools/json-schema-ref-parser': 11.9.3 '@docusaurus/plugin-content-docs': 3.8.1(@mdx-js/react@3.1.0(@types/react@19.2.5)(react@19.1.0))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.3) - '@docusaurus/utils': 3.8.1(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@docusaurus/utils-validation': 3.8.1(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@docusaurus/utils': 3.9.2(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@docusaurus/utils-validation': 3.9.2(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@redocly/openapi-core': 1.34.3(supports-color@10.0.0) allof-merge: 0.6.6 chalk: 4.1.2 @@ -23223,7 +23381,7 @@ snapshots: - sass-embedded - webpack - docusaurus-theme-openapi-docs@4.4.0(@docusaurus/theme-common@3.8.1(@docusaurus/plugin-content-docs@3.8.1(@mdx-js/react@3.1.0(@types/react@19.2.5)(react@19.1.0))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.3))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@types/react@19.2.5)(docusaurus-plugin-openapi-docs@4.4.0(@docusaurus/plugin-content-docs@3.8.1(@mdx-js/react@3.1.0(@types/react@19.2.5)(react@19.1.0))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.3))(@docusaurus/utils-validation@3.8.1(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@docusaurus/utils@3.8.1(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(encoding@0.1.13)(react@19.1.0))(docusaurus-plugin-sass@0.2.6(@docusaurus/core@3.8.1(@mdx-js/react@3.1.0(@types/react@19.2.5)(react@19.1.0))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.3))(sass@1.89.1)(webpack@5.99.9))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(webpack@5.99.9): + docusaurus-theme-openapi-docs@4.4.0(@docusaurus/theme-common@3.8.1(@docusaurus/plugin-content-docs@3.8.1(@mdx-js/react@3.1.0(@types/react@19.2.5)(react@19.1.0))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.3))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@types/react@19.2.5)(docusaurus-plugin-openapi-docs@4.4.0(@docusaurus/plugin-content-docs@3.8.1(@mdx-js/react@3.1.0(@types/react@19.2.5)(react@19.1.0))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.3))(@docusaurus/utils-validation@3.9.2(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@docusaurus/utils@3.9.2(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(encoding@0.1.13)(react@19.1.0))(docusaurus-plugin-sass@0.2.6(@docusaurus/core@3.8.1(@mdx-js/react@3.1.0(@types/react@19.2.5)(react@19.1.0))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.3))(sass@1.89.1)(webpack@5.99.9))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(webpack@5.99.9): dependencies: '@docusaurus/theme-common': 3.8.1(@docusaurus/plugin-content-docs@3.8.1(@mdx-js/react@3.1.0(@types/react@19.2.5)(react@19.1.0))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.3))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@hookform/error-message': 2.0.1(react-dom@19.1.0(react@19.1.0))(react-hook-form@7.62.0(react@19.1.0))(react@19.1.0) @@ -23233,7 +23391,7 @@ snapshots: clsx: 1.2.1 copy-text-to-clipboard: 3.2.0 crypto-js: 4.2.0 - docusaurus-plugin-openapi-docs: 4.4.0(@docusaurus/plugin-content-docs@3.8.1(@mdx-js/react@3.1.0(@types/react@19.2.5)(react@19.1.0))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.3))(@docusaurus/utils-validation@3.8.1(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@docusaurus/utils@3.8.1(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(encoding@0.1.13)(react@19.1.0) + docusaurus-plugin-openapi-docs: 4.4.0(@docusaurus/plugin-content-docs@3.8.1(@mdx-js/react@3.1.0(@types/react@19.2.5)(react@19.1.0))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.3))(@docusaurus/utils-validation@3.9.2(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@docusaurus/utils@3.9.2(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(encoding@0.1.13)(react@19.1.0) docusaurus-plugin-sass: 0.2.6(@docusaurus/core@3.8.1(@mdx-js/react@3.1.0(@types/react@19.2.5)(react@19.1.0))(acorn@8.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.3))(sass@1.89.1)(webpack@5.99.9) file-saver: 2.0.5 lodash: 4.17.21 -- cgit v1.2.3-70-g09d2