## File: README.md

##  Introduction

linkding is a bookmark manager that you can host yourself.
It's designed be to be minimal, fast, and easy to set up using Docker.

The name comes from:
- *link* which is often used as a synonym for URLs and bookmarks in common language
- *Ding* which is German for thing
- ...so basically something for managing your links

**Feature Overview:**
- Clean UI optimized for readability
- Organize bookmarks with tags
- Bulk editing, Markdown notes, read it later functionality
- Share bookmarks with other users or guests
- Automatically provides titles, descriptions and icons of bookmarked websites
- Automatically archive websites, either as local HTML file or on Internet Archive
- Import and export bookmarks in Netscape HTML format
- Installable as a Progressive Web App (PWA)
- Extensions for [Firefox](https://addons.mozilla.org/firefox/addon/linkding-extension/) and [Chrome](https://chrome.google.com/webstore/detail/linkding-extension/beakmhbijpdhipnjhnclmhgjlddhidpe), as well as a bookmarklet
- SSO support via OIDC or authentication proxies
- REST API for developing 3rd party apps
- Admin panel for user self-service and raw data access


**Demo:** https://demo.linkding.link/

**Screenshot:**



## Getting Started

The following links help you to get started with linkding:
- [Install linkding on your own server](https://linkding.link/installation) or [check managed hosting options](https://linkding.link/managed-hosting)
- [Install the browser extension](https://linkding.link/browser-extension)
- [Check out community projects](https://linkding.link/community), which include mobile apps, browser extensions, libraries and more

## Documentation

The full documentation is now available at [linkding.link](https://linkding.link/).

If you want to contribute to the documentation, you can find the source files in the `docs` folder.

If you want to contribute a community project, feel free to [submit a PR](https://github.com/sissbruecker/linkding/edit/master/docs/src/content/docs/community.md).

## Contributing

Small improvements, bugfixes and documentation improvements are always welcome. If you want to contribute a larger feature, consider opening an issue first to discuss it. I may choose to ignore PRs for features that don't align with the project's goals or that I don't want to maintain.

## Development

The application is built using the Django web framework. You can get started by checking out the excellent [Django docs](https://docs.djangoproject.com/en/4.1/). The `bookmarks` folder contains the actual bookmark application. Other than that the code should be self-explanatory / standard Django stuff 🙂.

### Prerequisites
- Python 3.13
- [uv](https://docs.astral.sh/uv/getting-started/installation/)
- Node.js

### Setup

Initialize the development environment with:
```
make init
```
This sets up a virtual environment using uv, installs NPM dependencies and runs migrations to create the initial database.

Create a user for the frontend:
```
uv run manage.py createsuperuser --username=joe --email=joe@example.com
```

Run the frontend build for bundling frontend components with:
```
make frontend
```

Then start the Django development server with:
```
make serve
```
The frontend is now available under http://localhost:8000

### Tests

Run all tests with pytest:
```
make test
```


### Linting

Run linting with ruff:
```
make lint
```

### Formatting

Format Python code with ruff, Django templates with djlint, and JavaScript code with prettier:
```
make format
```

### DevContainers

This repository also supports DevContainers: [](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/sissbruecker/linkding.git)

Once checked out, only the following commands are required to get started:

Create a user for the frontend:
```
uv run manage.py createsuperuser --username=joe --email=joe@example.com
```
Start the Node.js development server (used for compiling JavaScript components like tag auto-completion) with:
```
make frontend
```
Start the Django development server with:
```
make serve
```
The frontend is now available under http://localhost:8000

---

## File: docs/src/content/docs/admin.md

---
title: "Admin"
---

This document describes how to make use of the admin app that comes as part of each linkding installation. This is the default Django admin app with some linkding specific customizations.

The admin app provides several features that are not available in the linkding UI:
- User management and user self-management
- Bookmark and tag management, including bulk operations

## Linkding administration page

To open the Admin app, go the *Settings* view and click on the *Admin* tab. This should open a new window with the admin app.

Alternatively you can open the URL directly by adding `/admin` to the URL of your linkding installation.

## User management

Go to the linkding administration page and select *Users*.
Here you can add and delete users, and change the password of a user.

Once you have added a user you can, if needed, give the user staff status, which means this user can also access the linkding administration page.

This page also allows you to change your own password if necessary.

## Bookmark management

While the linkding UI itself now has a bulk edit feature for bookmarks you can also use the admin app to manage bookmarks or to do bulk operations. 

In the main linkding administration page, choose *Bookmarks*.

First select the bookmarks to operate on:

- Specify a filter to determine which bookmarks to operate on:
  - In the column *by username*, you can choose to filter for bookmarks for a specific user
  - In the column *by is archived*, you can choose to filter for bookmarks that are either archived or not
  - In the column *by tags*, you can choose to filter for specific tags
  - In the search box you can also add a text filter (note that this doesn't use the same search syntax as the linkding UI itself)  

Now a list of bookmarks which match your filter is displayed, each bookmark on a separate line.
Each line starts with a checkbox.
Either choose the individual bookmarks you want to do a bulk operation on, or choose the top checkbox to select all shown bookmarks.

Open the "Action" select box to choose the desired bulk operation:

- Delete
- Archive
- Unarchive

Click the button next to the checkbox to execute the operation.

## Tag management

While linkding UI currently only allows to create or assign tags, you can use the admin app to manage your tags. This can be especially useful if you want to clean up your tag collection.

In the main linkding administration page, choose *Tags*.

Similar to bookmarks management described above you can now specify which tags to operate on by specifying a filter and then selecting the individual tags.

Open the "Action" select box to choose the desired bulk operation:

- Delete
- Delete unused tags - this will only delete the selected tags that are currently not assigned to any bookmark

Click the button next to the checkbox to execute the operation.

Note that deleting a tag does not affect the bookmarks that are tagged with this tag, it only removes the tag from those bookmarks.

---

## File: docs/src/content/docs/api.md

---
title: "API"
---

The application provides a REST API that can be used by 3rd party applications to manage bookmarks.

## Authentication

All requests against the API must be authorized using an authorization token. The application automatically generates an
API token for each user, which can be accessed through the *Settings* page.

The token needs to be passed as `Authorization` header in the HTTP request:

```
Authorization: Token <Token>
```

## Resources

The following resources are available:

### Bookmarks

**List**

```
GET /api/bookmarks/
```

List bookmarks.

Parameters:

- `q` - Filters results using a search phrase using the same logic as through the UI
- `limit` - Limits the max. number of results. Default is `100`.
- `offset` - Index from which to start returning results
- `modified_since` - Filter results to only include bookmarks modified after the specified date (format: ISO 8601, e.g. "2025-01-01T00:00:00Z")
- `added_since` - Filter results to only include bookmarks added after the specified date (format: ISO 8601, e.g. "2025-05-29T00:00:00Z")
- `bundle` - Filter results by bundle id to only include bookmarks matched by a given bundle

Example response:

```json
{
  "count": 123,
  "next": "http://127.0.0.1:8000/api/bookmarks/?limit=100&offset=100",
  "previous": null,
  "results": [
    {
      "id": 1,
      "url": "https://example.com",
      "title": "Example title",
      "description": "Example description",
      "notes": "Example notes",
      "web_archive_snapshot_url": "https://web.archive.org/web/20200926094623/https://example.com",
      "favicon_url": "http://127.0.0.1:8000/static/https_example_com.png",
      "preview_image_url": "http://127.0.0.1:8000/static/0ac5c53db923727765216a3a58e70522.jpg",
      "is_archived": false,
      "unread": false,
      "shared": false,
      "tag_names": [
        "tag1",
        "tag2"
      ],
      "date_added": "2020-09-26T09:46:23.006313Z",
      "date_modified": "2020-09-26T16:01:14.275335Z"
    },
    ...
  ]
}
```

**List Archived**

```
GET /api/bookmarks/archived/
```

List archived bookmarks.

Parameters and response are the same as for the regular list endpoint.

**Retrieve**

```
GET /api/bookmarks//
```

Retrieves a single bookmark by ID.

**Check**

```
GET /api/bookmarks/check/?url=https%3A%2F%2Fexample.com
```

Allows to check if a URL is already bookmarked. If the URL is already bookmarked, the `bookmark` property in the
response holds the bookmark data, otherwise it is `null`.

Also returns a `metadata` property that contains metadata scraped from the website. Finally, the `auto_tags` property
contains the tag names that would be automatically added when creating a bookmark for that URL.

Example response:

```json
{
  "bookmark": {
    "id": 1,
    "url": "https://example.com",
    "title": "Example title",
    "description": "Example description",
    ...
  },
  "metadata": {
    "title": "Scraped website title",
    "description": "Scraped website description",
    ...
  },
  "auto_tags": [
    "tag1",
    "tag2"
  ]
}
```

**Create**

```
POST /api/bookmarks/
```

Creates a new bookmark. Tags are simply assigned using their names. Including
`is_archived: true` saves a bookmark directly to the archive.

If the provided URL is already bookmarked, this silently updates the existing bookmark instead of creating a new one. If
you are implementing a user interface, consider notifying users about this behavior. You can use the `/check` endpoint
to check if a URL is already bookmarked and at the same time get the existing bookmark data. This behavior may change in
the future to return an error instead.

If the title and description are not provided or empty, the application automatically tries to scrape them from the
bookmarked website. This behavior can be disabled by adding the `disable_scraping` query parameter to the API request.

Example payload:

```json
{
  "url": "https://example.com",
  "title": "Example title",
  "description": "Example description",
  "notes": "Example notes",
  "is_archived": false,
  "unread": false,
  "shared": false,
  "tag_names": [
    "tag1",
    "tag2"
  ]
}
```

**Update**

```
PUT /api/bookmarks//
PATCH /api/bookmarks//
```

Updates a bookmark.
When using `PUT`, at least all required fields must be provided (currently only `url`).
When using `PATCH`, only the fields that should be updated need to be provided.
Regardless which method is used, any field that is not provided is not modified.
Tags are simply assigned using their names.

Note that [auto tagging](/auto-tagging) rules are applied on every update: tags from
matching rules are merged into `tag_names`, even if the request does not include that field.

If the provided URL is already bookmarked this returns an error.

Example payload:

```json
{
  "url": "https://example.com",
  "title": "Example title",
  "description": "Example description",
  "tag_names": [
    "tag1",
    "tag2"
  ]
}
```

**Archive**

```
POST /api/bookmarks//archive/
```

Archives a bookmark.

**Unarchive**

```
POST /api/bookmarks//unarchive/
```

Unarchives a bookmark.

**Delete**

```
DELETE /api/bookmarks//
```

Deletes a bookmark by ID.

### Bookmark Assets

**List**

```
GET /api/bookmarks//assets/
```

List assets for a specific bookmark.

Example response:

```json
{
  "count": 2,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": 1,
      "bookmark": 1,
      "asset_type": "snapshot",
      "date_created": "2023-10-01T12:00:00Z",
      "content_type": "text/html",
      "display_name": "HTML snapshot from 10/01/2023",
      "status": "complete"
    },
    {
      "id": 2,
      "bookmark": 1,
      "asset_type": "upload",
      "date_created": "2023-10-01T12:05:00Z",
      "content_type": "image/png",
      "display_name": "example.png",
      "status": "complete"
    }
  ]
}
```

**Retrieve**

```
GET /api/bookmarks//assets//
```

Retrieves a single asset by ID for a specific bookmark.

**Download**

```
GET /api/bookmarks//assets//download/
```

Downloads the asset file.

**Upload**

```
POST /api/bookmarks//assets/upload/
```

Uploads a new asset for a specific bookmark. The request must be a `multipart/form-data` request with a single part
named `file` containing the file to upload.

Example response:

```json
{
  "id": 3,
  "bookmark": 1,
  "asset_type": "upload",
  "date_created": "2023-10-01T12:10:00Z",
  "content_type": "application/pdf",
  "display_name": "example.pdf",
  "status": "complete"
}
```

**Delete**

```
DELETE /api/bookmarks//assets//
```

Deletes an asset by ID for a specific bookmark.

### Tags

**List**

```
GET /api/tags/
```

List tags.

Parameters:

- `limit` - Limits the max. number of results. Default is `100`.
- `offset` - Index from which to start returning results

Example response:

```json
{
  "count": 123,
  "next": "http://127.0.0.1:8000/api/tags/?limit=100&offset=100",
  "previous": null,
  "results": [
    {
      "id": 1,
      "name": "example",
      "date_added": "2020-09-26T09:46:23.006313Z"
    },
    ...
  ]
}
```

**Retrieve**

```
GET /api/tags//
```

Retrieves a single tag by ID.

**Create**

```
POST /api/tags/
```

Creates a new tag.

Example payload:

```json
{
  "name": "example"
}
```

**Delete**

```
DELETE /api/tags//
```

Deletes a tag by ID.

### Bundles

**List**

```
GET /api/bundles/
```

List bundles.

Parameters:

- `limit` - Limits the max. number of results. Default is `100`.
- `offset` - Index from which to start returning results

Example response:

```json
{
  "count": 3,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": 1,
      "name": "Work Resources",
      "search": "productivity tools",
      "any_tags": "work productivity",
      "all_tags": "",
      "excluded_tags": "personal",
      "order": 0,
      "date_created": "2020-09-26T09:46:23.006313Z",
      "date_modified": "2020-09-26T16:01:14.275335Z"
    },
    {
      "id": 2,
      "name": "Tech Articles",
      "search": "",
      "any_tags": "programming development",
      "all_tags": "",
      "excluded_tags": "outdated",
      "order": 1,
      "date_created": "2020-09-27T10:15:30.123456Z",
      "date_modified": "2020-09-27T10:15:30.123456Z"
    },
    ...
  ]
}
```

**Retrieve**

```
GET /api/bundles//
```

Retrieves a single bundle by ID.

**Create**

```
POST /api/bundles/
```

Creates a new bundle. If no `order` is specified, the bundle will be automatically assigned the next available order position.

Example payload:

```json
{
  "name": "My Bundle",
  "search": "search terms",
  "any_tags": "tag1 tag2",
  "all_tags": "required-tag",
  "excluded_tags": "excluded-tag",
  "order": 5
}
```

**Update**

```
PUT /api/bundles//
PATCH /api/bundles//
```

Updates a bundle.
When using `PUT`, all fields except read-only ones should be provided.
When using `PATCH`, only the fields that should be updated need to be provided.

Example payload:

```json
{
  "name": "Updated Bundle Name",
  "search": "updated search terms",
  "any_tags": "new-tag1 new-tag2",
  "order": 10
}
```

**Delete**

```
DELETE /api/bundles//
```

Deletes a bundle by ID.

### User

**Profile**

```
GET /api/user/profile/
```

User preferences.

Example response:

```json
{
  "theme": "auto",
  "bookmark_date_display": "relative",
  "bookmark_link_target": "_blank",
  "web_archive_integration": "enabled",
  "tag_search": "lax",
  "enable_sharing": true,
  "enable_public_sharing": true,
  "enable_favicons": false,
  "display_url": false,
  "permanent_notes": false,
  "search_preferences": {
    "sort": "title_asc",
    "shared": "off",
    "unread": "off"
  }
}
```

---

## File: docs/src/content/docs/archiving.md

---
title: "Archiving"
---

Linkding allows to archive bookmarked web pages as HTML files. This can be useful to preserve the content of a web page in case it goes offline or its content changes. The sections below explain different methods to archive web pages and store them in linkding.

## Server-based Archiving

Linkding can automatically create HTML snapshots whenever a bookmark is added. This feature is only available in the `latest-plus` Docker image (see [Installation](/installation#using-docker)), and is automatically active when using that image.

The snapshots are created using [singlefile-cli](https://github.com/gildas-lormeau/single-file-cli), which effectively runs a headless Chromium instance on the server to convert the web page into a single HTML file. Linkding will also load the [uBlock Origin Lite extension](https://github.com/uBlockOrigin/uBOL-home) into Chromium to attempt to block ads and other unwanted content.

When bookmarking a URL that points directly to a PDF file, linkding will download the PDF instead of creating an HTML snapshot. This happens automatically based on the content type of the URL, and the downloaded PDF will be stored as an asset alongside the bookmark, just like HTML snapshots.

This method is fairly easy to set up, but also has several downsides:
- The Docker image is significantly larger than the base image, as it includes a Chromium installation.
- Running Chromium requires significantly more memory, at least 1 GB of RAM.
- The Docker image is not available for ARM v7 platforms.
- Creating snapshots from a headless browser is not always reliable, for example:
  - It may trigger anti-bot measures on the website.
  - Websites that require login will not show the same content you would see in your browser.

Read on for alternative methods to archive web pages directly from your browser, which do not require the `latest-plus` Docker image and will save the web page exactly as you see it in your browser.

## Using the Singlefile Browser Extension

[Singlefile](https://github.com/gildas-lormeau/SingleFile) is a popular browser extension for saving a web page as a single HTML file. By default, the extension saves the file to your local disk, but it can also be configured to send the file to a REST API endpoint. Linkding provides a REST API endpoint for this purpose.

To use the Singlefile extension with linkding, follow these steps:
- Install the [Singlefile extension](https://github.com/gildas-lormeau/SingleFile) in your browser
- Open the extension's settings
- Under `Destination`, select `upload to a REST Form API`
- Under `URL` enter the URL of your linkding installation, followed by `/api/bookmarks/singlefile/` (e.g. `https://linkding.example.com/api/bookmarks/singlefile/`)
- Under `authorization token`, enter the REST API token that you can get from your linkding settings page
- Under `data field name` enter `file`
- Under `URL field name` enter `url`

Now, when you click the Singlefile extension icon, the web page will be saved as a single HTML file and uploaded to your linkding installation.
Note that if a bookmark for that URL does not exist, linkding will automatically create a new bookmark. If a bookmark already exists, the snapshot will be added to the existing bookmark.

Using this method has some downsides, in that you can not provide any additional metadata to the bookmark, such as tags or a description. Read on for how to use the linkding extension directly to create bookmarks with metadata and run the Singlefile extension.

## Using the linkding Browser Extension

The linkding extension allows you to quickly add bookmarks from your browser. It can also integrate with the Singlefile extension to automatically create a snapshot of the web page when adding a bookmark.

To integrate with the Singlefile extension, follow these steps:
- First, install and configure the Singlefile extension as described above so that it uploads files to your linkding installation
- Open the linkding extension settings
- Enable the `Run Singlefile after adding new bookmark` option
- Save the settings

Now, when you add a bookmark through the linkding extension, it will automatically trigger the Singlefile extension to create a snapshot of the web page, which will then be uploaded to your linkding installation and stored under the newly added bookmark.

Note that when the option is enabled, linkding will not attempt to create an HTML snapshot on the server, even if you are using the `latest-plus` Docker image. The linkding extension will not trigger Singlefile when updating an existing bookmark. If you want to create a new snapshot for an existing bookmark, you can do so manually by clicking the Singlefile extension icon.

### Extension Store Compatibility

The linkding and Singlefile extensions communicate using store-specific extension IDs. For the integration to work, both extensions must be installed from the same browser extension store. For example:
- If you install linkding from the Chrome Web Store, install Singlefile from the Chrome Web Store as well
- If you install linkding from Firefox Add-ons, install Singlefile from Firefox Add-ons as well

This is particularly relevant for Microsoft Edge users, as Edge can install extensions from both the Chrome Web Store and the Microsoft Edge Add-ons store. If the extensions are installed from different stores, the automatic Singlefile integration will not work.

---

## File: docs/src/content/docs/auto-tagging.md

---
title: "Auto tagging"
---

Auto tagging allows to automatically add tags to bookmarks based on predefined rules. This makes categorizing commonly
bookmarked websites easier and faster.

Auto tagging rules can be defined in the profile settings. Each rule maps a URL pattern to one or more tags. For
example:

```
youtube.com video
reddit.com/r/Music music reddit
```

When a bookmark is created or updated, the URL of the bookmark is parsed to extract the hostname, path, query
string and fragment. These components are then compared against the patterns defined in the auto tagging rules. If all components
match, the tags associated with the rule are added to the bookmark. Both the bookmark form in the web interface and the
browser extension will show a preview of the tags that will be added based on the auto tagging rules.

The URL matching works like this:

- **Hostname Matching**: The hostname of the bookmark URL is compared to the hostname in the rule. If the rule does not
  specify a subdomain, it matches all subdomains. For example, a rule with `youtube.com` will match both
  `www.youtube.com` and `m.youtube.com`. If a subdomain is specified in the rule, it will only match that subdomain. For
  example, a rule with `gist.github.com` will only match `gist.github.com`.
- **Path Matching**: The path of the bookmark URL is compared to the path in the rule. If the rule does not specify a
  path, it matches all paths. For example, a rule with `reddit.com` will match `reddit.com/r/music`,
  `reddit.com/r/gaming`, etc. If a path is specified in the rule, it will only match that path and all its subpaths. For
  example, a rule with `reddit.com/r/music` will match `reddit.com/r/music`, `reddit.com/r/music/new`, etc.
- **Query String Matching**: The query string parameters of the bookmark URL are compared to those in the rule. If the
  rule does not specify any query string parameters, it matches all query strings. If the rule specifies a query string
  it will only match if the bookmark URL contains all the specified query string parameters with their respective
  values.
- **Fragment Matching**: The URL fragment (part after the # symbol) is also compared when present in a rule. If the rule
  specifies a fragment, it will match any URL whose fragment starts with the specified fragment. For example, a rule with
  `example.com/#/projects` will match URLs like `example.com/#/projects/123` or `example.com/#/projects/456`.

Note that URL matching currently does not support any kind of wildcards. Rule matching only works based on the URL, not
on the content of the website or any other aspect of the bookmark.

## Example

Consider the following auto tagging rule:

```
reddit.com/r/Music music reddit
```

When adding a bookmark for a URL like `https://www.reddit.com/r/Music/comments/...`, the auto tagging mechanism will:

1. Parse the URL to extract the hostname (`www.reddit.com`), path (`/r/Music/comments/...`), and query string (none).
2. Match the hostname against the pattern. The domain `reddit.com` matches. Since the rule does not specify a subdomain,
   it also matches `www.reddit.com`.
3. Match the path against the pattern. The path `/r/Music` also matches the nested path `/r/Music/comments/...`.
4. Match the query string. Since the rule does not specify a query string, it matches all query strings.
5. The tags `music` and `reddit` will be added to the bookmark.

---

## File: docs/src/content/docs/backups.md

---
title: "Backups"
---

Linkding stores all data in the application's data folder.
The full path to that folder in the Docker container is `/etc/linkding/data`.
As described in the installation docs, you should mount the `/etc/linkding/data` folder to a folder on your host system.

The data folder contains the following contents that are relevant for backups:
- `db.sqlite3` - the SQLite database
- `assets` - folder that contains HTML snapshots of bookmarks
- `favicons` - folder that contains downloaded favicons
- `previews` - folder that contains downloaded preview images

The following sections explain how to back up the individual contents.

## Full backup

linkding provides a CLI command to create a full backup of the data folder. This creates a zip file that contains backups of the database, assets, favicons, and preview images.

:::note
This method assumes that you are using the default SQLite database.
If you are using a different database, such as Postgres, you'll have to back up the database and other contents of the data folder manually.
:::

To create a full backup, execute the following command:
```shell
docker exec -it linkding python manage.py full_backup /etc/linkding/data/backup.zip
```
This creates a `backup.zip` file in the Docker container under `/etc/linkding/data`.

To copy the backup file to your host system, execute the following command:
```shell
docker cp linkding:/etc/linkding/data/backup.zip backup.zip
```
This copies the backup file from the Docker container to the current folder on your host system.
Now you can move that file to your backup location.

To restore a backup: 
- Extract the zip file in a folder of your new installation.
- Rename the extracted folder to `data`.
- When starting the Docker container, mount that folder to `/etc/linkding/data` as explained in the README.
- Then start the Docker container.

## Alternative backup methods

If you can't use the full backup method, this section describes alternatives how to back up the individual contents of the data folder.

### SQLite database backup

linkding includes a CLI command for creating a backup copy of the database.

:::caution
While the SQLite database is just a single file, it is not recommended to just copy that file.
This method is not transaction safe and may result in a [corrupted database](https://www.sqlite.org/howtocorrupt.html).
Use one of the backup methods described below.
:::

:::caution
This method is deprecated and may be removed in the future.
Please use the full backup method described above.
:::

To create a backup, execute the following command:
```shell
docker exec -it linkding python manage.py backup /etc/linkding/data/backup.sqlite3
```
This creates a `backup.sqlite3` file in the Docker container under `/etc/linkding/data`.

To copy the backup file to your host system, execute the following command:
```shell
docker cp linkding:/etc/linkding/data/backup.sqlite3 backup.sqlite3
```
This copies the backup file from the Docker container to the current folder on your host system.
Now you can move that file to your backup location.

To restore the backup, just copy the backup file to the data folder of your new installation and rename it to `db.sqlite3`. Then start the Docker container.

### SQLite database SQL dump

Requires [SQLite](https://www.sqlite.org/index.html) to be installed on your host system.

With this method you create a plain text file with the SQL statements to recreate the SQLite database.
To create a backup, execute the following command in the data folder on your host system:
```shell
sqlite3 db.sqlite3 .dump > backup.sql
```
This creates a `backup.sql` which you can copy to your backup location.
As this is a plain text file you can also commit it to any revision management system, like git.
Using git, you can commit the changes, followed by a git push to a remote repository.

### Exporting bookmarks from the UI

This is the least technical option to back up bookmarks, but has several limitations:
- It does not export user profiles.
- It only exports your own bookmarks, not those of other users.
- It does not export URLs of snapshots on the Internet Archive Wayback machine.
- It does not export HTML snapshots of bookmarks. Even if you backup and restore the assets folder, the bookmarks will not be linked to the snapshots anymore.
- It does not export favicons or preview images.

Only use this method if you are fine with the above limitations.

To export bookmarks from the UI, open the general settings.
In the Export section, click on the *Download* button to download an HTML file containing all your bookmarks.
Then move that file to your backup location.

To restore bookmarks, open the general settings on your new installation.
In the Import section, click on the *Choose file* button to select the HTML file you downloaded before.
Then click on the *Import* button to import the bookmarks.

### Assets

If you are using the HTML snapshots feature, you should also do backups of the `assets` folder.
It contains the HTML snapshots files of your bookmarks which are referenced from the database.

To back up the assets, then you have to copy the `assets` folder to your backup location.

To restore the assets, copy the `assets` folder back to the data folder of your new installation.

### Favicons

Doing a backup of the icons is optional, as they can be downloaded again.

If you choose not to back up the icons, you can just restore the database and then click the _Refresh Favicons_ button in the general settings.
This will download all missing icons again.

If you want to back up the icons, then you have to copy the `favicons` folder to your backup location.

To restore the icons, copy the `favicons` folder back to the data folder of your new installation.

---

## File: docs/src/content/docs/browser-extension.md

---
title: "Browser Extension"
---

linkding comes with an official browser extension that allows to quickly add bookmarks, and search bookmarks through the browser's address bar. You can get the extension here:
- [Mozilla Addon Store](https://addons.mozilla.org/firefox/addon/linkding-extension/)
- [Chrome Web Store](https://chrome.google.com/webstore/detail/linkding-extension/beakmhbijpdhipnjhnclmhgjlddhidpe)

The extension is open-source as well, and can be found [here](https://github.com/sissbruecker/linkding-extension).

---

## File: docs/src/content/docs/community.md

---
title: "Community"
---

This section lists community projects around using linkding. If you have a project that you want to share with the linkding community, feel free to [submit a PR](https://github.com/sissbruecker/linkding/edit/master/docs/src/content/docs/community.md) to add your project to this section.

## Mobile and Desktop Apps

| Name | Description | Author |
| ---- | ----------- | ------ |
| [cosmicding](https://github.com/vkhitrin/cosmicding) | Desktop client built using [libcosmic](https://github.com/pop-os/libcosmic). | [vkhitrin](https://github.com/vkhitrin) |
| [LinkBuddy](https://github.com/peterto/LinkBuddy) | An open-source Android and iOS client for linkding, written in React Native. Android apk available on [github](https://github.com/peterto/LinkBuddy/releases) and iOS version on [Apple AppStore](https://apps.apple.com/us/app/linkbuddy-for-linkding/id6740408952). | [peterto](https://github.com/peterto) |
| [Linkdy](https://github.com/JGeek00/linkdy) | An open-source Android and iOS client created with Flutter. Available on the [Google Play Store](https://play.google.com/store/apps/details?id=com.jgeek00.linkdy) and [App Store](https://apps.apple.com/us/app/linkdy/id6479930976). | [JGeek00](https://github.com/JGeek00) |
| [Linklater](https://github.com/danielyrovas/linklater) | An open-source Android client written in Kotlin. | [danielyrovas](https://github.com/danielyrovas) |
| [LinkThing](https://apps.apple.com/us/app/linkthing/id1666031776) | An iOS client for linkding. | [amoscardino](https://github.com/amoscardino) |
| [Pinkt](https://github.com/fibelatti/pinboard-kotlin) | An Android client for linkding. | [fibelatti](https://github.com/fibelatti) |
| [Ribbon](https://apps.apple.com/us/app/ribbon-a-linkding-client/id6762416055) | A native iOS client for linkding | [cdransf](https://github.com/cdransf) |
| [Save to Linkding](https://www.giuliomagnifico.dev/apps/savetolinkding/) | Save links from any browser on iOS or iPadOS using the system Share Sheet, and manage your instance using the main app. [App Store](https://apps.apple.com/app/save-to-linkding/id6761113021) | [Giulio Magnifico](https://www.giuliomagnifico.dev) |
| [Tsundoku](https://www.gingerbeardman.com/apps/tsundoku/) | macOS client for linkding and other bookmark managers. | [gingerbeardman](https://blog.gingerbeardman.com/2026/04/17/today-i-shipped-twenty-apps-and-a-screensaver/) |

## Browser Extensions

| Name | Description | Author |
| ---- | ----------- | ------ |
| [linkding-extension](https://github.com/jeroenpardon/linkding-extension) | An alternative to the official browser extension that wraps the linkding bookmarklet. | [jeroenpardon](https://github.com/jeroenpardon) |
| [linkding-injector](https://github.com/Fivefold/linkding-injector) | Injects search results from linkding into the sidebar of search pages like google and duckduckgo. | [Fivefold](https://github.com/Fivefold) |
| [linkding for Safari](https://github.com/phmagic/linkding-safari) | Free browser extension for saving and searching bookmarks in Safari | [phmagic](https://github.com/phmagic) |

## Web and CLI Apps

| Name | Description | Author |
| ---- | ----------- | ------ |
| [DingDrop](https://github.com/marb08/DingDrop) | A Telegram bot that allows you to quickly save bookmarks to your Linkding instance via Telegram using Linkding APIs. | [marb08](https://github.com/marb08) |
| [feed2linkding](https://codeberg.org/strubbl/feed2linkding) | A commandline utility to add all web feed item links to linkding via API call. | [Strubbl](https://github.com/Strubbl) |
| [Komrade](https://codeberg.org/kodemonaut/komrade) | A simple docker based startpage/dashboard which syncs with Linkding, Linkwarden or Nextcloud Bookmarks. | [kodemonaut](https://codeberg.org/kodemonaut) |
| [Linka!](https://github.com/cmsax/linka) | Web app (also a PWA) for quickly searching & opening bookmarks in linkding, support multi keywords, exclude mode and other advance options. | [cmsax](https://github.com/cmsax) |
| [linkding-archiver](https://github.com/sebw/linkding-archiver) | A Python application that integrates with SingleFile and Tube Archivist to archive your links and videos. | [sebw](https://github.com/sebw) |
| [linkding-bot](https://github.com/mesamirh/linkding-bot) | A Telegram bot for linkding that automatically generates tags and notes using AI. | [mesamirh](https://github.com/mesamirh) |
| [linkding-cleanup](https://github.com/andrewferrier/dotfiles/blob/main/stow/common/.local/bin/common-dotfiles/linkding-clean) | A Python script which validates if bookmarks are still valid (reachable), archiving and unarchiving appropriately, as well as cleaning broken bookmark titles | [andrewferrier](https://github.com/andrewferrier) |
| [linkding-cli](https://github.com/bachya/linkding-cli) | A command-line interface (CLI) to interact with the linkding REST API. Powered by [aiolinkding](https://github.com/bachya/aiolinkding). | [bachya](https://github.com/bachya) |
| [linkdinger](https://github.com/lmmendes/linkdinger) | A Telegram bot that saves links directly to Linkding, with support for tags, notes, and searching bookmarks. | [lmmendes](https://github.com/lmmendes) |
| [linkding-healthcheck](https://github.com/sebw/linkding-healthcheck) | A Go application that checks the health of your bookmarks and add a tag on dead and problematic URLs. | [sebw](https://github.com/sebw) |
| [linkding-media-archiver](https://github.com/proog/linkding-media-archiver) | Automatically downloads media files for your bookmarks with yt-dlp and makes them available within Linkding. | [proog](https://github.com/proog) |
| [linkding-reminder](https://github.com/sebw/linkding-reminder) | A Python application that will send an email reminder for links with a specific tag. | [sebw](https://github.com/sebw) |
| [linktiles](https://github.com/haondt/linktiles) | A web app that displays your links as tiles in a configurable mosaic. | [haondt](https://github.com/haondt) |
| [Pocket2Linkding](https://github.com/hkclark/Pocket2Linkding/) | A tool to migrate from Mozilla Pocket to linkding. Preserves the date the link was added to pocket and any tags. | [hkclark](https://github.com/hkclark) |
| [serchding](https://github.com/ldwgchen/serchding) | Full-text search for linkding. | [ldwgchen](https://github.com/ldwgchen) |

## Utilities

| Name | Description | Author |
| ---- | ----------- | ------ |
| [alfred-linkding-bookmarks](https://github.com/firefingers21/alfred-linkding-bookmarks) | An Alfred workflow for searching and opening linkding bookmarks. | [FireFingers21](https://github.com/FireFingers21) |
| [Helm Chart](https://charts.pascaliske.dev/charts/linkding/) | Helm Chart for deploying linkding inside a Kubernetes cluster. | [pascaliske](https://github.com/pascaliske) |
| [iOS Shortcut using API and Tagging](https://gist.github.com/andrewdolphin/a7dff49505e588d940bec55132fab8ad) | An iOS shortcut using the Linkding API (no extra logins required) that pulls previously used tags and allows tagging at the time of link creation. | [andrewdolphin](https://github.com/andrewdolphin) |
| [iOS Shortcut and workflow](https://joshdick.net/2025/01/23/how_i_use_linkding_on_ios.html) | iOS shortcut that accepts URLs in various ways, and shows a corresponding Linkding add/edit webview in a modal popup. | [joshdick](https://joshdick.net) |
| [k8s + s3](https://github.com/jzck/linkding-k8s-s3) | Setup for hosting stateless linkding on k8s with sqlite replicated to s3. | [jzck](https://github.com/jzck) |
| [Open all links bookmarklet](https://gist.github.com/ukcuddlyguy/336dd7339e6d35fc64a75ccfc9323c66) | A browser bookmarklet to open all links on the current Linkding page in new tabs. | [ukcuddlyguy](https://github.com/ukcuddlyguy) |
| [Postman collection](https://gist.github.com/gingerbeardman/f0b42502f3bc9344e92ce63afd4360d3) | A group of saved request templates for API testing. | [gingerbeardman](https://github.com/gingerbeardman) |

## Libraries

| Name | Description | Author |
| ---- | ----------- | ------ |
| [aiolinkding](https://github.com/bachya/aiolinkding) | A Python3, async library to interact with the linkding REST API. | [bachya](https://github.com/bachya) |
| [go-linkding](https://github.com/piero-vic/go-linkding) | A Go client library to interact with the linkding REST API. | [piero-vic](https://github.com/piero-vic) |
| [linkding-api](https://github.com/vbsampath/linkding-api) | A Javascript library implementing linkding REST API. | [vbsampath](https://github.com/vbsampath) |
| [linkding-rs](https://github.com/zbrox/linkding-rs) | A Rust client library to interact with the linkding REST API with cross platform support to be easily used in Android or iOS apps. | [zbrox](https://github.com/zbrox) |

## Self-Hosting Guides

| Name | Description | Author |
| ---- | ----------- | ------ |
| [linkding on fly.io](https://github.com/fspoettel/linkding-on-fly) | Guide for hosting a linkding installation on [fly.io](https://fly.io). | [fspoettel](https://github.com/fspoettel) |
| [linkding on railway.app](https://github.com/tianheg/linkding-on-railway) | Guide for hosting a linkding installation on [railway.app](https://railway.app/). | [tianheg](https://github.com/tianheg) |

---

## File: docs/src/content/docs/how-to.md

---
title: "How to"
---

Collection of tips and tricks around using linkding.

## Using the bookmarklet on Android/Chrome

This how-to explains the usage of the standard linkding bookmarklet on Android / Chrome. 

Chrome on Android does not permit running bookmarklets in the same way you can on a desktop system. There is however a workaround that is explained here.

**Note** that this only works with Chrome and not with other browsers on Android.

Create a bookmark of your linkding deployment by clicking the star icon which you find in the three dots menu in the top right. Next you have to edit the bookmark. Edit the URL and replace it it with the bookmarklet code of your instance and give it an easy to type name like `bm` for bookmark or `ld` for linkding:

```
javascript:window.open(`http://<YOUR_INSTANCE_HERE>/bookmarks/new?url=${encodeURIComponent(window.location)}&auto_close`)
```

Now when you are browsing the web and you want to save the current page as a bookmark to your linkding instance simply type `bm` into the address bar and select it from the results. The bookmarklet code will trigger and you will be redirected so save the current page.

For more info see here: https://paul.kinlan.me/use-bookmarklets-on-chrome-on-android/

## Using the PWA (Progressive Web App) to save links using the native share sheet on Android

 - Visit your instance in Chrome (works best) or another Chromium-based web browser.
 - A popup should appear (first time only) prompting you to install Linkding as an app. If it doesn't, tap the 3-dot menu then tap "Add to Home screen", then tap "Install".
 - Linkding will now show up in Android's native share sheet. Share a link from any app or browser and tap Linkding to save a link.
 - Optional: when the share sheet is displayed, tap and hold Linkding, then tap "Pin" to pin it to the top.

## Using HTTP Shortcuts app on Android

**Note** This allows you to share URL from any app to tag and bookmark it to linkding

- Install HTTP Shortcuts from [Play Store](https://play.google.com/store/apps/details?id=ch.rmy.android.http_shortcuts) or [F-Droid](https://f-droid.org/en/packages/ch.rmy.android.http_shortcuts/).

- Copy the URL of [linkding_shortcut.json](https://raw.githubusercontent.com/sissbruecker/linkding/master/docs/src/assets/linkding_shortcut.json).

- Open HTTP Shortcuts, tap the 3-dot-button at the top-right corner, tap `Import/Export`, then tap `Import from URL`.

- Paste the URL you copied earlier, tap OK, go back, tap the 3-dot-button again, then tap `Variables`.

- Edit the `values` of `linkding_instance` and `linkding_api_key`.

Try using share button on an app, a new item `Send to...` should appear on the share sheet. You can also manually share by tapping the shortcut inside the HTTP Shortcuts app itself.

## Create a share action on iOS for adding bookmarks to linkding

This how-to explains how to make use of the app shortcuts iOS app to create a share action that can be used in Safari for adding bookmarks to your linkding instance.

To install the shortcut:
- Download the [Shortcut](https://raw.githubusercontent.com/sissbruecker/linkding/master/docs/src/assets/Add%20To%20Linkding.shortcut) on your iOS device
- Tap the downloaded file, which brings up the Shortcuts app
- Confirm that you want to add the shortcut
- In the shortcut, change `https://linkding.mydomain.com` to the URL of your linkding instance
- Confirm / close the shortcut

To use the shortcut:
- Open Safari and navigate to the page you want to bookmark
- Tap the share button
- Scroll down and tap "Add To Linkding"
- This opens linkding in a Safari overlay where you can configure the bookmark
- When you're done, tap "Save"
- After the bookmark is saved you can close the overlay

At the bottom of the share sheet there is a button for configuring share actions. You can use this to move the "Add To Linkding" action to the top of the share sheet if you like.

:::note
You can also check the [Community section](/community) for other pre-made shortcuts that you can use.
:::

## Increase the font size

The font size can be adjusted globally by adding the following CSS to the custom CSS field in the settings:

```css
:root {
  --font-size: 0.75rem;
  --font-size-sm: 0.7rem;
  --font-size-lg: 0.9rem;
}

.bookmark-list {
  line-height: 1.15rem;
}

.tag-cloud {
  line-height: 1.15rem;
}
```

You can adjust the `--font-size`, `--font-size-sm` and `--font-size-lg` variables to your liking.
Note that increasing the font might also require you to adjust the line-height in certain places to better separate texts from each other.
As an example, the above also increases the font size and line height of the bookmark list and tag cloud.