diff --git a/.env.example b/.env.example
index 7ef00fa58..5b70c78c2 100644
--- a/.env.example
+++ b/.env.example
@@ -1,4 +1,6 @@
-# Required Settings
+# Configuration reference: http://docs.postiz.com/configuration/reference
+
+# === Required Settings
DATABASE_URL="postgresql://postiz-user:postiz-password@localhost:5432/postiz-db-local"
REDIS_URL="redis://localhost:6379"
JWT_SECRET="random string for your JWT secret, make it long"
@@ -6,11 +8,19 @@ FRONTEND_URL="http://localhost:4200"
NEXT_PUBLIC_BACKEND_URL="http://localhost:3000"
BACKEND_INTERNAL_URL="http://localhost:3000"
-# Optional. Your upload directory path if you host your files locally.
-UPLOAD_DIRECTORY="/opt/postiz/uploads/"
+## These are dummy values, you must create your own from Cloudflare.
+## Remember to set your public internet IP address in the allow-list for the API token.
+##
+## Cloudflare is currently required to save things like social media avatars for accounts.
+CLOUDFLARE_ACCOUNT_ID="QhcMSXQyPuMCRpSQcSYdEuTYgHeCXHbu"
+CLOUDFLARE_ACCESS_KEY="dcfCMSuFEeCNfvByUureMZEfxWJmDqZe"
+CLOUDFLARE_SECRET_ACCESS_KEY="zTTMXBmtyLPwHEdpACGHgDgzRTNpTJewiNriLnUS"
+CLOUDFLARE_BUCKETNAME="postiz"
+CLOUDFLARE_BUCKET_URL="https://QhcMSXQyPuMCRpSQcSYdEuTYgHeCXHbu.r2.cloudflarestorage.com/"
+CLOUDFLARE_REGION="auto"
+
-# Optional: your upload directory slug if you host your files locally.
-NEXT_PUBLIC_UPLOAD_STATIC_DIRECTORY="/opt/postiz/uploads/"
+# === Common optional Settings
## This is a dummy key, you must create your own from Resend.
## If this variable exists, user activation is required.
@@ -19,14 +29,12 @@ NEXT_PUBLIC_UPLOAD_STATIC_DIRECTORY="/opt/postiz/uploads/"
#EMAIL_FROM_ADDRESS=""
#EMAIL_FROM_NAME=""
-## These are dummy values, you must create your own from Cloudflare.
-## Remember to set your public internet IP address in the allow-list for the API token.
-CLOUDFLARE_ACCOUNT_ID="QhcMSXQyPuMCRpSQcSYdEuTYgHeCXHbu"
-CLOUDFLARE_ACCESS_KEY="dcfCMSuFEeCNfvByUureMZEfxWJmDqZe"
-CLOUDFLARE_SECRET_ACCESS_KEY="zTTMXBmtyLPwHEdpACGHgDgzRTNpTJewiNriLnUS"
-CLOUDFLARE_BUCKETNAME="postiz"
-CLOUDFLARE_BUCKET_URL="https://QhcMSXQyPuMCRpSQcSYdEuTYgHeCXHbu.r2.cloudflarestorage.com/"
-CLOUDFLARE_REGION="auto"
+# Your upload directory path if you host your files locally, otherwise Cloudflare will be used.
+#UPLOAD_DIRECTORY="/opt/postiz/uploads/"
+
+# Your upload directory path if you host your files locally, otherwise Cloudflare will be used.
+#NEXT_PUBLIC_UPLOAD_STATIC_DIRECTORY="/opt/postiz/uploads/"
+
# Social Media API Settings
X_API_KEY=""
@@ -57,7 +65,7 @@ DRIBBBLE_CLIENT_SECRET=""
# Misc Settings
OPENAI_API_KEY=""
NEXT_PUBLIC_DISCORD_SUPPORT=""
-NEXT_PUBLIC_POLOTNO="Polotno key for the gallery"
+NEXT_PUBLIC_POLOTNO=""
# Payment settings
FEE_AMOUNT=0.05
diff --git a/apps/docs b/apps/docs
deleted file mode 160000
index 3e75b2446..000000000
--- a/apps/docs
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 3e75b2446ece2de4542143937923b0be6a7023be
diff --git a/apps/docs/.gitignore b/apps/docs/.gitignore
new file mode 100644
index 000000000..5ddadd215
--- /dev/null
+++ b/apps/docs/.gitignore
@@ -0,0 +1,8 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# misc
+.DS_Store
+*.pem
+__snapshots__
+@generated
+node_modules
\ No newline at end of file
diff --git a/apps/docs/.kodiak.toml b/apps/docs/.kodiak.toml
new file mode 100644
index 000000000..854dd8315
--- /dev/null
+++ b/apps/docs/.kodiak.toml
@@ -0,0 +1,18 @@
+# .kodiak.toml
+version = 1
+
+[merge]
+automerge_label = "automerge"
+require_automerge_label = false
+method = "squash"
+delete_branch_on_merge = true
+optimistic_updates = true
+prioritize_ready_to_merge = true
+notify_on_conflict = false
+
+[merge.message]
+title = "pull_request_title"
+body = "pull_request_body"
+include_pr_number = true
+body_type = "markdown"
+strip_html_comments = true
diff --git a/apps/docs/components/snippets/docker-envvar-apps.mdx b/apps/docs/components/snippets/docker-envvar-apps.mdx
new file mode 100644
index 000000000..967daf402
--- /dev/null
+++ b/apps/docs/components/snippets/docker-envvar-apps.mdx
@@ -0,0 +1,7 @@
+## Controlling container services
+The environment variable POSTIZ_APPS defaults to "", which means that all
+services will be started in a single container. However, you can only start
+specific services within the docker container by changing this environement variable.
+
+For most deployments, starting all services is fine. To scale out, you might want
+to start individual containers for "frontend", "backend", "worker" and "cron".
diff --git a/apps/docs/components/snippets/earlydoc.mdx b/apps/docs/components/snippets/earlydoc.mdx
new file mode 100644
index 000000000..5664954f1
--- /dev/null
+++ b/apps/docs/components/snippets/earlydoc.mdx
@@ -0,0 +1,8 @@
+import { Callout } from 'nextra/components'
+
+
+ **NOTE:** This page is marked "earlydoc", or "early documentation", which means it might
+ be brief, or contain information about parts of the app that are under heavy development.
+ If you encounter issues with instructions found here, please check out the [support](/support)
+ page for options.
+
diff --git a/apps/docs/components/snippets/snippet-example.mdx b/apps/docs/components/snippets/snippet-example.mdx
new file mode 100644
index 000000000..0a4f5984a
--- /dev/null
+++ b/apps/docs/components/snippets/snippet-example.mdx
@@ -0,0 +1,7 @@
+import { Callout } from "nextra/components";
+
+## My Snippet
+
+
+This is an example of a reusable snippet
+
diff --git a/apps/docs/configuration/reference.mdx b/apps/docs/configuration/reference.mdx
new file mode 100644
index 000000000..b53f62f28
--- /dev/null
+++ b/apps/docs/configuration/reference.mdx
@@ -0,0 +1,39 @@
+---
+title: Configuration Reference
+---
+
+At the moment, Postiz is entirely configured by environment variables. It is
+important to understand that any configuration change to environment variables
+will require an application restart.
+
+An example file of the most used configuration settings can be found here; [example postiz.env file](https://raw.githubusercontent.com/gitroomhq/postiz-app/main/.env.example)
+
+## Required Settings
+
+### `DATABASE_URL`
+
+eg: `postgresql://postiz-user:postiz-password@localhost:5432/postiz-db-local`
+
+Postgres is not strictly necessary, Postiz uses Prisma to connect to the database, so technically mariadb or other databases could be used.
+
+### `REDIS_URL`
+
+eg: `redis://localhost:6379`
+
+### `JWT_SECRET`
+
+A random string that should be unique for every installation, this is used to secure your JWT auth tokens.
+
+### `FRONTEND_URL`
+
+eg: `http://postiz.example.lan:4200`
+
+### `NEXT_PUBLIC_BACKEND_URL`
+
+eg: `http://postiz.example.lan:3000`
+
+### `BACKEND_INTERNAL_URL`
+
+If running everything in the same host/container: `http://localhost:3000`
+
+
diff --git a/apps/docs/globals.css b/apps/docs/globals.css
new file mode 100644
index 000000000..930ddb7b7
--- /dev/null
+++ b/apps/docs/globals.css
@@ -0,0 +1,8 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+article a {
+ color: white !important;
+ font-weight: bold;
+}
\ No newline at end of file
diff --git a/apps/docs/installation/development.mdx b/apps/docs/installation/development.mdx
new file mode 100644
index 000000000..015b9bf18
--- /dev/null
+++ b/apps/docs/installation/development.mdx
@@ -0,0 +1,164 @@
+---
+title: Development Environment
+---
+
+This is currently the recommended option to install Postiz in a supportable configuration. The docker images are in active and heavy development for now.
+
+## Tested configurations
+
+- MacOS
+- Linux (Fedora 40)
+
+Naturally you can use these instructions to setup a development environment on any platform, but there may not be much experience in the community to help you with any issues you may encounter.
+
+## Prerequisites
+
+This guide will ask you to install & configure several services exaplained below.
+
+### Prerequisite Cloud Services
+
+- **[Cloudflare R2](https://cloudflare.com)** - for uploads (optional, can use local machine).
+- **Social Media API details** - various API keys and secrets (more details later) for services you want to use; reddit, X, Instagram, etc..
+
+### Optional Cloud Services
+
+- **[Resend account](https://resend.com)** - for user activation and email notifications.
+
+### Prerequisite Local Services
+
+- **Node.js** - for running the code! (version 18+)
+- **PostgreSQL** - or any other SQL database (instructions beleow suggest Docker)
+- **Redis** - for handling worker queues (instructions below suggest Docker)
+
+We have some messages from users who are using Windows, which should work, but they are not tested well yet.
+
+## Installation Instructions
+
+### NodeJS (version 18+)
+
+A complete guide of how to install NodeJS can be found [here](https://nodejs.org/en/download/).
+
+### PostgreSQL (or any other SQL database) & Redis
+
+You can choose **Option A** to **Option B** to install the database.
+
+#### Option A) Postgres and Redis as Single containers
+
+You can install [Docker](https://www.docker.com/products/docker-desktop) and run:
+
+```bash Terminal
+docker run -e POSTGRES_USER=root -e POSTGRES_PASSWORD=your_password --name postgres -p 5432:5432 -d postgres
+docker run --name redis -p 6379:6379 -d redis
+```
+
+#### Option B) Postgres and Redis as docker-compose
+
+Download the [docker-compose.yaml file here](https://raw.githubusercontent.com/gitroomhq/postiz-app/main/docker-compose.dev.yaml),
+or grab it from the repository in the next step.
+
+```bash Terminal
+docker compose -f "docker-compose.dev.yaml" up
+```
+
+## Build Postiz
+
+
+
+```bash Terminal
+git clone https://github.com/gitroomhq/gitroom
+```
+
+
+
+Copy the `.env.example` file to `.env` and fill in the values
+
+An example file of the most used configuration settings can be found here; [example postiz.env file](https://raw.githubusercontent.com/gitroomhq/postiz-app/main/.env.example)
+
+There is also a [configuration reference](/configuration/reference) page that goes into more detail.
+
+```bash .env
+# Required Settings
+DATABASE_URL="postgresql://postiz-user:postiz-password@localhost:5432/postiz-db-local"
+REDIS_URL="redis://localhost:6379"
+JWT_SECRET="random string for your JWT secret, make it long"
+FRONTEND_URL="http://localhost:4200"
+NEXT_PUBLIC_BACKEND_URL="http://localhost:3000"
+BACKEND_INTERNAL_URL="http://localhost:3000"
+
+# Optional. Your upload directory path if you host your files locally.
+UPLOAD_DIRECTORY="/opt/postiz/uploads/"
+
+# Optional: your upload directory slug if you host your files locally.
+NEXT_PUBLIC_UPLOAD_STATIC_DIRECTORY=""
+
+## This is a dummy key, you must create your own from Resend.
+## If this variable exists, user activation is required.
+## If it is commented out, users are activated automatically.
+#RESEND_API_KEY="RzeTwHijvxvPUerScFcenUZUALuQJzSaGSMJ"
+
+## These are dummy values, you must create your own from Cloudflare.
+## Remember to set your public internet IP address in the allow-list for the API token.
+CLOUDFLARE_ACCOUNT_ID="QhcMSXQyPuMCRpSQcSYdEuTYgHeCXHbu"
+CLOUDFLARE_ACCESS_KEY="dcfCMSuFEeCNfvByUureMZEfxWJmDqZe"
+CLOUDFLARE_SECRET_ACCESS_KEY="zTTMXBmtyLPwHEdpACGHgDgzRTNpTJewiNriLnUS"
+CLOUDFLARE_BUCKETNAME="postiz"
+CLOUDFLARE_BUCKET_URL="https://QhcMSXQyPuMCRpSQcSYdEuTYgHeCXHbu.r2.cloudflarestorage.com/"
+CLOUDFLARE_REGION="auto"
+
+# Social Media API Settings
+X_API_KEY="Twitter API key for normal oAuth not oAuth2"
+X_API_SECRET="Twitter API secret for normal oAuth not oAuth2"
+LINKEDIN_CLIENT_ID="Linkedin Client ID"
+LINKEDIN_CLIENT_SECRET="Linkedin Client Secret"
+REDDIT_CLIENT_ID="Reddit Client ID"
+REDDIT_CLIENT_SECRET="Linkedin Client Secret"
+GITHUB_CLIENT_ID="GitHub Client ID"
+GITHUB_CLIENT_SECRET="GitHub Client Secret"
+
+
+# Developer Settings
+NX_ADD_PLUGINS=false
+IS_GENERAL="true" # required for now
+```
+
+
+
+
+```bash Terminal
+npm install
+```
+
+
+
+```bash Terminal
+npm run prisma-db-push
+```
+
+
+
+```bash Terminal
+npm run dev
+```
+
+
+
+If everything is running successfully, open http://localhost:4200 in your browser!
+
+If everything is not running - you had errors in the steps above, please head over to our [support](/support) page.
+
+## Next Steps
+
+
+
+ Learn the architecture of the project
+
+
+ Set up email for notifications
+
+
+ Set up github for authentication and sync
+
+
+ Set up providers such as Linkedin, X and Reddit
+
+
diff --git a/apps/docs/installation/docker-compose.mdx b/apps/docs/installation/docker-compose.mdx
new file mode 100644
index 000000000..8c422f018
--- /dev/null
+++ b/apps/docs/installation/docker-compose.mdx
@@ -0,0 +1,79 @@
+---
+title: Docker Compose
+---
+
+import EarlyDoc from '/snippets/earlydoc.mdx';
+import DockerEnvvarApps from '/snippets/docker-envvar-apps.mdx';
+import DockerEnvvarGeneral from '/snippets/docker-envvar-general.mdx';
+
+
+
+
+
+The container images will copy a file called `/config/postiz.env` to `/apps/.env` on startup.
+
+# Example `docker-compose.yml` file
+
+```yaml
+services:
+ postiz:
+ image: ghcr.io/gitroomhq/postiz-app:latest
+ container_name: postiz
+ restart: always
+ environment: # If you want to specify the variables in your compose file.
+ - DATABASE_URL="postgresql://postiz-user:postiz-password@localhost:5432/postiz-db-local"
+ - REDIS_URL="redis://localhost:6379"
+ - JWT_SECRET="random string for your JWT secret, make it long"
+ - FRONTEND_URL="http://localhost:4200"
+ - NEXT_PUBLIC_BACKEND_URL="http://localhost:3000"
+ - BACKEND_INTERNAL_URL="http://localhost:3000"
+ volumes:
+ - ./config:/config/ # If you want to specify the variables in your `postiz.env` file.
+ ports:
+ - 4200:4200
+ - 3000:3000
+ networks:
+ - postiz-network
+
+ postiz-postgres:
+ image: postgres:14.5
+ container_name: postiz-postgres
+ restart: always
+ environment:
+ POSTGRES_PASSWORD: postiz-local-pwd
+ POSTGRES_USER: postiz-local
+ POSTGRES_DB: postiz-db-local
+ volumes:
+ - postgres-volume:/var/lib/postgresql/data
+ ports:
+ - 5432:5432
+ networks:
+ - postiz-network
+ postiz-pg-admin:
+ image: dpage/pgadmin4
+ container_name: postiz-pg-admin
+ restart: always
+ ports:
+ - 8081:80
+ environment:
+ PGADMIN_DEFAULT_EMAIL: admin@admin.com
+ PGADMIN_DEFAULT_PASSWORD: admin
+ networks:
+ - postiz-network
+ postiz-redis:
+ image: redis:7.2
+ container_name: postiz-redis
+ restart: always
+ ports:
+ - 6379:6379
+
+volumes:
+ postgres-volume:
+ external: false
+
+networks:
+ postiz-network:
+ external: false
+```
+
+
diff --git a/apps/docs/installation/docker.mdx b/apps/docs/installation/docker.mdx
new file mode 100644
index 000000000..3ba5228b7
--- /dev/null
+++ b/apps/docs/installation/docker.mdx
@@ -0,0 +1,39 @@
+---
+title: Docker
+---
+
+import EarlyDoc from '/snippets/earlydoc.mdx';
+import DockerEnvvarApps from '/snippets/docker-envvar-apps.mdx';
+import DockerEnvvarGeneral from '/snippets/docker-envvar-general.mdx';
+
+
+
+
+
+The container images will copy a file called `/config/postiz.env` to `/apps/.env` on startup.
+
+# Create the container on command line
+
+It is recommended to have a local directory where you save your `postiz.env` file, such as `/myContainers/postiz/config`, which is mounted as a volume.
+
+```bash Using a configuration volume
+docker create --name postiz -v /myContainers/postiz/config:/config -p 4200:4200 -p 3000:3000 ghcr.io/gitroomhq/postiz-app:latest
+```
+
+Alternatively, you can specify the variables one by one at creation time. This approach is not recommended
+simply because it's a pain to manage, and sensitive keys get stored with the container definition, which is bad practice.
+
+```bash At creation-time (not recommended)
+docker create --name postiz \
+ -e DATABASE_URL=postgres://... \
+ -e REDIS_URL=redis:// \
+ -e JWT_SECRET \
+ ... \
+ -p 4200:4200 \
+ -p 3000:3000 \
+ ghcr.io/gitroomhq/postiz-app:latest
+```
+
+
+
+
diff --git a/apps/docs/lib/ScarfPixel.tsx b/apps/docs/lib/ScarfPixel.tsx
new file mode 100644
index 000000000..c0096cf28
--- /dev/null
+++ b/apps/docs/lib/ScarfPixel.tsx
@@ -0,0 +1,5 @@
+export function ScarfPixel() {
+ const SCARF_PIXEL_ID = process.env.SCARF_PIXEL_ID;
+ if (!SCARF_PIXEL_ID) return null;
+ return ;
+}
\ No newline at end of file
diff --git a/apps/docs/lib/hooks/useRB2B.tsx b/apps/docs/lib/hooks/useRB2B.tsx
new file mode 100644
index 000000000..33a107d08
--- /dev/null
+++ b/apps/docs/lib/hooks/useRB2B.tsx
@@ -0,0 +1,44 @@
+import { useEffect } from "react";
+
+export function useRB2B() {
+ useEffect(() => {
+ const RB2B_ID = process.env.RB2B_ID;
+
+ if (!RB2B_ID) {
+ return;
+ }
+
+ // @ts-ignore
+ !(function () {
+ var reb2b = ((window as any).reb2b = (window as any).reb2b || []);
+ if (reb2b.invoked) return;
+ reb2b.invoked = true;
+ reb2b.methods = ["identify", "collect"];
+ reb2b.factory = function (method) {
+ return function () {
+ var args = Array.prototype.slice.call(arguments);
+ args.unshift(method);
+ reb2b.push(args);
+ return reb2b;
+ };
+ };
+ for (var i = 0; i < reb2b.methods.length; i++) {
+ var key = reb2b.methods[i];
+ reb2b[key] = reb2b.factory(key);
+ }
+ reb2b.load = function (key) {
+ var script = document.createElement("script");
+ script.type = "text/javascript";
+ script.async = true;
+ script.src =
+ "https://s3-us-west-2.amazonaws.com/b2bjsstore/b/" +
+ key +
+ "/reb2b.js.gz";
+ var first = document.getElementsByTagName("script")[0];
+ first.parentNode?.insertBefore(script, first);
+ };
+ reb2b.SNIPPET_VERSION = "1.0.1";
+ reb2b.load(RB2B_ID);
+ })();
+ }, []);
+}
diff --git a/apps/docs/lib/hooks/useTailoredContent.tsx b/apps/docs/lib/hooks/useTailoredContent.tsx
new file mode 100644
index 000000000..6d114cccf
--- /dev/null
+++ b/apps/docs/lib/hooks/useTailoredContent.tsx
@@ -0,0 +1,29 @@
+import { createContext, useContext, useState, ReactNode } from "react";
+import { useLocalStorage } from "usehooks-ts";
+
+type TailordContextContextType = {
+ mode: "cloud" | "self-host";
+ setMode: (mode: "cloud" | "self-host") => void;
+};
+
+const TailoredContentContext = createContext(undefined);
+
+export const TailoredContentProvider = ({ children }: { children: ReactNode }) => {
+ const [mode, setMode] = useLocalStorage<"cloud" | "self-host">("copilotkit-cloud-or-self-hosting", "cloud");
+
+ return (
+
+ {children}
+
+ );
+};
+
+export const useTailoredContent = () => {
+ const context = useContext(TailoredContentContext);
+ if (context === undefined) {
+ throw new Error("useTailoredContent must be used within a TailoredContentProvider");
+ }
+ return context;
+};
diff --git a/apps/docs/lib/providers/PostHogProvider.tsx b/apps/docs/lib/providers/PostHogProvider.tsx
new file mode 100644
index 000000000..2a7824df0
--- /dev/null
+++ b/apps/docs/lib/providers/PostHogProvider.tsx
@@ -0,0 +1,66 @@
+import { PostHogProvider as PostHogProviderBase } from "posthog-js/react";
+import posthog from "posthog-js";
+import { useRouter } from "next/router";
+import { useEffect } from "react";
+import { useAuth } from "@clerk/nextjs";
+import { useSearchParams } from "next/navigation";
+
+const POSTHOG_KEY = process.env.POSTHOG_KEY;
+const POSTHOG_HOST = process.env.POSTHOG_HOST;
+
+if (typeof window !== "undefined") {
+ // Get search param
+ const searchParams = new URLSearchParams(window.location.search);
+ const sessionId = searchParams.get("session_id");
+
+ if (POSTHOG_KEY && POSTHOG_HOST) {
+
+ posthog.init(POSTHOG_KEY, {
+ api_host: POSTHOG_HOST,
+ person_profiles: "identified_only",
+ bootstrap: {
+ sessionID: sessionId ?? undefined,
+ },
+ // Enable debug mode in development
+ loaded: (posthog) => {
+ if (process.env.NODE_ENV === "development") posthog.debug();
+ },
+ });
+ }
+}
+
+export function PostHogProvider({ children }: { children: React.ReactNode }) {
+ const router = useRouter();
+ const { userId } = useAuth();
+ const searchParams = useSearchParams();
+
+ const sessionId = searchParams.get("session_id");
+
+ posthog?.set_config({
+ bootstrap: {
+ sessionID: sessionId ?? undefined,
+ },
+ });
+
+ useEffect(() => {
+ if (!POSTHOG_KEY || !POSTHOG_HOST) return;
+
+ const handleRouteChange = () => {
+ posthog?.capture("$pageview");
+ };
+
+ router.events.on("routeChangeComplete", handleRouteChange);
+
+ return () => {
+ router.events.off("routeChangeComplete", handleRouteChange);
+ };
+ }, []);
+
+ useEffect(() => {
+ if (userId) {
+ posthog?.identify(userId);
+ }
+ }, [userId]);
+
+ return {children};
+}
\ No newline at end of file
diff --git a/apps/docs/mint.json b/apps/docs/mint.json
new file mode 100644
index 000000000..4b375a4d9
--- /dev/null
+++ b/apps/docs/mint.json
@@ -0,0 +1,106 @@
+{
+ "$schema": "https://mintlify.com/schema.json",
+ "name": "Starter Kit",
+ "logo": {
+ "dark": "/logo/dark.png",
+ "light": "/logo/light.png"
+ },
+ "favicon": "/favicon.png",
+ "colors": {
+ "primary": "#000",
+ "light": "#612ad5",
+ "dark": "#000",
+ "anchors": {
+ "from": "#612ad5",
+ "to": "#612ad5"
+ }
+ },
+ "openapi": "https://api.postiz.com/docs-json",
+ "api": {
+ "baseUrl": "https://api.postiz.com"
+ },
+ "topbarLinks": [
+ {
+ "name": "Support",
+ "url": "mailto:nevo@postiz.com"
+ },
+ {
+ "name": "Cloud",
+ "url": "https://platform.postiz.com"
+ }
+ ],
+ "modeToggle": {
+ "default": "light"
+ },
+ "topbarCtaButton": {
+ "type": "github",
+ "url": "https://github.com/gitroomhq/postiz-app"
+ },
+ "anchors": [
+ {
+ "name": "Community",
+ "icon": "discord",
+ "url": "https://postiz.gitroom.com"
+ }
+ ],
+ "navigation": [
+ {
+ "group": "How to use Postiz",
+ "pages": [
+ "use/analytics",
+ {
+ "group": "Launches",
+ "pages": ["use/calendar", "use/scheduling"]
+ },
+ "use/settings",
+ "use/billing"
+ ]
+ },
+ {
+ "group": "Self Hosting",
+ "pages": [
+ "introduction",
+ "quickstart",
+ {
+ "group": "Install",
+ "pages": [
+ "installation/development",
+ "installation/docker",
+ "installation/docker-compose",
+ "installation/kubernetes-helm"
+ ]
+ },
+ {
+ "group": "Configuration",
+ "pages": [
+ "configuration/reference"
+ ]
+ },
+ "howitworks",
+ "emails",
+ "github",
+ {
+ "group": "Providers",
+ "pages": [
+ "providers/x/x",
+ "providers/linkedin/linkedin",
+ "providers/reddit/reddit",
+ "providers/articles"
+ ]
+ },
+ "support"
+ ]
+ },
+ {
+ "group": "Developer Guide",
+ "pages": [
+ "developer-guide/how-to-add-provider"
+ ]
+ }
+ ],
+ "footerSocials": {
+ "twitter": "https://twitter.com/nevodavid",
+ "github": "https://github.com/gitroomhq/postiz-app",
+ "linkedin": "https://www.linkedin.com/nevodavid"
+ }
+}
diff --git a/apps/docs/next-env.d.ts b/apps/docs/next-env.d.ts
new file mode 100644
index 000000000..4f11a03dc
--- /dev/null
+++ b/apps/docs/next-env.d.ts
@@ -0,0 +1,5 @@
+///
+///
+
+// NOTE: This file should not be edited
+// see https://nextjs.org/docs/basic-features/typescript for more information.
diff --git a/apps/docs/next-sitemap.config.js b/apps/docs/next-sitemap.config.js
new file mode 100644
index 000000000..85f4f1a6b
--- /dev/null
+++ b/apps/docs/next-sitemap.config.js
@@ -0,0 +1,6 @@
+/** @type {import('next-sitemap').IConfig} */
+module.exports = {
+ siteUrl: "https://docs.copilotkit.ai",
+ generateRobotsTxt: true, // (optional)
+ exclude: ["*/_meta.tsx"]
+}
\ No newline at end of file
diff --git a/apps/docs/next.config.mjs b/apps/docs/next.config.mjs
new file mode 100644
index 000000000..38897288c
--- /dev/null
+++ b/apps/docs/next.config.mjs
@@ -0,0 +1,21 @@
+import nextra from 'nextra';
+
+const withNextra = nextra({
+ theme: 'nextra-theme-docs',
+ themeConfig: './theme.config.tsx',
+ defaultShowCopyCode: true,
+})
+
+export default withNextra({
+ env: {
+ },
+ async redirects() {
+ return [
+ {
+ source: "/",
+ destination: "/introduction",
+ permanent: false,
+ }
+ ]
+ }
+});
diff --git a/apps/docs/pages/_404/[...path].tsx b/apps/docs/pages/_404/[...path].tsx
new file mode 100644
index 000000000..c395350b1
--- /dev/null
+++ b/apps/docs/pages/_404/[...path].tsx
@@ -0,0 +1,9 @@
+// This is needed for catch-all redirect of non existent rountes to the home page.
+// https://github.com/vercel/next.js/discussions/16749#discussioncomment-2992732
+export const Custom404 = () => ;
+
+export const getServerSideProps = () => {
+ return { redirect: { destination: "/", permanent: false } };
+};
+
+export default Custom404;
\ No newline at end of file
diff --git a/apps/docs/pages/_app.tsx b/apps/docs/pages/_app.tsx
new file mode 100644
index 000000000..3e1769761
--- /dev/null
+++ b/apps/docs/pages/_app.tsx
@@ -0,0 +1,16 @@
+import "../globals.css";
+import { AppProps } from "next/app";
+import { IBM_Plex_Sans } from "next/font/google";
+
+const plex = IBM_Plex_Sans({
+ subsets: ["latin"],
+ weight: ["400", "500", "600", "700"],
+});
+
+export default function App({ Component, pageProps }: AppProps) {
+ return (
+
+
+
+ );
+}
diff --git a/apps/docs/pages/_meta.json b/apps/docs/pages/_meta.json
new file mode 100644
index 000000000..d6e9e869e
--- /dev/null
+++ b/apps/docs/pages/_meta.json
@@ -0,0 +1,9 @@
+{
+ "introduction": "Introduction",
+ "howitworks": "How it works",
+ "quickstart": "Quickstart",
+ "installation": "Installation",
+ "providers": "Providers Configuration",
+ "emails": "Email Configuration",
+ "support": "Support"
+}
diff --git a/apps/docs/pages/emails.mdx b/apps/docs/pages/emails.mdx
new file mode 100644
index 000000000..e7c7ea455
--- /dev/null
+++ b/apps/docs/pages/emails.mdx
@@ -0,0 +1,18 @@
+---
+title: Email Notifications
+description: How to send notifications to users
+---
+
+Postiz uses Resend to send email notifications to users. Emails are currently
+required as part of the new-user creation process, which sends an activation
+email.
+
+* Register to [Resend](https://resend.com), and connect your domain.
+* Copy your API Key from the Resend control panel.
+* Open the .env file and edit the following line.
+
+```env
+RESEND_API_KEY=""
+```
+
+Feel free to contribute other providers to send email notifications.
diff --git a/apps/docs/pages/howitworks.mdx b/apps/docs/pages/howitworks.mdx
new file mode 100644
index 000000000..aa1fa7dc4
--- /dev/null
+++ b/apps/docs/pages/howitworks.mdx
@@ -0,0 +1,55 @@
+---
+title: How it works
+description: 'Learn the architecture of the project'
+---
+
+The entire project is built under [NX](https://nx.dev/) to have a monorepo with multiple projects.
+Unlike other NX project, this project has one `.env` file that is shared between all the apps.
+It makes it easier to develop and deploy the project.
+When deploying to websites like [Railway](https://railway.app) or [Heroku](https://heroku.com), you can use a shared environment variables for all the apps.
+
+**At the moment it has 6 projects:**
+
+- [Frontend](#frontend) - Provides the Web user interface, talks to the Backend.
+- [Backend](#backend) - Does all the real work, provides an API for the frontend, and posts work to the redis queue.
+- [Workers](#worker) - Consumes work from the Redis Queue.
+- [Cron](#cron) - Run jobs at scheduled times.
+- [Docs](#docs) - This documentation site!
+
+
+
+## Architecture
+### Frontend
+The frontend is built with [NextJS](https://nextjs.org/) and [TailwindCSS](https://tailwindcss.com/).
+It works directly with the Backend to:
+- Show analytics
+- Schedule posts
+- Manage users
+
+### Backend
+The backend is built with [NestJS](https://nestjs.com/) with a basic architecture of controllers, services, repositories and dtos.
+It uses [Prisma](https://www.prisma.io/) as an ORM to interact with the database.
+By default Prisma uses [Postgres](https://www.postgresql.org/) as a database, but it can be easily changed to any other database since there are no native queries.
+It uses Redis to schedule posts and run background jobs.
+
+### Cron
+The backend is built with [NestJS](https://nestjs.com/) and share components with the backend.
+At the moment the use of the cron is:
+- Refresh tokens from different social media platforms.
+- Check for trending change every hour and inform users about it.
+- Sync the amount of stars for every repository at the end of the day.
+
+### Worker
+The backend is built with [NestJS](https://nestjs.com/) and share components with the backend.
+At the moment the use of the worker is:
+- Post scheduled posts to social media platforms.
+- Perform multiple jobs coming from the cron.
+
+### Docs
+The documentation website is built with [Mintlify](https://www.mintlify.com/).
+The reference in the documentation is being auto-generated by the backend.
+NestJS has a built-in Swagger module that generates a JSON file with all the routes and their documentation.
+It makes it very easy to track API changes and deploy them.
diff --git a/apps/docs/pages/installation/development.mdx b/apps/docs/pages/installation/development.mdx
new file mode 100644
index 000000000..52aff1e7f
--- /dev/null
+++ b/apps/docs/pages/installation/development.mdx
@@ -0,0 +1,152 @@
+---
+title: Development Environment
+---
+
+import { Cards, Card, Steps } from 'nextra/components';
+
+This is currently the recommended option to install Postiz in a supportable configuration. The docker images are in active and heavy development for now.
+
+## Tested configurations
+
+- MacOS
+- Linux (Fedora 40)
+
+Naturally you can use these instructions to setup a development environment on any platform, but there may not be much experience in the community to help you with any issues you may encounter.
+
+## Prerequisites
+
+This guide will ask you to install & configure several services exaplained below.
+
+### Prerequisite Cloud Services
+
+- **[Cloudflare R2](https://cloudflare.com)** - for uploads (optional, can use local machine).
+- **Social Media API details** - various API keys and secrets (more details later) for services you want to use; reddit, X, Instagram, etc..
+
+### Optional Cloud Services
+
+- **[Resend account](https://resend.com)** - for user activation and email notifications.
+
+### Prerequisite Local Services
+
+- **Node.js** - for running the code! (version 18+)
+- **PostgreSQL** - or any other SQL database (instructions beleow suggest Docker)
+- **Redis** - for handling worker queues (instructions below suggest Docker)
+
+We have some messages from users who are using Windows, which should work, but they are not tested well yet.
+
+## Installation Instructions
+
+### NodeJS (version 18+)
+
+A complete guide of how to install NodeJS can be found [here](https://nodejs.org/en/download/).
+
+### PostgreSQL (or any other SQL database) & Redis
+
+You can choose **Option A** to **Option B** to install the database.
+
+#### Option A) Postgres and Redis as Single containers
+
+You can install [Docker](https://www.docker.com/products/docker-desktop) and run:
+
+```bash Terminal
+docker run -e POSTGRES_USER=root -e POSTGRES_PASSWORD=your_password --name postgres -p 5432:5432 -d postgres
+docker run --name redis -p 6379:6379 -d redis
+```
+
+#### Option B) Postgres and Redis as docker-compose
+
+Download the [docker-compose.yaml file here](https://raw.githubusercontent.com/gitroomhq/postiz-app/main/docker-compose.dev.yaml),
+or grab it from the repository in the next step.
+
+```bash Terminal
+docker compose -f "docker-compose.dev.yaml" up
+```
+
+## Build Postiz
+
+
+### Clone the repository
+
+```bash Terminal
+git clone https://github.com/gitroomhq/gitroom
+```
+
+### Set environment variables
+Copy the `.env.example` file to `.env` and fill in the values
+
+```bash .env
+# Required Settings
+DATABASE_URL="postgresql://postiz-user:postiz-password@localhost:5432/postiz-db-local"
+REDIS_URL="redis://localhost:6379"
+JWT_SECRET="random string for your JWT secret, make it long"
+FRONTEND_URL="http://localhost:4200"
+NEXT_PUBLIC_BACKEND_URL="http://localhost:3000"
+BACKEND_INTERNAL_URL="http://localhost:3000"
+
+# Optional. Your upload directory path if you host your files locally.
+UPLOAD_DIRECTORY="/opt/postiz/uploads/"
+
+# Optional: your upload directory slug if you host your files locally.
+NEXT_PUBLIC_UPLOAD_STATIC_DIRECTORY=""
+
+## This is a dummy key, you must create your own from Resend.
+## If this variable exists, user activation is required.
+## If it is commented out, users are activated automatically.
+#RESEND_API_KEY="RzeTwHijvxvPUerScFcenUZUALuQJzSaGSMJ"
+
+## These are dummy values, you must create your own from Cloudflare.
+## Remember to set your public internet IP address in the allow-list for the API token.
+CLOUDFLARE_ACCOUNT_ID="QhcMSXQyPuMCRpSQcSYdEuTYgHeCXHbu"
+CLOUDFLARE_ACCESS_KEY="dcfCMSuFEeCNfvByUureMZEfxWJmDqZe"
+CLOUDFLARE_SECRET_ACCESS_KEY="zTTMXBmtyLPwHEdpACGHgDgzRTNpTJewiNriLnUS"
+CLOUDFLARE_BUCKETNAME="postiz"
+CLOUDFLARE_BUCKET_URL="https://QhcMSXQyPuMCRpSQcSYdEuTYgHeCXHbu.r2.cloudflarestorage.com/"
+CLOUDFLARE_REGION="auto"
+
+# Social Media API Settings
+X_API_KEY="Twitter API key for normal oAuth not oAuth2"
+X_API_SECRET="Twitter API secret for normal oAuth not oAuth2"
+LINKEDIN_CLIENT_ID="Linkedin Client ID"
+LINKEDIN_CLIENT_SECRET="Linkedin Client Secret"
+REDDIT_CLIENT_ID="Reddit Client ID"
+REDDIT_CLIENT_SECRET="Linkedin Client Secret"
+GITHUB_CLIENT_ID="GitHub Client ID"
+GITHUB_CLIENT_SECRET="GitHub Client Secret"
+
+
+# Developer Settings
+NX_ADD_PLUGINS=false
+IS_GENERAL="true" # required for now
+```
+
+### Install the dependencies
+
+```bash Terminal
+npm install
+```
+
+### Generate the prisma client and run the migrations
+
+```bash Terminal
+npm run prisma-db-push
+```
+
+### Run the project
+
+```bash Terminal
+npm run dev
+```
+
+
+
+If everything is running successfully, open http://localhost:4200 in your browser!
+
+If everything is not running - you had errors in the steps above, please head over to our [support](/support) page.
+
+## Next Steps
+
+
+
+
+
+
diff --git a/apps/docs/pages/installation/docker-compose.mdx b/apps/docs/pages/installation/docker-compose.mdx
new file mode 100644
index 000000000..ac9d765c1
--- /dev/null
+++ b/apps/docs/pages/installation/docker-compose.mdx
@@ -0,0 +1,67 @@
+---
+title: Docker Compose
+---
+
+import EarlyDoc from '../../components/snippets/earlydoc.mdx';
+import DockerEnvvarApps from '../../components/snippets/docker-envvar-apps.mdx';
+
+
+
+# Example `docker-compose.yml` file
+
+```yaml
+services:
+ postiz:
+ image: ghcr.io/gitroomhq/postiz-app:latest
+ container_name: postiz
+ restart: always
+ volumes:
+ - ./config:/config/ # Should contain your .env file
+ ports:
+ - 4200:4200
+ - 3000:3000
+ networks:
+ - postiz-network
+
+ postiz-postgres:
+ image: postgres:14.5
+ container_name: postiz-postgres
+ restart: always
+ environment:
+ POSTGRES_PASSWORD: postiz-local-pwd
+ POSTGRES_USER: postiz-local
+ POSTGRES_DB: postiz-db-local
+ volumes:
+ - postgres-volume:/var/lib/postgresql/data
+ ports:
+ - 5432:5432
+ networks:
+ - postiz-network
+ postiz-pg-admin:
+ image: dpage/pgadmin4
+ container_name: postiz-pg-admin
+ restart: always
+ ports:
+ - 8081:80
+ environment:
+ PGADMIN_DEFAULT_EMAIL: admin@admin.com
+ PGADMIN_DEFAULT_PASSWORD: admin
+ networks:
+ - postiz-network
+ postiz-redis:
+ image: redis:7.2
+ container_name: postiz-redis
+ restart: always
+ ports:
+ - 6379:6379
+
+volumes:
+ postgres-volume:
+ external: false
+
+networks:
+ postiz-network:
+ external: false
+```
+
+
diff --git a/apps/docs/pages/installation/docker.mdx b/apps/docs/pages/installation/docker.mdx
new file mode 100644
index 000000000..177257db6
--- /dev/null
+++ b/apps/docs/pages/installation/docker.mdx
@@ -0,0 +1,27 @@
+---
+title: Docker
+---
+
+import EarlyDoc from "../../components/snippets/earlydoc.mdx";
+import DockerEnvvarApps from "../../components/snippets/docker-envvar-apps.mdx";
+
+
+
+# Set environment variables
+
+Postiz configuration is entirely via environment variables for now. You might be used to setting environment variables when starting containers,
+however postiz needs a LOT of environment variables, so setting these on command line or in a docker-compose is probably not practical for long
+term maintainability.
+
+It is recommended to use a `.env` file, which the Postiz containers look for in /config. Docker will automatically create this file for you on a
+docker volume the first time you start up Postiz.
+
+The default .env file can be found here; [example .env file](https://raw.githubusercontent.com/gitroomhq/postiz-app/main/.env.example)
+
+# Create the container on command line
+
+```bash
+docker create --name postiz -v ./config:/config -p 4200:4200 -p 3000:3000 ghcr.io/gitroomhq/postiz-app:latest
+```
+
+
diff --git a/apps/docs/pages/installation/kubernetes-helm.mdx b/apps/docs/pages/installation/kubernetes-helm.mdx
new file mode 100644
index 000000000..ff4b98867
--- /dev/null
+++ b/apps/docs/pages/installation/kubernetes-helm.mdx
@@ -0,0 +1,11 @@
+---
+title: Helm
+---
+
+import EarlyDoc from '../../components/snippets/earlydoc.mdx';
+
+
+
+Postiz has a helm chart that is in very active development. You can find it here;
+
+https://github.com/gitroomhq/postiz-helmchart
diff --git a/apps/docs/pages/introduction.mdx b/apps/docs/pages/introduction.mdx
new file mode 100644
index 000000000..179868414
--- /dev/null
+++ b/apps/docs/pages/introduction.mdx
@@ -0,0 +1,50 @@
+---
+
+title: Introduction
+description: 'Welcome to Gitroom documentation'
+
+---
+
+import { Cards, Card } from "nextra/components";
+
+
+
+
+
+
+## What is Gitroom?
+
+Gitroom can help you launch your open-source tool every week
+
+
+
Schedule social media and articles.
+
Exchange or buy posts from other members.
+
Monitor your GitHub trending, and so much more.
+
+
+## Architecture
+
+Gitroom is an [NX monorepo](https://nx.dev) that contains a backend, a frontend, workers, cron jobs and the docs.
+Unlike other NX project, this project has one `.env` file that is shared between all the apps.
+It makes it easier to develop and deploy the project.
+When deploying to websites like [Railway](https://railway.app) or [Heroku](https://heroku.com), you can use a shared environment variables for all the apps.
+
+**It has four main components:**
+
+- `frontend` - NextJS control panel serving as the admin dashboard for the project.
+- `backend` - NestJS backend that serves as the API for the frontend.
+- `cron` - NestJS cron jobs that run every X to update the database with new trending, refresh tokens and more.
+- `workers` - NestJS workers that run every X to process scheduled posts, sync GitHub stars and more.
+
+
+ >}
+ title="Learn how to install the project and start using it"
+ href="/quickstart"
+ />
+ >}
+ title="Learn the architecture of the project"
+ href="/howitworks"
+ />
+
diff --git a/apps/docs/pages/providers/_meta.json b/apps/docs/pages/providers/_meta.json
new file mode 100644
index 000000000..86eb15a88
--- /dev/null
+++ b/apps/docs/pages/providers/_meta.json
@@ -0,0 +1,5 @@
+{
+ "linkedin": "Linkedin",
+ "reddit": "Reddit",
+ "x": "X"
+}
diff --git a/apps/docs/pages/providers/linkedin.mdx b/apps/docs/pages/providers/linkedin.mdx
new file mode 100644
index 000000000..0bba5cb98
--- /dev/null
+++ b/apps/docs/pages/providers/linkedin.mdx
@@ -0,0 +1,20 @@
+---
+title: Linkedin
+description: How to add Linkedin to your system
+---
+
+Head over to [Linkedin developers](https://www.linkedin.com/developers/apps) and create a new app.
+![Linkedin](/images/providers/linkedin/linkedin-001.png)
+
+Fill in all the details, once created head over to Products and make sure you add all the required products.
+![Linkedin](/images/providers/linkedin/linkedin-002.png)
+
+It is important to have the special permissions or you will not have the ability to refresh your tokens.
+
+Make sure your redirect URL is set to `http://localhost:4200/integrations/social/linkedin` for local development.
+Copy the created `Client ID` and `Client Secret` and add them to your `.env` file.
+
+```env
+LINKEDIN_CLIENT_ID=""
+LINKEDIN_CLIENT_SECRET=""
+```
diff --git a/apps/docs/pages/providers/reddit.mdx b/apps/docs/pages/providers/reddit.mdx
new file mode 100644
index 000000000..950818499
--- /dev/null
+++ b/apps/docs/pages/providers/reddit.mdx
@@ -0,0 +1,16 @@
+---
+title: Reddit
+description: How to add Reddit to your system
+---
+
+Head over to [Reddit developers](https://www.reddit.com/prefs/apps) and create a new app.
+In the type of app, select `web app` and in the redirect uri, add `http://localhost:4200/integrations/social/reddit`.
+
+Copy the Reddit client id and client secret and add them to your `.env` file.
+
+![Reddit](/images/providers/reddit/reddit-001.png)
+
+```env
+REDDIT_CLIENT_ID=""
+REDDIT_CLIENT_SECRET=""
+```
\ No newline at end of file
diff --git a/apps/docs/pages/providers/x.mdx b/apps/docs/pages/providers/x.mdx
new file mode 100644
index 000000000..f9f75d46e
--- /dev/null
+++ b/apps/docs/pages/providers/x.mdx
@@ -0,0 +1,33 @@
+---
+title: X
+description: How to add X to your system
+---
+
+X is a bit different.
+They created an oAuth2 flow, but it works only with Twitter v2 API.
+But in order to upload pictures to X, you need to use the old Twitter v1 API.
+So we are going to use the normal oAuth1 flow for that (that supports Twitter v2 also 🤷🏻).
+
+Head over the [Twitter developers page](https://developer.twitter.com/en/portal/dashboard) and create a new app.
+Click to sign-up for a new free account
+
+![X](/images/providers/x/x-001.png)
+
+Click to edit the application settings
+![X](/images/providers/x/x-002.png)
+
+The click to set up an authentication flow
+![X](/images/providers/x/x-003.png)
+
+In the App Permission set it to `Read and Write`
+In the Type of App set it to `Web App, Automated App or Bot`
+In the App Info set the `Callback URI / Redirect URL` to `http://localhost:4200/integrations/social/x`
+Save it and go to "Keys and Tokens" tab
+
+Click on "Regenerate" inside "Consumer Keys" and copy the `API Key` and `API Key Secret`.
+Open .env file and add the following:
+
+```env
+X_API_KEY=""
+X_API_SECRET=""
+```
\ No newline at end of file
diff --git a/apps/docs/pages/quickstart.mdx b/apps/docs/pages/quickstart.mdx
new file mode 100644
index 000000000..86a5bcd73
--- /dev/null
+++ b/apps/docs/pages/quickstart.mdx
@@ -0,0 +1,19 @@
+---
+title: 'Quickstart'
+slug: '/quickstart'
+---
+
+At the moment it is necessary to build the project locally - some dependencies
+like redis and postgres can run as docker containers, but there is no docker
+container for Postiz just yet.
+
+## Self Hosted installation options
+
+You can choose between the following installation options;
+
+* [Development](/installation/development) - The only installation option that is offically supported at the moment.
+* [Docker (standalone)](/installation/docker) - Run from the command line with Docker.
+* [Docker Compose](/installation/docker-compose) - Run with Docker Compose.
+* [Helm](/installation/kubernetes-helm) - Run with Kubernetes + Helm.
+
+
diff --git a/apps/docs/pages/support.mdx b/apps/docs/pages/support.mdx
new file mode 100644
index 000000000..837f6c860
--- /dev/null
+++ b/apps/docs/pages/support.mdx
@@ -0,0 +1,35 @@
+---
+title: Support
+---
+
+Sometimes, things can go wrong, or you need some help!
+
+Note that the Self Hosted version of Postiz is supported by the community in their
+free time, on a best-efforts basis. Please post your question and be patient.
+
+- [Discord](https://discord.com/invite/sf7QjTcX37) - Flexible chat, with screenshots and screen sharing, probably the best option for support.
+- [GitHub issue](https://github.com/gitroomhq/postiz-app/issues/new/choose) - backup option if you are unable to use Discord.
+
+## How to effectively ask for support
+
+Try to follow this guide when asking for support, in this order; **Goal, Environment, Changes, Results**.
+
+- **Goal:** Start off by explaining what you were trying to do
+ - _I want to schedule a post on Reddit at 6pm_
+ - _I want to run in a Linux container on a Raspberry Pi_
+ - _I want to use a custom domain name_
+
+- **Environment:** - Share the relevant parts about your environment. Web App issues; Are you using Firefox, Chrome, etc? Installation/Other issues; a Mac, Linux, Windows, how did you install?
+ - _I'm using Firefox on Windows 10_
+ - _I'm using a Raspberry Pi 4 with Ubuntu 20.04, and Node version 18_
+ - _This is a new installation on a Mac_
+
+- **Changed:** - Most likely something has changed, what is it?
+ - _I updated my browser to the latest version and now ..._
+ - _I found a change in the latest version and now ..._
+ - _I think this used to work, but now..._
+
+- **Results:** - What happened? What did you expect to happen?
+ - _I see a blank screen_
+ - _I see an error message_
+ - _I see a 404 page_
diff --git a/apps/docs/postcss.config.js b/apps/docs/postcss.config.js
new file mode 100644
index 000000000..33ad091d2
--- /dev/null
+++ b/apps/docs/postcss.config.js
@@ -0,0 +1,6 @@
+module.exports = {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+}
diff --git a/apps/docs/project.json b/apps/docs/project.json
new file mode 100644
index 000000000..34790955c
--- /dev/null
+++ b/apps/docs/project.json
@@ -0,0 +1,52 @@
+{
+ "name": "docs",
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
+ "sourceRoot": "apps/docs",
+ "projectType": "application",
+ "targets": {
+ "build": {
+ "executor": "@nx/next:build",
+ "outputs": ["{options.outputPath}"],
+ "defaultConfiguration": "production",
+ "options": {
+ "outputPath": "dist/apps/docs",
+ "postcssConfig": "apps/docs/postcss.config.js"
+ },
+ "configurations": {
+ "development": {
+ "outputPath": "apps/docs"
+ },
+ "production": {}
+ }
+ },
+ "serve": {
+ "executor": "@nx/next:server",
+ "defaultConfiguration": "development",
+ "options": {
+ "buildTarget": "docs:build",
+ "dev": true
+ },
+ "configurations": {
+ "development": {
+ "buildTarget": "docs:build:development",
+ "dev": true
+ },
+ "production": {
+ "buildTarget": "docs:build:production",
+ "dev": false
+ }
+ }
+ },
+ "export": {
+ "executor": "@nx/next:export",
+ "options": {
+ "buildTarget": "docs:build:production"
+ }
+ },
+ "lint": {
+ "executor": "@nx/eslint:lint",
+ "outputs": ["{options.outputFile}"]
+ }
+ },
+ "tags": []
+}
diff --git a/apps/docs/public/android-chrome-192x192.png b/apps/docs/public/android-chrome-192x192.png
new file mode 100644
index 000000000..94f0b8a31
Binary files /dev/null and b/apps/docs/public/android-chrome-192x192.png differ
diff --git a/apps/docs/public/android-chrome-512x512.png b/apps/docs/public/android-chrome-512x512.png
new file mode 100644
index 000000000..8d2e0fec5
Binary files /dev/null and b/apps/docs/public/android-chrome-512x512.png differ
diff --git a/apps/docs/public/apple-touch-icon.png b/apps/docs/public/apple-touch-icon.png
new file mode 100644
index 000000000..3a651d808
Binary files /dev/null and b/apps/docs/public/apple-touch-icon.png differ
diff --git a/apps/docs/public/favicon-16x16.png b/apps/docs/public/favicon-16x16.png
new file mode 100644
index 000000000..9bddb6f67
Binary files /dev/null and b/apps/docs/public/favicon-16x16.png differ
diff --git a/apps/docs/public/favicon-32x32.png b/apps/docs/public/favicon-32x32.png
new file mode 100644
index 000000000..bb6427ccf
Binary files /dev/null and b/apps/docs/public/favicon-32x32.png differ
diff --git a/apps/docs/public/favicon.ico b/apps/docs/public/favicon.ico
new file mode 100644
index 000000000..691ec46c9
Binary files /dev/null and b/apps/docs/public/favicon.ico differ
diff --git a/apps/docs/public/images/arch.png b/apps/docs/public/images/arch.png
new file mode 100644
index 000000000..2a45a0e52
Binary files /dev/null and b/apps/docs/public/images/arch.png differ
diff --git a/apps/docs/public/images/checks-passed.png b/apps/docs/public/images/checks-passed.png
new file mode 100644
index 000000000..3303c7736
Binary files /dev/null and b/apps/docs/public/images/checks-passed.png differ
diff --git a/apps/docs/public/images/hero-dark.svg b/apps/docs/public/images/hero-dark.svg
new file mode 100644
index 000000000..c6a30e88b
--- /dev/null
+++ b/apps/docs/public/images/hero-dark.svg
@@ -0,0 +1,161 @@
+
diff --git a/apps/docs/public/images/hero-light.svg b/apps/docs/public/images/hero-light.svg
new file mode 100644
index 000000000..297d68fb9
--- /dev/null
+++ b/apps/docs/public/images/hero-light.svg
@@ -0,0 +1,155 @@
+
diff --git a/apps/docs/public/images/providers/linkedin/linkedin-001.png b/apps/docs/public/images/providers/linkedin/linkedin-001.png
new file mode 100644
index 000000000..3226cc136
Binary files /dev/null and b/apps/docs/public/images/providers/linkedin/linkedin-001.png differ
diff --git a/apps/docs/public/images/providers/linkedin/linkedin-002.png b/apps/docs/public/images/providers/linkedin/linkedin-002.png
new file mode 100644
index 000000000..18138aa75
Binary files /dev/null and b/apps/docs/public/images/providers/linkedin/linkedin-002.png differ
diff --git a/apps/docs/public/images/providers/reddit/reddit-001.png b/apps/docs/public/images/providers/reddit/reddit-001.png
new file mode 100644
index 000000000..7507a0e38
Binary files /dev/null and b/apps/docs/public/images/providers/reddit/reddit-001.png differ
diff --git a/apps/docs/public/images/providers/x/x-001.png b/apps/docs/public/images/providers/x/x-001.png
new file mode 100644
index 000000000..bd8253a62
Binary files /dev/null and b/apps/docs/public/images/providers/x/x-001.png differ
diff --git a/apps/docs/public/images/providers/x/x-002.png b/apps/docs/public/images/providers/x/x-002.png
new file mode 100644
index 000000000..59f0d47c7
Binary files /dev/null and b/apps/docs/public/images/providers/x/x-002.png differ
diff --git a/apps/docs/public/images/providers/x/x-003.png b/apps/docs/public/images/providers/x/x-003.png
new file mode 100644
index 000000000..d54a5f196
Binary files /dev/null and b/apps/docs/public/images/providers/x/x-003.png differ
diff --git a/apps/docs/public/images/providers/x/x-004.png b/apps/docs/public/images/providers/x/x-004.png
new file mode 100644
index 000000000..8e62bf5e6
Binary files /dev/null and b/apps/docs/public/images/providers/x/x-004.png differ
diff --git a/apps/docs/public/images/screens/analytics.png b/apps/docs/public/images/screens/analytics.png
new file mode 100644
index 000000000..dbd67e75c
Binary files /dev/null and b/apps/docs/public/images/screens/analytics.png differ
diff --git a/apps/docs/public/images/screens/billing.png b/apps/docs/public/images/screens/billing.png
new file mode 100644
index 000000000..6df00c535
Binary files /dev/null and b/apps/docs/public/images/screens/billing.png differ
diff --git a/apps/docs/public/images/screens/settings.png b/apps/docs/public/images/screens/settings.png
new file mode 100644
index 000000000..6d256c835
Binary files /dev/null and b/apps/docs/public/images/screens/settings.png differ
diff --git a/apps/docs/public/logo/dark.png b/apps/docs/public/logo/dark.png
new file mode 100644
index 000000000..1d787f8c6
Binary files /dev/null and b/apps/docs/public/logo/dark.png differ
diff --git a/apps/docs/public/logo/light.png b/apps/docs/public/logo/light.png
new file mode 100644
index 000000000..14611589d
Binary files /dev/null and b/apps/docs/public/logo/light.png differ
diff --git a/apps/docs/public/robots.txt b/apps/docs/public/robots.txt
new file mode 100644
index 000000000..422c35f10
--- /dev/null
+++ b/apps/docs/public/robots.txt
@@ -0,0 +1,9 @@
+# *
+User-agent: *
+Allow: /
+
+# Host
+Host: https://docs.copilotkit.ai
+
+# Sitemaps
+Sitemap: https://docs.copilotkit.ai/sitemap.xml
diff --git a/apps/docs/public/site.webmanifest b/apps/docs/public/site.webmanifest
new file mode 100644
index 000000000..45dc8a206
--- /dev/null
+++ b/apps/docs/public/site.webmanifest
@@ -0,0 +1 @@
+{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
\ No newline at end of file
diff --git a/apps/docs/public/sitemap-0.xml b/apps/docs/public/sitemap-0.xml
new file mode 100644
index 000000000..1c4c31a21
--- /dev/null
+++ b/apps/docs/public/sitemap-0.xml
@@ -0,0 +1,41 @@
+
+
+https://docs.copilotkit.ai/anonymous-telemetry2024-08-06T12:01:35.688Zdaily0.7
+https://docs.copilotkit.ai/code-contributions/advanced-package-linking2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/code-contributions/how-to-contribute2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/concepts/agents2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/concepts/copilot-runtime2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/concepts/customize-look-and-feel2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/concepts/generative-ui2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/documentation-contributions2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/quickstart-chatbot2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/reference/classes/CopilotRuntime/CopilotRuntime2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/reference/classes/CopilotRuntime/service-adapters/GoogleGenerativeAIAdapter2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/reference/classes/CopilotRuntime/service-adapters/GroqAdapter2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/reference/classes/CopilotRuntime/service-adapters/LangChainAdapter2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/reference/classes/CopilotRuntime/service-adapters/OpenAIAdapter2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/reference/classes/CopilotRuntime/service-adapters/OpenAIAssistantAdapter2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/reference/classes/CopilotTask2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/reference/components/CopilotChat2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/reference/components/CopilotKit2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/reference/components/CopilotPopup2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/reference/components/CopilotSidebar2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/reference/components/CopilotTextarea2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/reference/hooks/useCopilotAction2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/reference/hooks/useCopilotChat2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/reference/hooks/useCopilotChatSuggestions2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/reference/hooks/useCopilotReadable2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/tutorial-ai-todo-list-copilot/next-steps2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/tutorial-ai-todo-list-copilot/overview2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/tutorial-ai-todo-list-copilot/step-1-checkout-repo2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/tutorial-ai-todo-list-copilot/step-2-setup-copilotkit2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/tutorial-ai-todo-list-copilot/step-3-copilot-readable-state2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/tutorial-ai-todo-list-copilot/step-4-copilot-actions2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/tutorial-textarea/next-steps2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/tutorial-textarea/overview2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/tutorial-textarea/step-1-checkout-repo2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/tutorial-textarea/step-2-setup-copilotkit2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/tutorial-textarea/step-3-copilot-textarea2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/tutorial-textarea/step-4-copilot-readable-state2024-08-06T12:01:35.689Zdaily0.7
+https://docs.copilotkit.ai/what-is-copilotkit2024-08-06T12:01:35.689Zdaily0.7
+
\ No newline at end of file
diff --git a/apps/docs/public/sitemap.xml b/apps/docs/public/sitemap.xml
new file mode 100644
index 000000000..eacc8b422
--- /dev/null
+++ b/apps/docs/public/sitemap.xml
@@ -0,0 +1,4 @@
+
+
+https://docs.copilotkit.ai/sitemap-0.xml
+
\ No newline at end of file
diff --git a/apps/docs/snippets/docker-envvar-apps.mdx b/apps/docs/snippets/docker-envvar-apps.mdx
new file mode 100644
index 000000000..314aeaa50
--- /dev/null
+++ b/apps/docs/snippets/docker-envvar-apps.mdx
@@ -0,0 +1,10 @@
+## Controlling container services
+When the environment variable `POSTIZ_APPS` is not set, or is set to an empty string, all
+services will be started in a single container. This is normally fine for small, personal deployments.
+
+However, you can only start specific services within the docker container by changing this environement variable.
+
+If you need to scale, you can experiement with having multiple containers defined like;
+- Frontend only: `POSTIZ_APPS="frontend"`
+- Backend only: `POSTIZ_APPS="backend"`
+- Worker and Cron only: `POSTIZ_APPS="worker cron"`
diff --git a/apps/docs/snippets/docker-envvar-general.mdx b/apps/docs/snippets/docker-envvar-general.mdx
new file mode 100644
index 000000000..cf1a09714
--- /dev/null
+++ b/apps/docs/snippets/docker-envvar-general.mdx
@@ -0,0 +1,15 @@
+# Set environment variables
+
+Postiz configuration is entirely via environment variables.
+
+When using Postiz container images, you can specify the environment variables when you create the container (`docker create -e DATABASE_URL=...`), but this might be
+a bit tedious, as Postiz requires quite a few variables set to startup.
+
+It is recommended to use a `postiz.env` file, which the Postiz containers look for in /config. Docker will automatically create this file for you on a
+docker volume the first time you start up Postiz. The default container images will copy the `/config/postiz.env` to `/apps/.env` on startup. Like with
+any environment variables, if you change them, you must restart the application for the changes to take effect.
+
+An example file of the most used configuration settings can be found here; [example postiz.env file](https://raw.githubusercontent.com/gitroomhq/postiz-app/main/.env.example)
+
+There is also a [configuration reference](/configuration/reference) page that goes into more detail.
+
diff --git a/apps/docs/snippets/self-hosting-copilot-runtime-configure-copilotkit-provider.mdx b/apps/docs/snippets/self-hosting-copilot-runtime-configure-copilotkit-provider.mdx
new file mode 100644
index 000000000..f1e04646e
--- /dev/null
+++ b/apps/docs/snippets/self-hosting-copilot-runtime-configure-copilotkit-provider.mdx
@@ -0,0 +1,19 @@
+
+Now you can configure the [``](/reference/components/CopilotKit) provider to point to your Copilot Runtime URL. For example, if your runtime endpoint is served at `http://localhost:3000/api/runtime`, you can configure the provider like this:
+
+ ```tsx filename="layout.tsx" showLineNumbers {8}
+ "use client";
+
+ import { CopilotKit } from "@copilotkit/react-core";
+ import { CopilotSidebar } from "@copilotkit/react-ui";
+
+ export default function RootLayout({children}) {
+ return (
+
+
+ {children}
+
+
+ );
+ }
+ ```
\ No newline at end of file
diff --git a/apps/docs/snippets/self-hosting-copilot-runtime-create-endpoint.mdx b/apps/docs/snippets/self-hosting-copilot-runtime-create-endpoint.mdx
new file mode 100644
index 000000000..806304fae
--- /dev/null
+++ b/apps/docs/snippets/self-hosting-copilot-runtime-create-endpoint.mdx
@@ -0,0 +1,160 @@
+import { Tabs } from "nextra/components";
+
+Copilot Runtime is designed to run as a handler for HTTP endpoints (typically `/copilotkit` or `/api/copilotkit`). We provide plug and play support for many common frameworks. For more information, check out the [Self Hosting documentation](/concepts/self-hosting).
+
+
+
+ Create a new route to handle the `/api/copilotkit` endpoint.
+
+ ```ts showLineNumbers filename="app/api/copilotkit/route.ts"
+ import {
+ CopilotRuntime,
+ OpenAIAdapter,
+ copilotRuntimeNextJSAppRouterEndpoint,
+ } from "@copilotkit/runtime";
+ import OpenAI from "openai";
+ import { NextRequest } from "next/server";
+
+ const openai = new OpenAI();
+ const serviceAdapter = new OpenAIAdapter({ openai });
+
+ const runtime = new CopilotRuntime();
+
+ export const POST = async (req: NextRequest) => {
+ const { handleRequest } = copilotRuntimeNextJSAppRouterEndpoint({
+ runtime,
+ serviceAdapter,
+ endpoint: "/api/copilotkit",
+ });
+
+ return handleRequest(req);
+ };
+ ```
+
+ Your Copilot Runtime endpoint should be available at `http://localhost:{port}/api/copilotkit`.
+
+
+
+ Create a new route to handle the `/api/copilotkit` endpoint:
+
+ ```ts showLineNumbers filename="pages/api/copilotkit.ts"
+ import { NextApiRequest, NextApiResponse } from "next";
+ import {
+ CopilotRuntime,
+ OpenAIAdapter,
+ copilotRuntimeNextJSPagesRouterEndpoint,
+ } from "@copilotkit/runtime";
+ import OpenAI from "openai";
+
+ const openai = new OpenAI();
+
+ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
+ const serviceAdapter = new OpenAIAdapter({ openai });
+ const runtime = new CopilotRuntime();
+
+ const handleRequest = copilotRuntimeNextJSPagesRouterEndpoint({
+ endpoint: "/api/copilotkit",
+ runtime,
+ serviceAdapter,
+ });
+
+ return await handleRequest(req, res);
+ };
+ ```
+
+ Your Copilot Runtime endpoint should be available at `http://localhost:{port}/api/copilotkit`.
+
+
+
+ Create a new Express.js app and set up the Copilot Runtime handler:
+
+ ```ts showLineNumbers filename="server.ts"
+ import express from "express";
+ import { CopilotRuntime, OpenAIAdapter, copilotRuntimeNodeHttpEndpoint } from "@copilotkit/runtime";
+ import OpenAI from "openai";
+
+ const app = express();
+ const openai = new OpenAI();
+
+ app.use("/copilotkit", (req, res, next) => {
+ const serviceAdapter = new OpenAIAdapter({ openai });
+ const runtime = new CopilotRuntime();
+ const handler = copilotRuntimeNodeHttpEndpoint({
+ endpoint: "/copilotkit",
+ runtime,
+ serviceAdapter,
+ });
+
+ return handler(req, res, next);
+ });
+
+ app.listen(4000, () => {
+ console.log("Listening at http://localhost:4000/copilotkit");
+ });
+ ```
+
+ Your Copilot Runtime endpoint should be available at `http://localhost:4000/copilotkit`.
+
+
+
+ Set up a simple Node.js HTTP server and use the Copilot Runtime to handle requests:
+
+ ```ts showLineNumbers filename="server.ts"
+ import { createServer } from "node:http";
+ import { CopilotRuntime, OpenAIAdapter, copilotRuntimeNodeHttpEndpoint } from "@copilotkit/runtime";
+ import OpenAI from "openai";
+
+ const openai = new OpenAI();
+
+ const server = createServer((req, res) => {
+ const serviceAdapter = new OpenAIAdapter({ openai });
+ const runtime = new CopilotRuntime();
+ const handler = copilotRuntimeNodeHttpEndpoint({
+ endpoint: "/copilotkit",
+ runtime,
+ serviceAdapter,
+ });
+
+ return handler(req, res);
+ });
+
+ server.listen(4000, () => {
+ console.log("Listening at http://localhost:4000/copilotkit");
+ });
+ ```
+
+ Your Copilot Runtime endpoint should be available at `http://localhost:4000/copilotkit`.
+
+
+
+ ```ts showLineNumbers filename="copilotkit.controller.ts"
+ import { All, Controller, Req, Res } from "@nestjs/common";
+ import { AppService } from "./app.service";
+ import { CopilotRuntime, OpenAIAdapter } from "@copilotkit/backend";
+
+@Controller()
+export class AppController {
+constructor(private readonly appService: AppService) {}
+
+ @All("/copilotkit")
+ copilotkit(@Req() req: Request, @Res() res: Response) {
+ const copilotKit = new CopilotRuntime();
+ const openaiAdapter = new OpenAIAdapter();
+ copilotKit.streamHttpServerResponse(req, res, openaiAdapter);
+ }
+
+}
+
+```
+
+Your Copilot Runtime endpoint should be available at `http://localhost:{port}/copilotkit`.
+
+
+
+```
diff --git a/apps/docs/tailwind.config.js b/apps/docs/tailwind.config.js
new file mode 100644
index 000000000..103e9746e
--- /dev/null
+++ b/apps/docs/tailwind.config.js
@@ -0,0 +1,15 @@
+/** @type {import('tailwindcss').Config} */
+module.exports = {
+ content: [
+ "./theme.config.tsx",
+ "./pages/**/*.{js,jsx,ts,tsx,md,mdx}",
+ "./components/**/*.{js,jsx,ts,tsx,md,mdx}",
+
+ // Or if using `src` directory:
+ "./src/**/*.{js,jsx,ts,tsx,md,mdx}",
+ ],
+ theme: {
+ extend: {},
+ },
+ plugins: [],
+};
diff --git a/apps/docs/theme.config.tsx b/apps/docs/theme.config.tsx
new file mode 100644
index 000000000..ccd036db6
--- /dev/null
+++ b/apps/docs/theme.config.tsx
@@ -0,0 +1,99 @@
+import Image from "next/image";
+import { useRouter } from "next/router";
+import { DocsThemeConfig, useConfig } from "nextra-theme-docs";
+
+const themeConfig: DocsThemeConfig = {
+ head: () => {
+ const router = useRouter();
+ const { title, ...rest } = useConfig();
+
+ const pagePath = router.asPath;
+ const ogImageUrl = `https://docs.postiz.com/api/opengraph-image?title=${title}`;
+
+ const ogTitle = `${title} - Postiz`;
+
+ return (
+ <>
+ {ogTitle}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+ },
+ logo: (
+