Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .env-sample
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,12 @@ KEYCLOAK_CLIENT_SECRET=replace-with-client-secret
# Optional
# Keycloak__RequireHttpsMetadata=false

# AI
REKA_API_KEY=replace-with-reka-api-key
# AI (any OpenAI-compatible provider, see docs/ai-provider-setup.md)
# Base URL must end at /v1, without /chat/completions.
AI_API_KEY=replace-with-your-ai-api-key
AI_BASE_URL=https://openrouter.ai/api/v1
AI_MODEL_NAME=mistralai/mistral-small-3.2-24b-instruct
# Older setups can keep using REKA_API_KEY instead of AI_API_KEY.

# Parser
PARSER_BASE_URL=https://...azurewebsites.net/api/parser
Expand Down
147 changes: 74 additions & 73 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,73 +1,74 @@
# Note Bookmark

![GitHub Release](https://img.shields.io/github/v/release/fboucher/NoteBookmark) ![.NET](https://img.shields.io/badge/10.0-512BD4?logo=dotnet&logoColor=fff) ![MAUI](https://img.shields.io/badge/MAUI-10.0-gray?logo=dotnet&logoColor=white&labelColor=512BD4) ![Android Supported](https://img.shields.io/badge/Android-supported-3DDC84?logo=android&logoColor=white) [![Unit Tests](https://github.com/FBoucher/NoteBookmark/actions/workflows/running-unit-tests.yml/badge.svg)](https://github.com/FBoucher/NoteBookmark/actions/workflows/running-unit-tests.yml)
[![OpenAI Compatible](https://img.shields.io/badge/OpenAI-Compatible-10a37f?logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU%2BT3BlbkFJPC90aXRsZT48cGF0aCBmaWxsPSJ3aGl0ZSIgZD0iTTIyLjI4MTkgOS44MjExYTUuOTg0NyA1Ljk4NDcgMCAwIDAtLjUxNTctNC45MTA4IDYuMDQ2MiA2LjA0NjIgMCAwIDAtNi41MDk4LTIuOUE2LjA2NTEgNi4wNjUxIDAgMCAwIDQuOTgwNyA0LjE4MThhNS45ODQ3IDUuOTg0NyAwIDAgMC0zLjk5NzcgMi45IDYuMDQ2MiA2LjA0NjIgMCAwIDAgLjc0MjcgNy4wOTY2IDUuOTggNS45OCAwIDAgMCAuNTExIDQuOTEwNyA2LjA1MSA2LjA1MSAwIDAgMCA2LjUxNDYgMi45MDAxQTUuOTg0NyA1Ljk4NDcgMCAwIDAgMTMuMjU5OSAyNGE2LjA1NTcgNi4wNTU3IDAgMCAwIDUuNzcxOC00LjIwNTggNS45ODk0IDUuOTg5NCAwIDAgMCAzLjk5NzctMi45MDAxIDYuMDU1NyA2LjA1NTcgMCAwIDAtLjc0NzUtNy4wNzI5em0tOS4wMjIgMTIuNjA4MWE0LjQ3NTUgNC40NzU1IDAgMCAxLTIuODc2NC0xLjA0MDhsLjE0MTktLjA4MDQgNC43NzgzLTIuNzU4MmEuNzk0OC43OTQ4IDAgMCAwIC4zOTI3LS42ODEzdi02LjczNjlsMi4wMiAxLjE2ODZhLjA3MS4wNzEgMCAwIDEgLjAzOC4wNTJ2NS41ODI2YTQuNTA0IDQuNTA0IDAgMCAxLTQuNDk0NSA0LjQ5NDR6bS05LjY2MDctNC4xMjU0YTQuNDcwOCA0LjQ3MDggMCAwIDEtLjUzNDYtMy4wMTM3bC4xNDIuMDg1MiA0Ljc4MyAyLjc1ODJhLjc3MTIuNzcxMiAwIDAgMCAuNzgwNiAwbDUuODQyOC0zLjM2ODV2Mi4zMzI0YS4wODA0LjA4MDQgMCAwIDEtLjAzMzIuMDYxNUw5Ljc0IDE5Ljk1MDJhNC40OTkyIDQuNDk5MiAwIDAgMS02LjE0MDgtMS42NDY0ek0yLjM0MDggNy44OTU2YTQuNDg1IDQuNDg1IDAgMCAxIDIuMzY1NS0xLjk3MjhWMTEuNmEuNzY2NC43NjY0IDAgMCAwIC4zODc5LjY3NjVsNS44MTQ0IDMuMzU0My0yLjAyMDEgMS4xNjg1YS4wNzU3LjA3NTcgMCAwIDEtLjA3MSAwbC00LjgzMDMtMi43ODY1QTQuNTA0IDQuNTA0IDAgMCAxIDIuMzQwOCA3Ljg3MnptMTYuNTk2MyAzLjg1NThMMTMuMTAzOCA4LjM2NCAxNS4xMTkyIDcuMmEuMDc1Ny4wNzU3IDAgMCAxIC4wNzEgMGw0LjgzMDMgMi43OTEzYTQuNDk0NCA0LjQ5NDQgMCAwIDEtLjY3NjUgOC4xMDQydi01LjY3NzJhLjc5Ljc5IDAgMCAwLS40MDctLjY2N3ptMi4wMTA3LTMuMDIzMWwtLjE0Mi0uMDg1Mi00Ljc3MzUtMi43ODE4YS43NzU5Ljc3NTkgMCAwIDAtLjc4NTQgMEw5LjQwOSA5LjIyOTdWNi44OTc0YS4wNjYyLjA2NjIgMCAwIDEgLjAyODQtLjA2MTVsNC44MzAzLTIuNzg2NmE0LjQ5OTIgNC40OTkyIDAgMCAxIDYuNjgwMiA0LjY2ek04LjMwNjUgMTIuODYzbC0yLjAyLTEuMTYzOGEuMDgwNC4wODA0IDAgMCAxLS4wMzgtLjA1NjdWNi4wNzQyYTQuNDk5MiA0LjQ5OTIgMCAwIDEgNy4zNzU3LTMuNDUzN2wtLjE0Mi4wODA1TDguNzA0IDUuNDU5YS43OTQ4Ljc5NDggMCAwIDAtLjM5MjcuNjgxM3ptMS4wOTc2LTIuMzY1NGwyLjYwMi0xLjQ5OTggMi42MDY5IDEuNDk5OHYyLjk5OTRsLTIuNTk3NCAxLjQ5OTctMi42MDY3LTEuNDk5N1oiLz48L3N2Zz4%3D)](https://developers.openai.com/)




I use this project mostly everyday. I build it to help me collecting my thoughts about articles, and blob posts I read during the week and then aggregate them in a #ReadingNotes blog post. You can find those post on my blog [here](https://frankysnotes.com).

NoteBookmark is composed of three main sections:

- **Post**: where you can manage a posts "to read", and add notes to them.
- **Generate Summary**: where you can generate a summary of the posts you read.
- **Summaries**: where you can see all the summaries you generated.

![Slide show of all NoteBookmark Screens](gh/images/NoteBookmark-Tour_hd.gif)

## Run Options

- Development: running the Aspire project is the easiest path and everything is wired automatically.
- Production-style: run with containers and deploy to Azure.

Run locally with Aspire:

```bash
dotnet run --project src/NoteBookmark.AppHost
```

## How to deploy Your own NoteBookmark

### Get the code on your machine

- Fork this repository to your account.
- Clone the repository to your local machine.


### Deploy the solution (5 mins)

Using Azure Developer CLI let's initialize your environment. In a terminal, at the root of the project, run the following command. When ask give it a name (ex: NoteBookmark-dev).

```bash
azd init
```

Now let's deploy the solution. Run the following command in the terminal. You will have to select your Azure subscription where you want to deploy the solution, and a location (ex: eastus).

```bash
azd up
```

It should take around five minutes to deploy the solution. Once it's done, you will see the URL for **Deploying service blazor-app**.

### Secure the App in a few clicks

The app is now deployed, but it's not secure. Navigate to the Azure Portal, and find the Resource Group you just deployed (ex: rg-notebookmark-dev). In this resource group, open the Container App **Container App**. From the left menu, select **Authentication** and click the **Add identity provider**.

You can choose between multiple providers, I like to use Microsoft since it's deploy in Azure and I'm already logged in. If Microsoft is choose, select the recomended **Client secret expiration** (ex: 180 days). You can keep all the other default settings. Click **Add**.

Next time you will navigate to the app, you will be prompt a to login with your Microsoft account. The first time you will have a **Permissions requested** screen, click **Accept**.

Voila! Your app is now secure.

## Documentation

For detailed setup guides and configuration information:
- [Keycloak Container Setup](/docs/keycloak-container-setup.md) - Start a local Keycloak instance if you do not already have one
- [Keycloak Authentication Setup](/docs/keycloak-setup.md) - Complete guide for setting up Keycloak authentication
- [Docker Compose Deployment](/docs/docker-compose-deployment.md) - Deploy NoteBookmark containers (assumes a healthy Keycloak + configured realm)

## Contributing

Your contributions are welcome! Take a look at [CONTRIBUTING](/CONTRIBUTING.md) for details.
# Note Bookmark

![GitHub Release](https://img.shields.io/github/v/release/fboucher/NoteBookmark) ![.NET](https://img.shields.io/badge/10.0-512BD4?logo=dotnet&logoColor=fff) ![MAUI](https://img.shields.io/badge/MAUI-10.0-gray?logo=dotnet&logoColor=white&labelColor=512BD4) ![Android Supported](https://img.shields.io/badge/Android-supported-3DDC84?logo=android&logoColor=white) [![Unit Tests](https://github.com/FBoucher/NoteBookmark/actions/workflows/running-unit-tests.yml/badge.svg)](https://github.com/FBoucher/NoteBookmark/actions/workflows/running-unit-tests.yml)
[![OpenAI Compatible](https://img.shields.io/badge/OpenAI-Compatible-10a37f?logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU%2BT3BlbkFJPC90aXRsZT48cGF0aCBmaWxsPSJ3aGl0ZSIgZD0iTTIyLjI4MTkgOS44MjExYTUuOTg0NyA1Ljk4NDcgMCAwIDAtLjUxNTctNC45MTA4IDYuMDQ2MiA2LjA0NjIgMCAwIDAtNi41MDk4LTIuOUE2LjA2NTEgNi4wNjUxIDAgMCAwIDQuOTgwNyA0LjE4MThhNS45ODQ3IDUuOTg0NyAwIDAgMC0zLjk5NzcgMi45IDYuMDQ2MiA2LjA0NjIgMCAwIDAgLjc0MjcgNy4wOTY2IDUuOTggNS45OCAwIDAgMCAuNTExIDQuOTEwNyA2LjA1MSA2LjA1MSAwIDAgMCA2LjUxNDYgMi45MDAxQTUuOTg0NyA1Ljk4NDcgMCAwIDAgMTMuMjU5OSAyNGE2LjA1NTcgNi4wNTU3IDAgMCAwIDUuNzcxOC00LjIwNTggNS45ODk0IDUuOTg5NCAwIDAgMCAzLjk5NzctMi45MDAxIDYuMDU1NyA2LjA1NTcgMCAwIDAtLjc0NzUtNy4wNzI5em0tOS4wMjIgMTIuNjA4MWE0LjQ3NTUgNC40NzU1IDAgMCAxLTIuODc2NC0xLjA0MDhsLjE0MTktLjA4MDQgNC43NzgzLTIuNzU4MmEuNzk0OC43OTQ4IDAgMCAwIC4zOTI3LS42ODEzdi02LjczNjlsMi4wMiAxLjE2ODZhLjA3MS4wNzEgMCAwIDEgLjAzOC4wNTJ2NS41ODI2YTQuNTA0IDQuNTA0IDAgMCAxLTQuNDk0NSA0LjQ5NDR6bS05LjY2MDctNC4xMjU0YTQuNDcwOCA0LjQ3MDggMCAwIDEtLjUzNDYtMy4wMTM3bC4xNDIuMDg1MiA0Ljc4MyAyLjc1ODJhLjc3MTIuNzcxMiAwIDAgMCAuNzgwNiAwbDUuODQyOC0zLjM2ODV2Mi4zMzI0YS4wODA0LjA4MDQgMCAwIDEtLjAzMzIuMDYxNUw5Ljc0IDE5Ljk1MDJhNC40OTkyIDQuNDk5MiAwIDAgMS02LjE0MDgtMS42NDY0ek0yLjM0MDggNy44OTU2YTQuNDg1IDQuNDg1IDAgMCAxIDIuMzY1NS0xLjk3MjhWMTEuNmEuNzY2NC43NjY0IDAgMCAwIC4zODc5LjY3NjVsNS44MTQ0IDMuMzU0My0yLjAyMDEgMS4xNjg1YS4wNzU3LjA3NTcgMCAwIDEtLjA3MSAwbC00LjgzMDMtMi43ODY1QTQuNTA0IDQuNTA0IDAgMCAxIDIuMzQwOCA3Ljg3MnptMTYuNTk2MyAzLjg1NThMMTMuMTAzOCA4LjM2NCAxNS4xMTkyIDcuMmEuMDc1Ny4wNzU3IDAgMCAxIC4wNzEgMGw0LjgzMDMgMi43OTEzYTQuNDk0NCA0LjQ5NDQgMCAwIDEtLjY3NjUgOC4xMDQydi01LjY3NzJhLjc5Ljc5IDAgMCAwLS40MDctLjY2N3ptMi4wMTA3LTMuMDIzMWwtLjE0Mi0uMDg1Mi00Ljc3MzUtMi43ODE4YS43NzU5Ljc3NTkgMCAwIDAtLjc4NTQgMEw5LjQwOSA5LjIyOTdWNi44OTc0YS4wNjYyLjA2NjIgMCAwIDEgLjAyODQtLjA2MTVsNC44MzAzLTIuNzg2NmE0LjQ5OTIgNC40OTkyIDAgMCAxIDYuNjgwMiA0LjY2ek04LjMwNjUgMTIuODYzbC0yLjAyLTEuMTYzOGEuMDgwNC4wODA0IDAgMCAxLS4wMzgtLjA1NjdWNi4wNzQyYTQuNDk5MiA0LjQ5OTIgMCAwIDEgNy4zNzU3LTMuNDUzN2wtLjE0Mi4wODA1TDguNzA0IDUuNDU5YS43OTQ4Ljc5NDggMCAwIDAtLjM5MjcuNjgxM3ptMS4wOTc2LTIuMzY1NGwyLjYwMi0xLjQ5OTggMi42MDY5IDEuNDk5OHYyLjk5OTRsLTIuNTk3NCAxLjQ5OTctMi42MDY3LTEuNDk5N1oiLz48L3N2Zz4%3D)](https://developers.openai.com/)




I use this project mostly everyday. I build it to help me collecting my thoughts about articles, and blob posts I read during the week and then aggregate them in a #ReadingNotes blog post. You can find those post on my blog [here](https://frankysnotes.com).

NoteBookmark is composed of three main sections:

- **Post**: where you can manage a posts "to read", and add notes to them.
- **Generate Summary**: where you can generate a summary of the posts you read.
- **Summaries**: where you can see all the summaries you generated.

![Slide show of all NoteBookmark Screens](gh/images/NoteBookmark-Tour_hd.gif)

## Run Options

- Development: running the Aspire project is the easiest path and everything is wired automatically.
- Production-style: run with containers and deploy to Azure.

Run locally with Aspire:

```bash
dotnet run --project src/NoteBookmark.AppHost
```

## How to deploy Your own NoteBookmark

### Get the code on your machine

- Fork this repository to your account.
- Clone the repository to your local machine.


### Deploy the solution (5 mins)

Using Azure Developer CLI let's initialize your environment. In a terminal, at the root of the project, run the following command. When ask give it a name (ex: NoteBookmark-dev).

```bash
azd init
```

Now let's deploy the solution. Run the following command in the terminal. You will have to select your Azure subscription where you want to deploy the solution, and a location (ex: eastus).

```bash
azd up
```

It should take around five minutes to deploy the solution. Once it's done, you will see the URL for **Deploying service blazor-app**.

### Secure the App in a few clicks

The app is now deployed, but it's not secure. Navigate to the Azure Portal, and find the Resource Group you just deployed (ex: rg-notebookmark-dev). In this resource group, open the Container App **Container App**. From the left menu, select **Authentication** and click the **Add identity provider**.

You can choose between multiple providers, I like to use Microsoft since it's deploy in Azure and I'm already logged in. If Microsoft is choose, select the recomended **Client secret expiration** (ex: 180 days). You can keep all the other default settings. Click **Add**.

Next time you will navigate to the app, you will be prompt a to login with your Microsoft account. The first time you will have a **Permissions requested** screen, click **Accept**.

Voila! Your app is now secure.

## Documentation

For detailed setup guides and configuration information:
- [Keycloak Container Setup](/docs/keycloak-container-setup.md) - Start a local Keycloak instance if you do not already have one
- [Keycloak Authentication Setup](/docs/keycloak-setup.md) - Complete guide for setting up Keycloak authentication
- [Docker Compose Deployment](/docs/docker-compose-deployment.md) - Deploy NoteBookmark containers (assumes a healthy Keycloak + configured realm)
- [AI Provider Setup](/docs/ai-provider-setup.md) - Configure the AI provider (API key, Base URL, model) with OpenCode, OpenRouter or Ollama examples

## Contributing

Your contributions are welcome! Take a look at [CONTRIBUTING](/CONTRIBUTING.md) for details.
4 changes: 3 additions & 1 deletion docker-compose/note-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ services:
services__keycloak__http__0: "http://keycloak:8080"
ConnectionStrings__nb-tables: ${NB_STORAGE_OUTPUTS_TABLEENDPOINT}
ConnectionStrings__nb-blobs: ${NB_STORAGE_OUTPUTS_BLOBENDPOINT}
REKA_API_KEY: ${REKA_API_KEY}
AppSettings__AiApiKey: ${AI_API_KEY:-${REKA_API_KEY:-}}
AppSettings__AiBaseUrl: ${AI_BASE_URL:-}
AppSettings__AiModelName: ${AI_MODEL_NAME:-}
Keycloak__Authority: ${KEYCLOAK_AUTHORITY}
Keycloak__ClientId: ${KEYCLOAK_CLIENT_ID}
Keycloak__ClientSecret: ${KEYCLOAK_CLIENT_SECRET}
Expand Down
107 changes: 107 additions & 0 deletions docs/ai-provider-setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# AI Provider Setup

NoteBookmark uses an AI model to generate post summaries and research suggestions. It works with any provider that exposes an **OpenAI-compatible** Chat Completions API. This guide explains the three AI settings, how the app decides which values to use, and gives working examples for [OpenCode.ai](#opencodeai), [OpenRouter](#openrouter) and [Ollama](#ollama-local).

## The three settings

| Setting | What it expects |
|---|---|
| **API Key** | The key issued by your provider. |
| **Base URL** | The root of the provider's OpenAI-compatible API, ending at `/v1`. |
| **Model Name** | The model id exactly as the provider names it. |

### The Base URL must stop at `/v1`

The app builds an OpenAI .NET SDK `ChatClient` with `Endpoint = BaseUrl`, and the SDK appends `/chat/completions` itself. So the Base URL must **not** include `/chat/completions` or any other trailing path.

| ✅ Correct | ❌ Wrong |
|---|---|
| `https://opencode.ai/inference/openai/v1` | `https://opencode.ai/inference/openai/v1/chat/completions` |
| `https://openrouter.ai/api/v1` | `https://openrouter.ai/api/v1/chat/completions` |

With the wrong form, the request goes to `.../chat/completions/chat/completions` and fails.

## Where the settings come from

The app reads the AI settings in this order:

1. **The Settings page** (stored in the database). These values are used **only when API Key is non-empty**. If Base URL or Model Name is left empty, a built-in default is used for that field.
2. **Configuration** (environment variables or `appsettings.json`), used when no API Key is saved on the Settings page:
- API key: `AppSettings:AiApiKey`, then `AppSettings:REKA_API_KEY`, then the `REKA_API_KEY` environment variable (the Reka names are still supported for backward compatibility).
- Base URL: `AppSettings:AiBaseUrl`
- Model name: `AppSettings:AiModelName`

As environment variables (for Docker Compose or Azure Container Apps) the configuration keys use a double underscore: `AppSettings__AiApiKey`, `AppSettings__AiBaseUrl`, `AppSettings__AiModelName`.

> **Tip:** Set all three values together. If you only set the API key, the Base URL and Model Name fall back to the built-in defaults, which are unlikely to match your provider.

## When a summary comes back empty

AI errors don't show up in the UI. The summary just comes back empty. To find the cause, look at the **blazor-app** logs (the AI calls are made by the web app, not the API):

- With Aspire, open the dashboard, select the `blazor-app` resource, and look at its console logs or structured logs.
- With Docker Compose, run `docker logs notebookmark-blazor`.

Look for `An error occurred while generating summary:` followed by the provider's error message. The usual causes are:

- A Base URL that ends with `/chat/completions` (see above).
- A model id the provider doesn't serve on its OpenAI-compatible endpoint.
- An invalid or missing API key.

## Provider examples

### OpenCode.ai

| Field | Value |
|---|---|
| **API Key** | Your OpenCode key |
| **Base URL** | `https://opencode.ai/inference/openai/v1` |
| **Model Name** | A model served on the OpenAI-compatible path, for example a DeepSeek, GLM, Kimi, MiniMax, Qwen or Mistral model |

The full model list is at `https://opencode.ai/inference/v1/models`.

> **Gotcha: Gemini models don't work.** OpenCode serves Gemini models (for example `gemini-*-flash`) only on its Google-native path (`/inference/google/v1beta/...`), not on the OpenAI-compatible one. NoteBookmark can only talk to the OpenAI-compatible path, so pick a model from the list above instead.

### OpenRouter

| Field | Value |
|---|---|
| **API Key** | Your OpenRouter key (from <https://openrouter.ai/keys>) |
| **Base URL** | `https://openrouter.ai/api/v1` |
| **Model Name** | Any id from <https://openrouter.ai/models>, in `vendor/model` form (for example `mistralai/mistral-small-3.2-24b-instruct`) |

### Ollama (local)

| Field | Value |
|---|---|
| **API Key** | Any non-empty placeholder, for example `ollama`. Ollama ignores it, but the app only uses the Settings page values when the API Key is non-empty. |
| **Base URL** | `http://localhost:11434/v1`, or `http://host.docker.internal:11434/v1` when NoteBookmark runs in a container and Ollama runs on the host |
| **Model Name** | A model you've pulled, as shown by `ollama list` (for example `llama3.2`) |

Pull the model first, for example `ollama pull llama3.2`.

## Configuring without the Settings page

Use these when you'd rather set the provider in configuration than through the UI.

**Local development (Aspire)**, in `src/NoteBookmark.AppHost/appsettings.json` or user secrets:

```json
"AppSettings": {
"AiApiKey": "your-openrouter-key",
"AiBaseUrl": "https://openrouter.ai/api/v1",
"AiModelName": "mistralai/mistral-small-3.2-24b-instruct"
}
```

The AppHost passes these to the web app.

**Docker Compose**, in `docker-compose/.env` (see [Docker Compose Deployment](docker-compose-deployment.md)):

```bash
AI_API_KEY=your-openrouter-key
AI_BASE_URL=https://openrouter.ai/api/v1
AI_MODEL_NAME=mistralai/mistral-small-3.2-24b-instruct
```

`note-compose.yaml` maps them to `AppSettings__AiApiKey`, `AppSettings__AiBaseUrl` and `AppSettings__AiModelName` on the `blazor-app` service.
2 changes: 2 additions & 0 deletions docs/docker-compose-deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ cp .env-sample docker-compose/.env

Edit `docker-compose/.env` and set all required values.

For the AI provider (`AI_API_KEY`, `AI_BASE_URL`, `AI_MODEL_NAME`), see [AI Provider Setup](ai-provider-setup.md). You can also leave them empty and set the provider on the Settings page instead.

Important Keycloak values for NoteBookmark:

- `KEYCLOAK_AUTHORITY` (for example `http://localhost:8080/realms/notebookmark`)
Expand Down
Loading
Loading