# Technical Documentation: go-shiori/shiori
> ℹ️ **Provenance:** Hybrid Fusion: `go-shiori/shiori` (README + 10 In-Tree Chapters) · [CodeWiki Reference](https://codewiki.google/github.com/go-shiori/shiori) · Recency: Active (< 180 days)
## 1. Project Overview & Quickstart (go-shiori/shiori)
# Shiori
[](https://github.com/go-shiori/shiori/actions/workflows/push.yml)
[](https://goreportcard.com/report/github.com/go-shiori/shiori)
[](https://matrix.to/#/#shiori:matrix.org)
[](https://github.com/go-shiori/shiori/pkgs/container/shiori)
**Check out our latest [Announcements](https://github.com/go-shiori/shiori/discussions/categories/announcements)**
Shiori is a simple bookmarks manager written in the Go language. Intended as a simple clone of [Pocket][pocket]. You can use it as a command line application or as a web application. This application is distributed as a single binary, which means it can be installed and used easily.
![Screenshot][screenshot]
## Features
- Basic bookmarks management i.e. add, edit, delete and search.
- Import and export bookmarks from and to Netscape Bookmark file.
- Import bookmarks from Pocket.
- Simple and clean command line interface.
- Simple and pretty web interface for those who don't want to use a command line app.
- Portable, thanks to its single binary format.
- Support for sqlite3, PostgreSQL, MariaDB and MySQL as its database.
- Where possible, by default `shiori` will parse the readable content and create an offline archive of the webpage.
- [BETA] [web extension][web-extension] support for Firefox and Chrome.
![Comparison of reader mode and archive mode][mode-comparison]
## Documentation
All documentation is available in the [docs folder][documentation]. If you think there is incomplete or incorrect information, feel free to edit it by submitting a pull request.
## License
Shiori is distributed under the terms of the [MIT license][mit], which means you can use it and modify it however you want. However, if you make an enhancement for it, if possible, please send a pull request.
[documentation]: https://github.com/go-shiori/shiori/blob/master/docs/index.md
[mit]: https://choosealicense.com/licenses/mit/
[web-extension]: https://github.com/go-shiori/shiori-web-ext
[screenshot]: https://raw.githubusercontent.com/go-shiori/shiori/master/docs/assets/screenshots/cover.png
[mode-comparison]: https://raw.githubusercontent.com/go-shiori/shiori/master/docs/assets/screenshots/comparison.png
[pocket]: https://getpocket.com/
[256]: https://github.com/go-shiori/shiori/issues/256
## 2. In-Tree Documentation Chapters (go-shiori/shiori)
## File: README.md
# Shiori
[](https://github.com/go-shiori/shiori/actions/workflows/push.yml)
[](https://goreportcard.com/report/github.com/go-shiori/shiori)
[](https://matrix.to/#/#shiori:matrix.org)
[](https://github.com/go-shiori/shiori/pkgs/container/shiori)
**Check out our latest [Announcements](https://github.com/go-shiori/shiori/discussions/categories/announcements)**
Shiori is a simple bookmarks manager written in the Go language. Intended as a simple clone of [Pocket][pocket]. You can use it as a command line application or as a web application. This application is distributed as a single binary, which means it can be installed and used easily.
![Screenshot][screenshot]
## Features
- Basic bookmarks management i.e. add, edit, delete and search.
- Import and export bookmarks from and to Netscape Bookmark file.
- Import bookmarks from Pocket.
- Simple and clean command line interface.
- Simple and pretty web interface for those who don't want to use a command line app.
- Portable, thanks to its single binary format.
- Support for sqlite3, PostgreSQL, MariaDB and MySQL as its database.
- Where possible, by default `shiori` will parse the readable content and create an offline archive of the webpage.
- [BETA] [web extension][web-extension] support for Firefox and Chrome.
![Comparison of reader mode and archive mode][mode-comparison]
## Documentation
All documentation is available in the [docs folder][documentation]. If you think there is incomplete or incorrect information, feel free to edit it by submitting a pull request.
## License
Shiori is distributed under the terms of the [MIT license][mit], which means you can use it and modify it however you want. However, if you make an enhancement for it, if possible, please send a pull request.
[documentation]: https://github.com/go-shiori/shiori/blob/master/docs/index.md
[mit]: https://choosealicense.com/licenses/mit/
[web-extension]: https://github.com/go-shiori/shiori-web-ext
[screenshot]: https://raw.githubusercontent.com/go-shiori/shiori/master/docs/assets/screenshots/cover.png
[mode-comparison]: https://raw.githubusercontent.com/go-shiori/shiori/master/docs/assets/screenshots/comparison.png
[pocket]: https://getpocket.com/
[256]: https://github.com/go-shiori/shiori/issues/256
---
## File: docs/API.md
This is a brief explanation of Shiori's API. For more examples you can import this [collection](https://github.com/go-shiori/shiori/blob/master/docs/postman/shiori.postman_collection.json) in Postman.
> ⚠️ **This is the documentation for the old API. This API is deprecated and will be removed in the future. Please refer and start migrating to the [API v1](./APIv1.md) instead.**
- [Auth](#auth)
- [Log in](#log-in)
- [Log out](#log-out)
- [Bookmarks](#bookmarks)
- [Get bookmarks](#get-bookmarks)
- [Add bookmark](#add-bookmark)
- [Edit bookmark](#edit-bookmark)
- [Delete bookmark](#delete-bookmark)
- [Tags](#tags)
- [Get tags](#get-tags)
- [Rename tag](#rename-tag)
- [Accounts](#accounts)
- [List accounts](#list-accounts)
- [Create account](#create-account)
- [Edit account](#edit-account)
- [Delete accounts](#delete-accounts)
# Auth
## Log in
Most actions require a session id. For that, you'll need to log in using your username and password.
|Request info|Value|
|-|-|
|Endpoint|`/api/login`|
|Method|`POST`|
Body:
```json
{
"username": "shiori",
"password": "gopher",
"remember": true,
"owner": true
}
```
It will return your session ID in a JSON:
```json
{
"session": "YOUR_SESSION_ID",
"account": {
"id": 1,
"username": "shiori",
"owner": true
}
}
```
## Log out
Log out of a session ID.
|Request info|Value|
|-|-|
|Endpoint|`/api/logout`|
|Method|`POST`|
|`X-Session-Id` Header|`sessionId`|
# Bookmarks
## Get bookmarks
Gets the last 30 bookmarks (last page).
|Request info|Value|
|-|-|
|Endpoint|`/api/bookmarks`|
|Method|`GET`|
|`X-Session-Id` Header|`sessionId`|
Returns:
```json
{
"bookmarks": [
{
"id": 825,
"url": "https://interesting_cool_article.com",
"title": "Cool Interesting Article",
"excerpt": "An interesting and cool article indeed!",
"author": "",
"public": 0,
"modified": "2020-12-06 00:00:00",
"imageURL": "",
"hasContent": true,
"hasArchive": true,
"tags": [
{
"id": 7,
"name": "TAG"
}
],
"createArchive": false
},
],
"maxPage": 19,
"page": 1
}
```
## Add bookmark
Add a bookmark. For some reason, Shiori ignores the provided title and excerpt, and instead fetches them automatically. Note the tag format, a regular JSON list will result in an error.
|Request info|Value|
|-|-|
|Endpoint|`/api/bookmarks`|
|Method|`POST`|
|`X-Session-Id` Header|`sessionId`|
Body:
```json
{
"url": "https://interesting_cool_article.com",
"createArchive": true,
"public": 1,
"tags": [{"name": "Interesting"}, {"name": "Cool"}],
"title": "Cool Interesting Article",
"excerpt": "An interesting and cool article indeed!"
}
```
Returns:
```json
{
"id": 827,
"url": "https://interesting_cool_article.com",
"title": "TITLE",
"excerpt": "EXCERPT",
"author": "AUTHOR",
"public": 1,
"modified": "DATE",
"html": "HTML",
"imageURL": "/bookmark/827/thumb",
"hasContent": false,
"hasArchive": true,
"tags": [
{
"name": "Interesting"
},
{
"name": "Cool"
}
],
"createArchive": true
}
```
## Edit bookmark
Modifies a bookmark, by ID.
|Request info|Value|
|-|-|
|Endpoint|`/api/bookmarks`|
|Method|`PUT`|
|`X-Session-Id` Header|`sessionId`|
Body:
```json
{
"id": 3,
"url": "https://interesting_cool_article.com",
"title": "Cool Interesting Article",
"excerpt": "An interesting and cool article indeed!",
"author": "AUTHOR",
"public": 1,
"modified": "2019-09-22 00:00:00",
"imageURL": "/bookmark/3/thumb",
"hasContent": false,
"hasArchive": false,
"tags": [],
"createArchive": false
}
```
After providing the ID, provide the modified fields. The syntax is the same as [adding](#Add-a-bookmark).
## Delete bookmark
Deletes a list of bookmarks, by their IDs.
|Request info|Value|
|-|-|
|Endpoint|`/api/bookmarks`|
|Method|`DEL`|
|`X-Session-Id` Header|`sessionId`|
Body:
```json
[1, 2, 3]
```
# Tags
## Get tags
Gets the list of tags, their IDs and the number of entries that have those tags.
|Request info|Value|
|-|-|
|Endpoint|`/api/tags`|
|Method|`GET`|
|`X-Session-Id` Header|`sessionId`|
Returns:
```json
[
{
"id": 1,
"name": "Cool",
"nBookmarks": 1
},
{
"id": 2,
"name": "Interesting",
"nBookmarks": 1
}
```
## Rename tag
Renames a tag, provided its ID.
|Request info|Value|
|-|-|
|Endpoint|`/api/tags`|
|Method|`PUT`|
|`X-Session-Id` Header|`sessionId`|
Body:
```json
{
"id": 1,
"name": "TAG_NEW_NAME"
}
```
# Accounts
## List accounts
Gets the list of all user accounts, their IDs, and whether or not they are owners.
|Request info|Value|
|-|-|
|Endpoint|`/api/accounts`|
|Method|`GET`|
|`X-Session-Id` Header|`sessionId`|
Returns:
```json
[
{
"id": 1,
"username": "shiori",
"owner": true
}
]
```
## Create account
Creates a new user.
|Request info|Value|
|-|-|
|Endpoint|`/api/accounts`|
|Method|`POST`|
|`X-Session-Id` Header|`sessionId`|
Body:
```json
{
"username": "shiori2",
"password": "gopher",
"owner": false
}
```
## Edit account
Changes an account's password or owner status.
|Request info|Value|
|-|-|
|Endpoint|`/api/accounts`|
|Method|`PUT`|
|`X-Session-Id` Header|`sessionId`|
Body:
```json
{
"username": "shiori",
"oldPassword": "gopher",
"newPassword": "gopher",
"owner": true
}
```
## Delete accounts
Deletes a list of users.
|Request info|Value|
|-|-|
|Endpoint|`/api/accounts`|
|Method|`DEL`|
|`X-Session-Id` Header|`sessionId`|
Body:
```json
["shiori", "shiori2"]
```
---
## File: docs/APIv1.md
# API v1
> ℹ️ **This is the documentation for the new API. This API is still in development and though the finished endpoints should not change please consider that breaking changes may occur once its properly released. If you are looking for the current API, please [see here](./API.md).**
The new API is an ongoing effort to migrate the current API to a more modern and standard API.
The main goals of this new API are:
- Ease of development
- Use of a [modern framework](https://gin-gonic.com)
- Use of a [standard API specification](https://swagger.io/specification/)
- Self-documented API using [Swag](https://github.com/swaggo/swag)
- Improved authentication and sessions using [JWT](https://jwt.io)
- Deduplicate code between the webserver and the API by refactoring the logic into domains
- Improve testability by using interfaces and dependency injection
The current status of this new API can be checked [here](https://github.com/go-shiori/shiori/issues/640).
Since the API is self-docummented, you can check the API documentation by [running the server locally](./Contribute.md#running-the-server-locally) and visiting the [`/swagger/index.html` endpoint](http://localhost:8080/swagger/index.html).
---
## File: docs/CLI.md
Content
---
- [Add bookmark](#add-bookmark)
Add bookmark
---
To add bookmark with CLI you can use `shiori add`.
Shiori has flags to add bookmark: `shiori add --help`
```
Bookmark the specified URL
Usage:
shiori add url [flags]
Flags:
-e, --excerpt string Custom excerpt for this bookmark
-h, --help help for add
--log-archival Log the archival process
-a, --no-archival Save bookmark without creating offline archive
-o, --offline Save bookmark without fetching data from internet
-t, --tags strings Comma-separated tags for this bookmark
-i, --title string Custom title for this bookmark
Global Flags:
--log-caller logrus report caller or not
--log-level string set logrus loglevel (default "info")
--portable run shiori in portable mode
--storage-directory string path to store shiori data
```
Examples:
Add url:
`shiori add https://example.com`
Add url with tags:
`shiori add https://example.com -t "example-1,example-2"`
Add url with custom title:
`shiori add https://example.com --title "example example"`
---
## File: docs/Configuration.md
# Configuration
- [Overall Configuration](#overall-configuration)
- [Global configuration](#global-configuration)
- [HTTP configuration variables](#http-configuration-variables)
- [Storage Configuration](#storage-configuration)
- [The data Directory](#the-data-directory)
- [Database Configuration](#database-configuration)
- [MySQL](#mysql)
- [PostgreSQL](#postgresql)
- [Reverse proxies and the webroot path](#reverse-proxies-and-the-webroot-path)
- [Nginx](#nginx)
## Overall Configuration
Most configuration can be set directly using environment variables or flags. The available flags can be found by running `shiori --help`. The available environment variables are listed below.
### Global configuration
| Environment variable | Default | Required | Description |
| -------------------- | ------- | -------- | -------------------------------------- |
| `SHIORI_DEVELOPMENT` | `False` | No | Specifies if the server is in dev mode |
### HTTP configuration variables
| Environment variable | Default | Required | Description |
| ------------------------------------------ | ------- | -------- | ----------------------------------------------------- |
| `SHIORI_HTTP_ENABLED` | True | No | Enable HTTP service |
| `SHIORI_HTTP_PORT` | 8080 | No | Port number for the HTTP service |
| `SHIORI_HTTP_ADDRESS` | : | No | Address for the HTTP service |
| `SHIORI_HTTP_ROOT_PATH` | / | No | Root path for the HTTP service |
| `SHIORI_HTTP_ACCESS_LOG` | True | No | Logging accessibility for HTTP requests |
| `SHIORI_HTTP_SERVE_WEB_UI` | True | No | Serving Web UI via HTTP. Disable serves only the API. |
| `SHIORI_HTTP_SECRET_KEY` | | **Yes** | Secret key for HTTP sessions. |
| `SHIORI_HTTP_BODY_LIMIT` | 1024 | No | Limit for request body size |
| `SHIORI_HTTP_READ_TIMEOUT` | 10s | No | Maximum duration for reading the entire request |
| `SHIORI_HTTP_WRITE_TIMEOUT` | 10s | No | Maximum duration before timing out writes |
| `SHIORI_HTTP_IDLE_TIMEOUT` | 10s | No | Maximum amount of time to wait for the next request |
| `SHIORI_HTTP_DISABLE_KEEP_ALIVE` | true | No | Disable HTTP keep-alive connections |
| `SHIORI_HTTP_DISABLE_PARSE_MULTIPART_FORM` | true | No | Disable pre-parsing of multipart form |
| `SHIORI_SSO_PROXY_AUTH_ENABLED` | false | No | Enable SSO Auth Proxy Header |
| `SHIORI_SSO_PROXY_AUTH_HEADER_NAME` | Remote-User | No | List of CIDRs of trusted proxies |
| `SHIORI_SSO_PROXY_AUTH_TRUSTED` | 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, fc00::/7 | No | List of CIDRs of trusted proxies |
### Storage Configuration
The `StorageConfig` struct contains settings related to storage.
| Environment variable | Default | Required | Description |
| -------------------- | ------------- | -------- | --------------------------------------- |
| `SHIORI_DIR` | (current dir) | No | Directory where Shiori stores its data. |
#### The data Directory
Shiori is designed to work out of the box, but you can change where it stores your bookmarks if you need to.
By default, Shiori saves your bookmarks in one of the following directories:
| Platform | Directory |
| -------- | ------------------------------------------------------------ |
| Linux | `${XDG_DATA_HOME}/shiori` (default: `~/.local/share/shiori`) |
| macOS | `~/Library/Application Support/shiori` |
| Windows | `%LOCALAPPDATA%/shiori` |
If you pass the flag `--portable` to Shiori, your data will be stored in the `shiori-data` subdirectory alongside the shiori executable.
To specify a custom path, set the `SHIORI_DIR` environment variable.
### Database Configuration
| Environment variable | Default | Required | Description |
| -------------------------- | ------- | -------- | ----------------------------------------------- |
| `SHIORI_DBMS` (deprecated) | `DBMS` | No | Deprecated (Use environment variables for DBMS) |
| `SHIORI_DATABASE_URL` | `URL` | No | URL for the database (required) |
> `SHIORI_DBMS` is deprecated and will be removed in a future release. Please use `SHIORI_DATABASE_URL` instead.
Shiori uses an SQLite3 database stored in the above [data directory by default](#storage-configuration). If you prefer, you can also use MySQL or PostgreSQL database by setting the `SHIORI_DATABASE_URL` environment variable.
#### MySQL
MySQL example: `SHIORI_DATABASE_URL="mysql://username:password@(hostname:port)/database?charset=utf8mb4"`
You can find additional details in [go mysql sql driver documentation](https://github.com/go-sql-driver/mysql#dsn-data-source-name).
#### PostgreSQL
PostgreSQL example: `SHIORI_DATABASE_URL="postgres://pqgotest:password@hostname/database?sslmode=verify-full"`
You can find additional details in [go postgres sql driver documentation](https://pkg.go.dev/github.com/lib/pq).
## Reverse proxies and the webroot path
If you want to serve Shiori behind a reverse proxy, you can set the `SHIORI_HTTP_ROOT_PATH` environment variable to the path where Shiori is served, e.g. `/shiori/`.
Keep in mind this configuration wont make Shiori accessible from `/shiori` path so you need to setup your reverse proxy accordingly so it can strip the webroot path.
We provide some examples for popular reverse proxies below. Please follow your reverse proxy documentation in order to setup it properly.
### Nginx
Fox nginx, you can use the following configuration as a example. The important part **is the trailing slash in `proxy_pass` directive**:
```nginx
location /shiori/ {
proxy_pass http://localhost:8080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
```
---
## File: docs/Contribute.md
# Contribute
1. [Running the server locally](#running-the-server-locally)
2. [Updating the API documentation](#updating-the-api-documentation)
3. [Lint the code](#lint-the-code)
4. [Running tests](#running-tests)
## Running the server locally
To run the current development server with the defaults you can run the following command:
```bash
make run-server
```
## Updating the API documentation
> **ℹ️ Note:** This only applies for the Rest API documentation under the `internal/http` folder, **not** the one under `internal/webserver`.
If you make any changes to the Rest API endpoints, you need to update the swagger documentation. In order to do that, you need to have installed [swag](https://github.com/swaggo/swag).
Then, run the following command:
```bash
make swagger
```
## Updating the frontend styles
The styles that are bundled with Shiori are stored under `internal/view/assets/css/style.css` and `internal/view/assets/css/archive.css` and created from the less files under `internal/views/assets/less`.
If you want to make frontend changes you need to do that under the less files and then compile them to css. In order to do that, you need to have installed [bun](https://bun.sh).
Then, run the following command:
```bash
make styles
```
The `style.css`/`archive.css` will be updated and changes **needs to be committed** to the repository.
## Lint the code
In order to lint the code, you need to have installed [golangci-lint](https://golangci-lint.run) and [swag](https://github.com/swaggo/swag).
After that, run the following command:
```bash
make lint
```
If any errors are found please fix them before submitting your PR.
## Running tests
In order to run the test suite, you need to have running a local instance of MariaDB and PostgreSQL.
If you have docker, you can do this by running the following command with the compose file provided:
```bash
docker-compose up -d mariadb mysql postgres
```
After that, provide the environment variables for the unitest to connect to the database engines:
- `SHIORI_TEST_MYSQL_URL` for MySQL
- `SHIORI_TEST_MARIADB_URL` for MariaDB
- `SHIORI_TEST_PG_URL` for PostgreSQL
```
SHIORI_TEST_PG_URL=postgres://shiori:shiori@127.0.0.1:5432/shiori?sslmode=disable
SHIORI_TEST_MYSQL_URL=shiori:shiori@tcp(127.0.0.1:3306)/shiori
SHIORI_TEST_MARIADB_URL=shiori:shiori@tcp(127.0.0.1:3307)/shiori
```
Finally, run the tests with the following command:
```bash
make unittest
```
## Building the documentation
The documentation is built using MkDocs with the Material theme. For installation instructions, please refer to the [MkDocs installation guide](https://www.mkdocs.org/user-guide/installation/).
To preview the documentation locally while making changes, run:
```bash
mkdocs serve
```
This will start a local server at `http://127.0.0.1:8000` where you can preview your changes in real-time.
Documentation for production is generated automatically on every release and published using github pages.
## Running the server with docker
To run the development server using Docker, you can use the provided `docker-compose.yaml` file which includes both PostgreSQL and MariaDB databases:
```bash
docker compose up shiori
```
This will start the Shiori server on port 8080 with hot-reload enabled. Any changes you make to the code will automatically rebuild and restart the server.
By default, it uses SQLite mounting the local `dev-data` folder in the source code path. To use MariaDB or PostgreSQL instead, uncomment the `SHIORI_DATABASE_URL` line for the appropriate engine in the `docker-compose.yaml` file.
## Running the server using an nginx reverse proxy and a custom webroot
To test Shiori behind an nginx reverse proxy with a custom webroot (e.g., `/shiori/`), you can use the provided nginx configuration:
1. First, ensure the `SHIORI_HTTP_ROOT_PATH` environment variable is uncommented in `docker-compose.yaml`:
```yaml
SHIORI_HTTP_ROOT_PATH: /shiori/
```
2. Then start both Shiori and nginx services:
```bash
docker compose up shiori nginx
```
This will start the shiori service along with nginx. You can access Shiori using [http://localhost:8081/shiori](http://localhost:8081/shiori).
The nginx configuration in `testdata/nginx.conf` handles all the necessary configuration.
---
## File: docs/faq.md
# Frequently asked questions
- [General](#general)
- [What is this project ?](#what-is-this-project-)
- [How does it compare to other bookmarks manager ?](#how-does-it-compare-to-other-bookmarks-manager-)
- [What are the system requirements ?](#what-are-the-system-requirements-)
- [What is the status for this app ?](#what-is-the-status-for-this-app-)
- [Is this app actively maintained ?](#is-this-app-actively-maintained-)
- [How to make a contribution ?](#how-to-make-a-contribution-)
- [How to make a donation ?](#how-to-make-a-donation-)
- [Common Issues](#common-issues)
- [What is the default account to login at the first time ?](#what-is-the-default-account-to-login-at-the-first-time-)
- [Why my old accounts can't do anything after upgrading Shiori to v1.5.0 ?](#why-my-old-accounts-cant-do-anything-after-upgrading-shiori-to-v150-)
- [`Failed to get bookmarks: failed to fetch data: no such module: fts4` ?](#failed-to-get-bookmarks-failed-to-fetch-data-no-such-module-fts4-)
- [Advanced](#advanced)
- [How to run `shiori` on start up (Linux)?](#how-to-run-shiori-on-start-up-linux)
- [How to run `shiori` on start up (macOS)?](#how-to-run-shiori-on-start-up-macos)
## General
### What is this project ?
Shiori is a bookmarks manager that built with Go. I've got the idea to make this after reading a comment on HN back in [April 2017](https://news.ycombinator.com/item?id=14203383) :
```
... for me the dream bookmark manager would be something really simple
with two commands like:
$ bookmark add http://...
That will:
a. Download a static copy of the webpage in a single HTML file, with a
PDF exported copy, that also take care of removing ads and
unrelated content from the stored content.
b. Run something like http://smmry.com/ to create a summary of the page
in few sentences and store it.
c. Use NLP techniques to extract the principle keywords and use them
as tags
And another command like:
$ bookmark search "..."
That will:
d. Not use regexp or complicated search pattern, but instead;
e. Search titles, tags, page content smartly and interactively, and;
f. Sort/filter results smartly by relevance, number of matches,
frequency, or anything else useful
g. Storing everything in a git repository or simple file structure
for easy synchronization, bonus point for browsers integrations.
```
I do like using bookmarks and those idea sounds useful to me. More importantly, it seems possible enough to do. Not too hard that it's impossible for me, but not too easy that it doesn't teach me anything. Looking back now, the only thing that I (kind of) managed to do is a, b, d and e. But it's enough for me, so it's fine I guess :laughing:.
### How does it compare to other bookmarks manager ?
To be honest I don't know. The only bookmarks manager that I've used is Pocket and the one that bundled in web browser. I do like Pocket though. However, since bookmarks is kind of sensitive data, I prefer it stays offline or in my own server.
### What are the system requirements ?
It runs in the lowest tier of Digital Ocean VPS, so I guess it should be able to run anywhere.
### What is the status for this app ?
It's stable enough to use and the database shouldn't be changed anymore. However, my bookmarks at most is only several hundred entries, therefore I haven't test whether it able to process or imports huge amount of bookmarks. If you would, please do try it.
### Is this app actively maintained ?
Yes, however the development pace might be really slow. @fmartingr is the current active maintainer though @RadhiFadlillah or @deanishe may step and work on stuff from time to time or in other [go-shiori projects](https://github.com/go-shiori)
### How to make a contribution ?
Just like other open source projects, you can make a contribution by submitting issues or pull requests.
### How to make a donation ?
If you like this project, you can donate to maintainers via:
- **fmartingr** [PayPal](https://www.paypal.me/fmartingr), [Ko-Fi](https://ko-fi.com/fmartingr)
- **RadhiFadlillah** [PayPal](https://www.paypal.me/RadhiFadlillah), [Ko-Fi](https://ko-fi.com/radhifadlillah)
## Common Issues
### What is the default account to login at the first time ?
A default account is created with the credentials:
- Username: `shiori`
- Password: `gopher`
### Why my old accounts can't do anything after upgrading Shiori to v1.5.0 ?
This issue happened because in Shiori v1.0.0 there are no account level, which means everyone is treated as owner. However, in Shiori v1.5.0 there are two account levels i.e. owner and visitor. The level difference is stored in [database](https://github.com/go-shiori/shiori/blob/master/internal/database/sqlite.go#L42-L48) as boolean value in column `owner` with default value false (which means by default all account is visitor, unless specified otherwise).
Because in v1.5.0 by default all account is visitor, when updating from v1.0 to v1.5 all of the old accounts by default will be marked as visitor. Fortunately, when there are no owner registered in database, we can login as owner using default account.
So, as workaround for this issue, you should :
- Login as default account.
- Go to options page.
- Remove your old accounts.
- Recreate them, but now as owner.
For more details see [#148](https://github.com/go-shiori/shiori/issues/148).
### `Failed to get bookmarks: failed to fetch data: no such module: fts4` ?
This happens to SQLite users that upgrade from 1.5.0 to 1.5.1 because of a breaking change. Please check the
[announcement](https://github.com/go-shiori/shiori/discussions/383) to understand how to migrate your database and move forward.
## Advanced
### How to run `shiori` on start up (Linux)?
There are several methods to run `shiori` on start up, however the most recommended is running it as a service.
1. Create a service unit for `systemd` at `/etc/systemd/system/shiori.service`.
* Shiori is run via `docker` :
```ini
[Unit]
Description=Shiori container
After=docker.service
[Service]
Restart=always
ExecStartPre=-/usr/bin/docker rm shiori-1
ExecStart=/usr/bin/docker run \
--rm \
--name shiori-1 \
-p 8080:8080 \
-v /srv/machines/shiori:/shiori \
ghcr.io/go-shiori/shiori
ExecStop=/usr/bin/docker stop -t 2 shiori-1
[Install]
WantedBy=multi-user.target
```
* Shiori without `docker`. Set absolute path to `shiori` binary. `--portable` sets the data directory to be alongside the executable.
```ini
[Unit]
Description=Shiori service
[Service]
ExecStart=/home/user/go/bin/shiori server --portable
Restart=always
[Install]
WantedBy=multi-user.target
```
* Shiori without `docker` and without `--portable` but secure.
```ini
[Unit]
Description=shiori service
Requires=network-online.target
After=network-online.target
[Service]
Type=simple
ExecStart=/usr/bin/shiori server
Restart=always
User=shiori
Group=shiori
Environment="SHIORI_DIR=/var/lib/shiori"
DynamicUser=true
PrivateUsers=true
ProtectHome=true
ProtectKernelLogs=true
RestrictAddressFamilies=AF_INET AF_INET6
StateDirectory=shiori
SystemCallErrorNumber=EPERM
SystemCallFilter=@system-service
SystemCallFilter=~@chown
SystemCallFilter=~@keyring
SystemCallFilter=~@memlock
SystemCallFilter=~@setuid
DeviceAllow=
CapabilityBoundingSet=
LockPersonality=true
MemoryDenyWriteExecute=true
NoNewPrivileges=true
PrivateDevices=true
PrivateTmp=true
ProtectControlGroups=true
ProtectKernelTunables=true
ProtectSystem=full
ProtectClock=true
ProtectKernelModules=true
ProtectProc=noaccess
ProtectHostname=true
ProcSubset=pid
RestrictNamespaces=true
RestrictRealtime=true
RestrictSUIDSGID=true
SystemCallArchitectures=native
SystemCallFilter=~@clock
SystemCallFilter=~@debug
SystemCallFilter=~@module
SystemCallFilter=~@mount
SystemCallFilter=~@raw-io
SystemCallFilter=~@reboot
SystemCallFilter=~@privileged
SystemCallFilter=~@resources
SystemCallFilter=~@cpu-emulation
SystemCallFilter=~@obsolete
UMask=0077
[Install]
WantedBy=multi-user.target
```
2. Set up data directory if Shiori with `docker`
This assumes, that the Shiori container has a runtime directory to store their
database, which is at `/srv/machines/shiori`. If you want to modify that,
make sure, to fix your `shiori.service` as well.
```sh
install -d /srv/machines/shiori
```
3. Enable and start the service
```sh
systemctl enable --now shiori
```
### How to run `shiori` on start up (macOS)?
Create `local.app.shiori.plist` file in `~/Library/LaunchAgents` and use the template below. Add your own secret key and paths. The filename can be anything but it's a good practice to start it with `local`:
```xml
Label
local.app.shiori
EnvironmentVariables
SHIORI_HTTP_SECRET_KEY
somerandomvalue123489
ProgramArguments
/absolute/path/to/shiori/binary
server
--storage-directory
/absolute/path/to/shiori/storage/directory
RunAtLoad
ServiceDescription
Shiori Bookmarking Service
```
You also need to update your Mac's `System Settings > General > Login Items & Extensions > Allow in the background`. Next time you log in to your Mac, the Shiori server will automatically start and the Shiori login state will persist. To remove the service, delete the `plist` file.
---
## File: docs/index.md
# Documentation
Shiori is a simple bookmarks manager written in Go language. Intended as a simple clone of [Pocket](https://getpocket.com/), it can be used as both a command line and web application. Features include:
- Basic bookmarks management (add, edit, delete and search)
- Import/export bookmarks from Netscape Bookmark file
- Import from Pocket
- Simple web interface
- Offline webpage archiving
- Support for SQLite, PostgreSQL and MySQL
---
## File: docs/Installation.md
There are several installation methods available :
- [Supported](#supported)
- [Using Precompiled Binary](#using-precompiled-binary)
- [Building From Source](#building-from-source)
- [Using Docker Image](#using-docker-image)
- [Community provided](#community-provided)
- [Using Kubernetes manifests](#using-kubernetes-manifests)
- [Managed Hosting](#managed-hosting)
- [PikaPods](#pikapods)
## Supported
### Using Precompiled Binary
Download the latest version of `shiori` from [the release page](https://github.com/go-shiori/shiori/releases/latest), then put it in your `PATH`.
On Linux or MacOS, you can do it by adding this line to your profile file (either `$HOME/.bash_profile` or `$HOME/.profile`):
```
export PATH=$PATH:/path/to/shiori
```
Note that this will not automatically update your path for the remainder of the session. To do this, you should run:
```
source $HOME/.bash_profile
or
source $HOME/.profile
```
On Windows, you can simply set the `PATH` by using the advanced system settings.
### Building From Source
Shiori uses Go module so make sure you have version of `go >= 1.14.1` installed, then run:
```
go get -u -v github.com/go-shiori/shiori
```
### Using Docker Image
To use Docker image, you can pull the latest automated build from Docker Hub :
```
docker pull ghcr.io/go-shiori/shiori
```
If you want to build the Docker image on your own, Shiori already has its [Dockerfile](https://github.com/go-shiori/shiori/blob/master/Dockerfile), so you can build the Docker image by running :
```
docker build -t shiori .
```
## Community provided
Below this there are other ways to deploy Shiori which are not supported by the team but were provided by the community to help others have a starting point.
### Using Kubernetes manifests
If you're self-hosting with a Kubernetes cluster, here are manifest files that
you can use to deploy Shiori:
`deploy.yaml`:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: shiori
labels:
app: shiori
spec:
replicas: 1
selector:
matchLabels:
app: shiori
template:
metadata:
labels:
app: shiori
spec:
volumes:
- name: app
hostPath:
path: /path/to/data/dir
- name: tmp
emptyDir:
medium: Memory
containers:
- name: shiori
image: ghcr.io/go-shiori/shiori:latest
command: ["/usr/bin/shiori", "serve"]
imagePullPolicy: Always
ports:
- containerPort: 8080
env:
- name: SHIORI_DIR
value: /srv/shiori
volumeMounts:
- mountPath: /srv/shiori
name: app
- mountPath: /tmp
name: tmp
```
Here we are using a local directory to persist Shiori's data. You will need
to replace `/path/to/data/dir` with the path to the directory where you want
to keep your data. We are also mounting an `EmptyDir` volume for `/tmp` so
we can successfully generate ebooks.
Since we haven't configured a database in particular,
Shiori will use SQLite. I don't think Postgres or MySQL is worth it for
such an app, but that's up to you. If you decide to use SQLite, I strongly
suggest to keep `replicas` set to 1 since SQLite usually allows at most
one writer to proceed concurrently.
To route requests to your deployment, you will need a `Service` that gets used
by an `Ingress` to handle routing. If you wand to add a path suffix or use a
sub domain, you can do so through the ingress config. We only show the bare
minimum config to get you started.
`service.yaml`
```yaml
apiVersion: v1
kind: Service
metadata:
name: shiori
spec:
type: LoadBalancer
selector:
app: shiori
ports:
- port: 8080
targetPort: 8080
```
This is using a `LoadBalancer` type which gives the most flexibility.
`ingress.yaml`:
```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: shiori
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: shiori
port:
number: 8080
```
## Managed Hosting
If you don't manage your own server, the below providers will host Shiori for you. None are endorsed by or affiliated with the team. Support is provided by the providers.
### CloudBreak
[CloudBreak](https://cloudbreak.app/products/shiori?utm_medium=referral&utm_source=shiori-docs&rby=shiori-docs) offers Shiori hosting from $12/year ($1/month). Get $3 off with coupon `SHIORI`.
### PikaPods
[PikaPods](https://www.pikapods.com/) offers Shiori hosting from $1.20/month with $5 free welcome credit. EU and US regions available. Updates are applied weekly and user data backed up daily.
[](https://www.pikapods.com/pods?run=shiori)
---
## File: docs/Screenshots.md
# Desktop Screenshots
## Login Screen
=== "Light Theme"
[](./assets/screenshots/01-login.png)
=== "Dark Theme"
[](./assets/screenshots/05-dark-login.png)
## Grid Mode
=== "Light Theme"
[](./assets/screenshots/02-home.png)
=== "Dark Theme"
[](./assets/screenshots/06-dark-home.png)
## List Mode
=== "Light Theme"
[](./assets/screenshots/03-home-list.png)
=== "Dark Theme"
[](./assets/screenshots/07-dark-home-list.png)
## Options Page
=== "Light Theme"
[](./assets/screenshots/04-options.png)
=== "Dark Theme"
[](./assets/screenshots/08-dark-options.png)
# Mobile Screenshots
## Login Screen
=== "Light Theme"
[](./assets/screenshots/09-mobile-login.png)
=== "Dark Theme"
[](./assets/screenshots/13-mobile-dark-login.png)
## Grid Mode
=== "Light Theme"
[](./assets/screenshots/10-mobile-home.png)
=== "Dark Theme"
[](./assets/screenshots/14-mobile-dark-home.png)
## List Mode
=== "Light Theme"
[](./assets/screenshots/11-mobile-home-list.png)
=== "Dark Theme"
[](./assets/screenshots/15-mobile-dark-home-list.png)
## Options Page
=== "Light Theme"
[](./assets/screenshots/12-mobile-options.png)
=== "Dark Theme"
[](./assets/screenshots/16-mobile-dark-options.png)
--- METRICS ---
- Files Extracted: 11
- Estimated Token Budget: ~10171 tokens
- Recency Window: Active (< 180 days)
- Canonical Reference: https://codewiki.google/github.com/go-shiori/shiori