### Docker Compose Configuration Example Source: https://docs.papra.app/self-hosting/using-docker-compose An example of a docker-compose.yml file content for deploying Papra. This configuration is intended for users who prefer declarative configurations or need to integrate Papra into a broader service stack, supporting rootless setup. ```yaml version: "3.8" services: papra: image: ghcr.io/papra-hq/papra:latest container_name: papra ports: - "8080:8080" volumes: - ./app-data/db:/app/db - ./app-data/documents:/app/documents environment: - PAPRA_PORT=8080 - PAPRA_DB_PATH=/app/db - PAPRA_DOCUMENTS_PATH=/app/documents restart: unless-stopped ``` -------------------------------- ### Setup Custom OAuth2 Providers Guide Source: https://docs.papra.app/guides/setup-custom-oauth2-providers A markdown guide detailing the process of configuring custom OAuth2 providers for authentication within a Papra instance. It references the Better Auth Generic OAuth plugin for advanced configurations and outlines prerequisites and basic setup steps. ```markdown Setup Custom OAuth2 Providers ============================= This guide will show you how to configure custom OAuth2 providers for authentication in your Papra instance. Note Papra’s OAuth2 implementation is based on the [Better Auth Generic OAuth plugin](https://www.better-auth.com/docs/plugins/generic-oauth). For more detailed information about the configuration options and advanced usage, please refer to their documentation. Prerequisites ------------- [Section titled “Prerequisites”](#prerequisites) In order to follow this guide, you need: * A custom OAuth2 provider * An accessible Papra instance * Basic understanding of OAuth2 flows Configuration ------------- ``` -------------------------------- ### Get Help for Papra CLI Commands Source: https://docs.papra.app/resources/cli Access help information for any Papra CLI command. Using the `--help` flag provides detailed usage instructions, available options, and examples for the main CLI or specific subcommands like 'config' and 'documents'. ```shell papra --help papra config --help papra documents --help ``` -------------------------------- ### Get Help with Papra CLI Commands Source: https://papra.app/blog/papra-04 Examples of using the `--help` flag to retrieve detailed information about the Papra CLI and its subcommands. This is useful for understanding available options and syntax. ```shell papra --help ``` ```shell papra config --help ``` ```shell papra documents --help ``` -------------------------------- ### PostHog Analytics Initialization Source: https://docs.papra.app/self-hosting/using-docker Initializes the PostHog analytics service with a provided API key and host configuration. This snippet ensures analytics tracking is set up for the application. ```javascript posthog.init('phc_gYxH8GEgu7w2H8cjMu3fFthDbmZfvR0MJFGJSsmHLYX', { api_host: 'https://jasmine.papra.app', person_profiles: 'identified_only' // or 'always' to create profiles for anonymous users as well }) ``` -------------------------------- ### Papra JSON Configuration Example Source: https://docs.papra.app/self-hosting/configuration An example of a Papra configuration file in JSON format. It includes a schema reference for IDE autocompletion and defines server, client, and authentication settings. ```json { "$schema": "https://docs.papra.app/papra-config-schema.json", "server": { "baseUrl": "https://papra.example.com" }, "client": { "baseUrl": "https://papra.example.com" }, "auth": { "secret": "your-secret-key", "isRegistrationEnabled": true } } ``` -------------------------------- ### Papra Docker Installation - Verify Docker Source: https://docs.papra.app/self-hosting/using-docker Command to verify the Docker installation on the host system. This is a prerequisite for deploying Papra using Docker. ```shell docker --version ``` -------------------------------- ### Papra YAML Configuration Example Source: https://docs.papra.app/self-hosting/configuration An example of a Papra configuration file written in YAML format. It demonstrates how to set server base URLs, CORS origins, client base URLs, and authentication secrets, including enabling registration. ```yaml server: baseUrl: https://papra.example.com corsOrigins: * client: baseUrl: https://papra.example.com auth: secret: your-secret-key isRegistrationEnabled: true ``` -------------------------------- ### Papra Docker Compose Setup Command Source: https://docs.papra.app/docker-compose-generator Shell commands to set up the necessary directories for Papra's persistent data and then start the Docker Compose services in detached mode. This prepares the environment and launches the Papra application. ```bash mkdir -p ./app-data/{db,documents} && docker compose up -d ``` -------------------------------- ### Deploy Email Worker with Wrangler Source: https://docs.papra.app/guides/intake-emails-with-cloudflare-email-workers Instructions for cloning the email proxy repository, installing dependencies, building the worker, and deploying it using the Wrangler CLI. This method requires Node.js v22 and pnpm. ```shell git clone https://github.com/papra-hq/email-proxy.git cd email-proxy pnpm install pnpm build pnpm deploy ``` -------------------------------- ### Launch Papra with Default Configuration Source: https://docs.papra.app/self-hosting/using-docker Starts a Papra container in detached mode, assigning it a name, configuring automatic restarts, and mapping the web interface port. This command uses the latest rootless image by default. ```docker docker run -d \ --name papra \ --restart unless-stopped \ -p 1221:1221 \ ghcr.io/papra-hq/papra:latest ``` -------------------------------- ### Using Cadence-MQ with LibSQL Source: https://papra.app/blog/introducing-cadence-mq This snippet demonstrates how to set up and use Cadence-MQ with a LibSQL backend. It covers installing necessary packages, initializing the LibSQL client and the Cadence-MQ queue, registering a task handler, and scheduling a job. ```bash pnpm install @cadence-mq/core @cadence-mq/driver-libsql ``` ```javascript import { createQueue } from '@cadence-mq/core'; import { createLibSqlDriver } from '@cadence-mq/driver-libsql'; import { createClient } from '@libsql/client'; const client = createClient({ url: 'file:./cadence-mq.db' }); const queue = createQueue({ driver: createLibSqlDriver({ client }) }); queue.registerTask({ name: 'send-welcome-email', handler: async ({ data }) => { console.log(`Sending welcome email to ${data.email}`); }, }); queue.startWorker({ workerId: 'worker-1' }); await queue.scheduleJob({ taskName: 'send-welcome-email', data: { email: '[email protected]' }, }); ``` -------------------------------- ### Starlight Theme Provider Setup Source: https://docs.papra.app/resources/troubleshooting Manages the Starlight theme by reading from localStorage or user preferences, applying the theme to the document, and providing methods to update theme pickers. It ensures consistent theming across the application. ```javascript window.StarlightThemeProvider = (() => { const storedTheme = typeof localStorage !== 'undefined' && localStorage.getItem('starlight-theme'); const theme = storedTheme || (window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark'); document.documentElement.dataset.theme = theme === 'light' ? 'light' : 'dark'; return { updatePickers(theme = storedTheme || 'auto') { document.querySelectorAll('starlight-theme-select').forEach((picker) => { const select = picker.querySelector('select'); if (select) select.value = theme; /** @type {HTMLTemplateElement | null} */ const tmpl = document.querySelector(`#theme-icons`); const newIcon = tmpl && tmpl.content.querySelector('.' + theme); if (newIcon) { const oldIcon = picker.querySelector('svg.label-icon'); if (oldIcon) { oldIcon.replaceChildren(...newIcon.cloneNode(true).childNodes); } } }); }, }; })(); ``` -------------------------------- ### Starlight Theme Provider Source: https://docs.papra.app/self-hosting/using-docker Manages theme settings for the Starlight documentation theme. It handles storing the user's theme preference in local storage and applying it based on system preferences or explicit user selection. ```javascript window.StarlightThemeProvider = (() => { const storedTheme = typeof localStorage !== 'undefined' && localStorage.getItem('starlight-theme'); const theme = storedTheme || (window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark'); document.documentElement.dataset.theme = theme === 'light' ? 'light' : 'dark'; return { updatePickers(theme = storedTheme || 'auto') { document.querySelectorAll('starlight-theme-select').forEach((picker) => { const select = picker.querySelector('select'); if (select) select.value = theme; /** @type {HTMLTemplateElement | null} */ const tmpl = document.querySelector(`#theme-icons`); const newIcon = tmpl && tmpl.content.querySelector('.' + theme); if (newIcon) { const oldIcon = picker.querySelector('svg.label-icon'); if (oldIcon) { oldIcon.replaceChildren(...newIcon.cloneNode(true).childNodes); } } }); }, }; })(); ``` -------------------------------- ### Initialize Papra CLI Configuration Source: https://docs.papra.app/resources/cli Initializes the Papra CLI configuration by prompting the user for essential details such as the Papra instance URL and API key. This setup is crucial for authenticating and connecting to your Papra account. ```shell papra config init ``` -------------------------------- ### Papra Docker Compose Service Setup Source: https://docs.papra.app/guides/setup-ingestion-folder Configures the Papra service within `docker-compose.yml`, specifying the image, restart policy, port mapping, environment variables for ingestion, volume mounts for data and ingestion, and user. ```docker-compose.yml services: papra: container_name: papra image: ghcr.io/papra-hq/papra:latest restart: unless-stopped ports: - "1221:1221" environment: - INGESTION_FOLDER_IS_ENABLED=true volumes: - ./app-data:/app/app-data - :/app/ingestion user: "${UID}:${GID}" ``` -------------------------------- ### Initialize Posthog Analytics Source: https://docs.papra.app/guides/setup-custom-oauth2-providers Initializes the Posthog analytics service with a given API key and configuration options. This snippet sets up event tracking and user profile management for the application. ```javascript function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.crossOrigin="anonymous",p.async=!0,p.src=s.api_host.replace(".i.posthog.com","-assets.i.posthog.com")+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="init capture register register_once register_for_session unregister unregister_for_session getFeatureFlag getFeatureFlagPayload isFeatureEnabled reloadFeatureFlags updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures on onFeatureFlags onSessionId getSurveys getActiveMatchingSurveys renderSurvey canRenderSurvey identify setPersonProperties group resetGroups setPersonPropertiesForFlags resetPersonPropertiesForFlags setGroupPropertiesForFlags resetGroupPropertiesForFlags reset get_distinct_id getGroups get_session_id get_session_replay_url alias set_config startSessionRecording stopSessionRecording sessionRecordingStarted captureException loadToolbar get_property getSessionProperty createPersonProfile opt_in_capturing opt_out_capturing has_opted_in_capturing has_opted_out_capturing debug getPageViewId captureTraceFeedback captureTraceMetric".split(" "),n=0;n/ touch //hello.txt ``` -------------------------------- ### Install Papra CLI Source: https://papra.app/blog/papra-04 Instructions for installing the Papra CLI globally using npm or yarn. This makes the command-line tools available system-wide. ```shell npm install -g @papra/cli ``` ```shell yarn add -g @papra/cli ``` -------------------------------- ### Install Papra API SDK Source: https://papra.app/blog/papra-04 Installs the official Papra SDK for JavaScript and TypeScript applications using package managers like pnpm, npm, or yarn. ```bash pnpm install @papra/api-sdk # or npm install @papra/api-sdk # or yarn add @papra/api-sdk ``` -------------------------------- ### Initialize PostHog Analytics Source: https://docs.papra.app/self-hosting/using-docker-compose Initializes the PostHog analytics service with a specific API host and configuration. This snippet sets up tracking for the application. ```javascript function(t,e){var o,n,p,r;e.__SV|| (window.posthog=e,e._i=[],e.init=function(i,s,a){ function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}} (p=t.createElement("script")).type="text/javascript",p.crossOrigin="anonymous",p.async=!0,p.src=s.api_host.replace(".i.posthog.com","-assets.i.posthog.com")+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r); var u=e; void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e}, u.people.toString=function(){return u.toString(1)+".people (stub)"}, o="init capture register register_once register_for_session unregister unregister_for_session getFeatureFlag getFeatureFlagPayload isFeatureEnabled reloadFeatureFlags updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures on onFeatureFlags onSessionId getSurveys getActiveMatchingSurveys renderSurvey canRenderSurvey identify setPersonProperties group resetGroups setPersonPropertiesForFlags resetPersonPropertiesForFlags setGroupPropertiesForFlags resetGroupPropertiesForFlags reset get_distinct_id getGroups get_session_id get_session_replay_url alias set_config startSessionRecording stopSessionRecording sessionRecordingStarted captureException loadToolbar get_property getSessionProperty createPersonProfile opt_in_capturing opt_out_capturing has_opted_in_capturing has_opted_out_capturing clear_opt_in_out_capturing debug getPageViewId captureTraceFeedback captureTraceMetric".split(" "),n=0;n/documents \ -H "Authorization: Bearer " \ -H "Content-Type: multipart/form-data" \ -F "[email protected]" ``` -------------------------------- ### Simplify App Base URL Configuration Source: https://papra.app/blog/papra-07 Sets the APP_BASE_URL environment variable to simplify configuration. When defined, it overrides both SERVER_BASE_URL and CLIENT_BASE_URL, streamlining setup for Papra deployments. ```env APP_BASE_URL= ``` -------------------------------- ### PostHog Initialization Source: https://papra.app/blog/introducing-cadence-mq Initializes the PostHog analytics service with an API key and host. This snippet demonstrates how to integrate PostHog tracking into a Node.js application. ```javascript var apiKey = "phc_gYxH8GEgu7w2H8cjMu3fFthDbmZfvR0MJFGJSsmHLYX"; var apiHost = "https://jasmine.papra.app"; !function(t,e){ var o,n,p,r; e.__SV || (window.posthog = e, e._i = [], e.init = function(i, s, a) { function g(t, e) { var o = e.split("."); 2 == o.length && (t = t[o[0]], e = o[1]), t[e] = function() { t.push([e].concat(Array.prototype.slice.call(arguments, 0))) } } (p = t.createElement("script")).type = "text/javascript", p.crossOrigin = "anonymous", p.async = !0, p.src = s.api_host.replace(".i.posthog.com", "-assets.i.posthog.com") + "/static/array.js"; (r = t.getElementsByTagName("script")[0]).parentNode.insertBefore(p, r); var u = e; void 0 !== a ? u = e[a] = [] : a = "posthog", u.people = u.people || [], u.toString = function(t) { var e = "posthog"; return "posthog" !== a && (e += "." + a), t || (e += " (stub)"), e }, u.people.toString = function() { return u.toString(1) + ".people (stub)" }, o = "init capture register register_once register_for_session unregister unregister_for_session getFeatureFlag getFeatureFlagPayload isFeatureEnabled reloadFeatureFlags updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures on onFeatureFlags onSessionId getSurveys getActiveMatchingSurveys renderSurvey canRenderSurvey getNextSurveyStep identify setPersonProperties group resetGroups setPersonPropertiesForFlags resetPersonPropertiesForFlags setGroupPropertiesForFlags resetGroupPropertiesForFlags reset get_distinct_id getGroups get_session_id get_session_replay_url alias set_config startSessionRecording stopSessionRecording sessionRecordingStarted captureException loadToolbar get_property getSessionProperty createPersonProfile opt_in_capturing opt_out_capturing has_opted_in_capturing has_opted_out_capturing clear_opt_in_out_capturing debug getPageViewId".split(" "), n = 0; n < o.length; n++) g(u, o[n]); e._i.push([i, s, a]) }), e.__SV = 1 }(document, window.posthog || []); posthog.init(apiKey, { api_host: apiHost, person_profiles: 'identified_only' }); ``` -------------------------------- ### Update Papra Container Source: https://docs.papra.app/self-hosting/using-docker Updates the Papra application by pulling the latest Docker image and then recreating the container. This process ensures that security patches and new features are applied. ```docker # Pull latest image from GHCR docker pull ghcr.io/papra-hq/papra:latest # Or pull from Docker Hub # docker pull corentinth/papra:latest # After pulling, you would typically stop and remove the old container and run a new one with the same configuration. ``` -------------------------------- ### Apply Sidebar Scroll Restoration Source: https://docs.papra.app/guides/setup-custom-oauth2-providers Applies the stored scroll position to the sidebar element. This script runs after the page has loaded and restores the scroll position if it was previously saved in sessionStorage. ```javascript (() => { const scroller = document.getElementById('starlight__sidebar'); if (!window._starlightScrollRestore || !scroller) return; scroller.scrollTop = window._starlightScrollRestore; delete window._starlightScrollRestore; })(); ``` -------------------------------- ### Starlight Theme Selector Logic Source: https://docs.papra.app/self-hosting/using-docker This JavaScript code manages the theme selection for the Starlight documentation theme. It handles storing the user's preference in localStorage, applying the theme to the document, and updating the theme based on system preferences or user interaction. It also defines a custom element for the theme selector. ```javascript StarlightThemeProvider.updatePickers() const n="starlight-theme"; function c(e){ return e==="auto"||e==="dark"||e==="light"?e:"auto" } function l(){ return c(typeof localStorage<"u"&&localStorage.getItem(n)) } function i(e){ typeof localStorage<"u"&&localStorage.setItem(n,e==="light"||e==="dark"?e:"") } function s(){ return matchMedia("(prefers-color-scheme: light)").matches?"light":"dark" } function t(e){ StarlightThemeProvider.updatePickers(e), document.documentElement.dataset.theme=e==="auto"?s():e, i(e) } matchMedia("(prefers-color-scheme: light)").addEventListener("change",()=>{ l()==="auto"&&t("auto") }); customElements.define("starlight-rapide-theme-select",class extends HTMLElement{ constructor(){ super(), t(l()); const a=this.querySelector("button"); a?.addEventListener("click",()=>{ const o=c(document.documentElement.dataset.theme), r=o==="dark"?"light":o==="light"?"dark":"auto"; t(r), a?.setAttribute("aria-label",`${r} theme`) }) } }); ``` -------------------------------- ### Troubleshooting: Database Directory Permissions Source: https://docs.papra.app/resources/troubleshooting Addresses a common error where the server fails to create the database directory due to insufficient permissions. Provides solutions such as manually creating the directory, ensuring correct ownership, or running the server as root (not recommended). ```markdown Troubleshooting =============== You can find here some common issues and how to fix them. If you encounter an issue that is not listed here, please [open an issue](https://github.com/papra-hq/papra/issues/new/choose) or [join our Discord](https://papra.app/discord). Failed to ensure that the database directory exists --------------------------------------------------- [Section titled “Failed to ensure that the database directory exists”](#failed-to-ensure-that-the-database-directory-exists) Upon starting the server or a script, you may encounter this error Failed to ensure that the database directory exists, error while creating the directoryError: EACCES: permission denied, mkdir './app-data/db' Before accessing the DB sqlite file, the server will try to ensure that the database directory exists, and if it doesn’t, it try will create it. But in case of insufficient permissions, it will fail. To fix this, you can either: * Create the directory manually `mkdir -p /db` * Ensure that the directory is owned by the user running the container * Run the server as root (not recommended) [Edit page](https://github.com/papra-hq/papra/edit/main/apps/docs/src/content/docs/04-resources/01-troubleshooting.mdx) ``` -------------------------------- ### Starlight Icon Styles Source: https://docs.papra.app/guides/intake-emails-with-owlrelay Styles for Starlight icons, setting their color, font size, and dimensions using CSS variables. Ensures icons scale appropriately within the UI. ```css svg:where(.astro-vde4smz7){color:var(--sl-icon-color);font-size:var(--sl-icon-size, 1em);width:1em;height:1em}} ``` -------------------------------- ### Sidebar Scroll Restoration Source: https://docs.papra.app/guides/intake-emails-with-owlrelay Restores the scroll position of the sidebar element after the page has loaded. It retrieves the stored scroll position from `window._starlightScrollRestore` and applies it to the sidebar element with the ID 'starlight__sidebar'. ```javascript (() => { const scroller = document.getElementById('starlight__sidebar'); if (!window._starlightScrollRestore || !scroller) return; scroller.scrollTop = window._starlightScrollRestore; delete window._starlightScrollRestore; })(); ``` -------------------------------- ### Initialize Posthog Analytics Source: https://docs.papra.app/guides/intake-emails-with-owlrelay Initializes the Posthog analytics service with a specific API host and configuration. This snippet includes the necessary JavaScript code to embed the Posthog tracking script and configure it for the application, enabling event tracking and user profiling. ```javascript function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.crossOrigin="anonymous",p.async=!0,p.src=s.api_host.replace(".i.posthog.com","-assets.i.posthog.com")+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="init capture register register_once register_for_session unregister unregister_for_session getFeatureFlag getFeatureFlagPayload isFeatureEnabled reloadFeatureFlags updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures on onFeatureFlags onSessionId getSurveys getActiveMatchingSurveys renderSurvey canRenderSurvey identify setPersonProperties group resetGroups setPersonPropertiesForFlags resetPersonPropertiesForFlags setGroupPropertiesForFlags resetGroupPropertiesForFlags reset get_distinct_id getGroups get_session_id get_session_replay_url alias set_config startSessionRecording stopSessionRecording sessionRecordingStarted captureException loadToolbar get_property getSessionProperty createPersonProfile opt_in_capturing opt_out_capturing has_opted_in_capturing has_opted_out_capturing clear_opt_in_out_capturing debug getPageViewId captureTraceFeedback captureTraceMetric".split(" "),n=0;n