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 of Gitroom + +## 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"; + +
+ Hero Light + Hero Dark +
+ +## 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: ( +
+ CopilotKit + Docs +
+ ), + project: { + link: "https://github.com/copilotkit/copilotkit", + }, + chat: { + link: "https://discord.gg/6dffbvGU3D", + }, + docsRepositoryBase: "https://github.com/copilotkit/copilotkit", + footer: { + text: "Gitroom Limited. All rights reserved.", + }, + darkMode: false, + nextThemes: { + defaultTheme: "dark", + forcedTheme: "dark", + }, + primaryHue: 280, + primarySaturation: 100, +}; + +export default themeConfig; diff --git a/apps/docs/tsconfig.json b/apps/docs/tsconfig.json new file mode 100644 index 000000000..9aa0e952b --- /dev/null +++ b/apps/docs/tsconfig.json @@ -0,0 +1,35 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "target": "es5", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": false, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "incremental": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve" + }, + "include": [ + "**/*.ts", + "**/*.tsx", + "**/*.js", + "**/*.jsx", + "../../apps/docs/.next/types/**/*.ts", + "../../dist/apps/docs/.next/types/**/*.ts", + "next-env.d.ts", + ".next/types/**/*.ts" + ], + "exclude": [ + "node_modules", + "jest.config.ts", + "src/**/*.spec.ts", + "src/**/*.test.ts" + ] +} diff --git a/apps/docs/tsconfig.spec.json b/apps/docs/tsconfig.spec.json new file mode 100644 index 000000000..bb0f78b4b --- /dev/null +++ b/apps/docs/tsconfig.spec.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "jsx": "react" + }, + "include": [ + ] +} diff --git a/var/docker/entrypoint.sh b/var/docker/entrypoint.sh index f79c8f42a..526ca6f32 100755 --- a/var/docker/entrypoint.sh +++ b/var/docker/entrypoint.sh @@ -1,21 +1,23 @@ #!/bin/bash +set -o xtrace + if [[ "$SKIP_CONFIG_CHECK" != "true" ]]; then - echo "symlinking /config/.env into /app/.env" + echo "Entrypoint: Copying /config/postiz.env into /app/.env" if [ ! -f /config/.env ]; then - echo "ERROR: No .env file found in /config/.env" + echo "Entrypoint: WARNING: No .env file found in /config/postiz.env" fi - ln -sf /config/postiz.env /app/.env + cp -vf /config/postiz.env /app/.env fi if [[ "$POSTIZ_APPS" -eq "" ]]; then - echo "POSTIZ_APPS is not set, starting everything!" + echo "Entrypoint: POSTIZ_APPS is not set, starting everything!" POSTIZ_APPS="frontend workers cron backend" fi -echo "Running database migrations" +echo "Entrypoint: Running database migrations" npm run prisma-db-push mkdir -p /etc/supervisor.d/