add documentation
This commit is contained in:
42
apps/docs/.gitignore
vendored
Normal file
42
apps/docs/.gitignore
vendored
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# database
|
||||||
|
/prisma/db.sqlite
|
||||||
|
/prisma/db.sqlite-journal
|
||||||
|
|
||||||
|
# next.js
|
||||||
|
/.next/
|
||||||
|
/out/
|
||||||
|
next-env.d.ts
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
*.pem
|
||||||
|
|
||||||
|
# debug
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
.pnpm-debug.log*
|
||||||
|
|
||||||
|
# local env files
|
||||||
|
# do not commit any .env files to git, except for the .env.example file. https://create.t3.gg/en/usage/env-variables#using-environment-variables
|
||||||
|
.env
|
||||||
|
.env*.local
|
||||||
|
|
||||||
|
# vercel
|
||||||
|
.vercel
|
||||||
|
|
||||||
|
# typescript
|
||||||
|
*.tsbuildinfo
|
||||||
1
apps/docs/.prettierignore
Normal file
1
apps/docs/.prettierignore
Normal file
@@ -0,0 +1 @@
|
|||||||
|
./src/pages/docs/*
|
||||||
113
apps/docs/Dockerfile
Normal file
113
apps/docs/Dockerfile
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
FROM --platform=linux/amd64 node:20-slim AS base
|
||||||
|
|
||||||
|
ARG NEXT_PUBLIC_DASHBOARD_URL
|
||||||
|
ENV NEXT_PUBLIC_DASHBOARD_URL=$NEXT_PUBLIC_DASHBOARD_URL
|
||||||
|
|
||||||
|
ARG NEXT_PUBLIC_API_URL
|
||||||
|
ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL
|
||||||
|
|
||||||
|
ARG DATABASE_URL
|
||||||
|
ENV DATABASE_URL=$DATABASE_URL
|
||||||
|
|
||||||
|
ARG CLICKHOUSE_DB
|
||||||
|
ENV CLICKHOUSE_DB=$CLICKHOUSE_DB
|
||||||
|
|
||||||
|
ARG CLICKHOUSE_PASSWORD
|
||||||
|
ENV CLICKHOUSE_PASSWORD=$CLICKHOUSE_PASSWORD
|
||||||
|
|
||||||
|
ARG CLICKHOUSE_URL
|
||||||
|
ENV CLICKHOUSE_URL=$CLICKHOUSE_URL
|
||||||
|
|
||||||
|
ARG CLICKHOUSE_USER
|
||||||
|
ENV CLICKHOUSE_USER=$CLICKHOUSE_USER
|
||||||
|
|
||||||
|
ARG REDIS_URL
|
||||||
|
ENV REDIS_URL=$REDIS_URL
|
||||||
|
|
||||||
|
ARG NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY
|
||||||
|
ENV NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=$NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY
|
||||||
|
|
||||||
|
ARG CLERK_SECRET_KEY
|
||||||
|
ENV CLERK_SECRET_KEY=$CLERK_SECRET_KEY
|
||||||
|
|
||||||
|
ENV PNPM_HOME="/pnpm"
|
||||||
|
|
||||||
|
ENV PATH="$PNPM_HOME:$PATH"
|
||||||
|
|
||||||
|
RUN corepack enable
|
||||||
|
|
||||||
|
ARG NODE_VERSION=20
|
||||||
|
|
||||||
|
RUN apt update \
|
||||||
|
&& apt install -y curl \
|
||||||
|
&& curl -L https://raw.githubusercontent.com/tj/n/master/bin/n -o n \
|
||||||
|
&& bash n $NODE_VERSION \
|
||||||
|
&& rm n \
|
||||||
|
&& npm install -g n
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY package.json package.json
|
||||||
|
COPY pnpm-lock.yaml pnpm-lock.yaml
|
||||||
|
COPY pnpm-workspace.yaml pnpm-workspace.yaml
|
||||||
|
COPY apps/public/package.json apps/public/package.json
|
||||||
|
COPY packages/db/package.json packages/db/package.json
|
||||||
|
COPY packages/redis/package.json packages/redis/package.json
|
||||||
|
COPY packages/queue/package.json packages/queue/package.json
|
||||||
|
COPY packages/common/package.json packages/common/package.json
|
||||||
|
COPY packages/constants/package.json packages/constants/package.json
|
||||||
|
COPY packages/validation/package.json packages/validation/package.json
|
||||||
|
COPY packages/sdk/package.json packages/sdk/package.json
|
||||||
|
|
||||||
|
# BUILD
|
||||||
|
FROM base AS build
|
||||||
|
|
||||||
|
WORKDIR /app/apps/public
|
||||||
|
RUN pnpm install --frozen-lockfile --ignore-scripts
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
COPY apps apps
|
||||||
|
COPY packages packages
|
||||||
|
COPY tooling tooling
|
||||||
|
RUN pnpm db:codegen
|
||||||
|
|
||||||
|
WORKDIR /app/apps/public
|
||||||
|
RUN pnpm run build
|
||||||
|
|
||||||
|
# PROD
|
||||||
|
FROM base AS prod
|
||||||
|
|
||||||
|
WORKDIR /app/apps/public
|
||||||
|
RUN pnpm install --frozen-lockfile --prod --ignore-scripts
|
||||||
|
|
||||||
|
# FINAL
|
||||||
|
FROM base AS runner
|
||||||
|
|
||||||
|
COPY --from=build /app/package.json /app/package.json
|
||||||
|
COPY --from=prod /app/node_modules /app/node_modules
|
||||||
|
# Apps
|
||||||
|
COPY --from=build /app/apps/public /app/apps/public
|
||||||
|
# Apps node_modules
|
||||||
|
COPY --from=prod /app/apps/public/node_modules /app/apps/public/node_modules
|
||||||
|
# Packages
|
||||||
|
COPY --from=build /app/packages/db /app/packages/db
|
||||||
|
COPY --from=build /app/packages/redis /app/packages/redis
|
||||||
|
COPY --from=build /app/packages/common /app/packages/common
|
||||||
|
COPY --from=build /app/packages/queue /app/packages/queue
|
||||||
|
COPY --from=build /app/packages/constants /app/packages/constants
|
||||||
|
COPY --from=build /app/packages/validation /app/packages/validation
|
||||||
|
COPY --from=build /app/packages/sdk /app/packages/sdk
|
||||||
|
# Packages node_modules
|
||||||
|
COPY --from=prod /app/packages/db/node_modules /app/packages/db/node_modules
|
||||||
|
COPY --from=prod /app/packages/redis/node_modules /app/packages/redis/node_modules
|
||||||
|
COPY --from=prod /app/packages/common/node_modules /app/packages/common/node_modules
|
||||||
|
COPY --from=prod /app/packages/queue/node_modules /app/packages/queue/node_modules
|
||||||
|
COPY --from=prod /app/packages/validation/node_modules /app/packages/validation/node_modules
|
||||||
|
|
||||||
|
RUN pnpm db:codegen
|
||||||
|
|
||||||
|
WORKDIR /app/apps/public
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
CMD ["pnpm", "start"]
|
||||||
1
apps/docs/README.md
Normal file
1
apps/docs/README.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# Docs
|
||||||
33
apps/docs/next.config.mjs
Normal file
33
apps/docs/next.config.mjs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import nextra from 'nextra';
|
||||||
|
|
||||||
|
/** @type {import("next").NextConfig} */
|
||||||
|
const config = {
|
||||||
|
reactStrictMode: true,
|
||||||
|
transpilePackages: ['@mixan/queue'],
|
||||||
|
eslint: { ignoreDuringBuilds: true },
|
||||||
|
typescript: { ignoreBuildErrors: true },
|
||||||
|
experimental: {
|
||||||
|
// Avoid "Critical dependency: the request of a dependency is an expression"
|
||||||
|
serverComponentsExternalPackages: ['bullmq'],
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* If you are using `appDir` then you must comment the below `i18n` config out.
|
||||||
|
*
|
||||||
|
* @see https://github.com/vercel/next.js/issues/41980
|
||||||
|
*/
|
||||||
|
i18n: {
|
||||||
|
locales: ['en'],
|
||||||
|
defaultLocale: 'en',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const withNextra = nextra({
|
||||||
|
theme: 'nextra-theme-docs',
|
||||||
|
themeConfig: './theme.config.jsx',
|
||||||
|
flexsearch: {
|
||||||
|
codeblocks: false,
|
||||||
|
},
|
||||||
|
defaultShowCopyCode: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default withNextra(config);
|
||||||
46
apps/docs/package.json
Normal file
46
apps/docs/package.json
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
"name": "@mixan/docs",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "rm -rf .next && pnpm with-env next dev",
|
||||||
|
"build": "next build",
|
||||||
|
"start": "next start",
|
||||||
|
"lint": "eslint .",
|
||||||
|
"format": "prettier --write \"**/*.{tsx,mjs,ts,md,json}\"",
|
||||||
|
"typecheck": "tsc --noEmit",
|
||||||
|
"with-env": "dotenv -e ../../.env -c --"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"next": "~14.0.4",
|
||||||
|
"nextra": "^2.13.4",
|
||||||
|
"nextra-theme-docs": "^2.13.4",
|
||||||
|
"react": "18.2.0",
|
||||||
|
"react-dom": "18.2.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@mixan/eslint-config": "workspace:*",
|
||||||
|
"@mixan/prettier-config": "workspace:*",
|
||||||
|
"@mixan/tsconfig": "workspace:*",
|
||||||
|
"@types/node": "^18.16.0",
|
||||||
|
"@types/react": "^18.2.20",
|
||||||
|
"@types/react-dom": "^18.2.7",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^6.6.0",
|
||||||
|
"@typescript-eslint/parser": "^6.6.0",
|
||||||
|
"autoprefixer": "^10.4.18",
|
||||||
|
"eslint": "^8.48.0",
|
||||||
|
"postcss": "^8.4.35",
|
||||||
|
"prettier": "^3.0.3",
|
||||||
|
"tailwindcss": "^3.4.1",
|
||||||
|
"typescript": "^5.2.2"
|
||||||
|
},
|
||||||
|
"eslintConfig": {
|
||||||
|
"root": true,
|
||||||
|
"extends": [
|
||||||
|
"@mixan/eslint-config/base",
|
||||||
|
"@mixan/eslint-config/react",
|
||||||
|
"@mixan/eslint-config/nextjs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"prettier": "@mixan/prettier-config"
|
||||||
|
}
|
||||||
6
apps/docs/postcss.config.js
Normal file
6
apps/docs/postcss.config.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
module.exports = {
|
||||||
|
plugins: {
|
||||||
|
tailwindcss: {},
|
||||||
|
autoprefixer: {},
|
||||||
|
},
|
||||||
|
}
|
||||||
12
apps/docs/src/components/device-id-warning.tsx
Normal file
12
apps/docs/src/components/device-id-warning.tsx
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
import { Callout } from 'nextra/components';
|
||||||
|
|
||||||
|
export function DeviceIdWarning() {
|
||||||
|
return (
|
||||||
|
<Callout>
|
||||||
|
Read more about{' '}
|
||||||
|
<Link href="/docs/device-id">device id and why you might want it</Link>.
|
||||||
|
**We recommend not to but it's up to you.**
|
||||||
|
</Callout>
|
||||||
|
);
|
||||||
|
}
|
||||||
10
apps/docs/src/components/personal-data-warning.tsx
Normal file
10
apps/docs/src/components/personal-data-warning.tsx
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { Callout } from 'nextra/components';
|
||||||
|
|
||||||
|
export function PersonalDataWarning() {
|
||||||
|
return (
|
||||||
|
<Callout emoji="⚠️">
|
||||||
|
Keep in mind that this is considered personal data. Make sure you have the
|
||||||
|
users consent before calling this!
|
||||||
|
</Callout>
|
||||||
|
);
|
||||||
|
}
|
||||||
5
apps/docs/src/components/sdk-config.mdx
Normal file
5
apps/docs/src/components/sdk-config.mdx
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
- `url` - The url of the openpanel API or your self-hosted instance
|
||||||
|
- `clientId` - The client id of your application
|
||||||
|
- `trackScreenViews` - If true, the library will automatically track screen views
|
||||||
|
- `trackOutgoingLinks` - If true, the library will automatically track outgoing links
|
||||||
|
- `trackAttributes` - If true, the library will automatically track attributes
|
||||||
7
apps/docs/src/globals.css
Normal file
7
apps/docs/src/globals.css
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
|
||||||
|
article main a {
|
||||||
|
@apply underline;
|
||||||
|
}
|
||||||
11
apps/docs/src/pages/_app.tsx
Normal file
11
apps/docs/src/pages/_app.tsx
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import type { AppProps } from 'next/app';
|
||||||
|
|
||||||
|
import 'src/globals.css';
|
||||||
|
|
||||||
|
export default function App({ Component, pageProps }: AppProps) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Component {...pageProps} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
10
apps/docs/src/pages/_meta.json
Normal file
10
apps/docs/src/pages/_meta.json
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"index": {
|
||||||
|
"title": "Introduction",
|
||||||
|
"type": "page"
|
||||||
|
},
|
||||||
|
"docs": {
|
||||||
|
"title": "Documentation",
|
||||||
|
"type": "page"
|
||||||
|
}
|
||||||
|
}
|
||||||
14
apps/docs/src/pages/docs/_meta.json
Normal file
14
apps/docs/src/pages/docs/_meta.json
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"index": "Get Started",
|
||||||
|
"-- Implementation": {
|
||||||
|
"type": "separator",
|
||||||
|
"title": "Implementation"
|
||||||
|
},
|
||||||
|
"script": "Script",
|
||||||
|
"javascript": "Javascript SDK",
|
||||||
|
"nextjs": "Next.js",
|
||||||
|
"react": "React",
|
||||||
|
"react-native": "React-Native",
|
||||||
|
"remix": "Remix",
|
||||||
|
"vue": "Vue"
|
||||||
|
}
|
||||||
80
apps/docs/src/pages/docs/index.mdx
Normal file
80
apps/docs/src/pages/docs/index.mdx
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
import { Card, Cards } from 'nextra/components';
|
||||||
|
|
||||||
|
# Get started
|
||||||
|
|
||||||
|
Create an account on [Openpanel](https://openpanel.dev) and setup your first project (takes 2 minutes). You will get a `clientId` that you will use to initialize Openpanel in your app.
|
||||||
|
|
||||||
|
<Cards>
|
||||||
|
<Card
|
||||||
|
icon={
|
||||||
|
<img
|
||||||
|
style={{ width: 32, height: 32, objectFit: 'contain' }}
|
||||||
|
src="https://upload.wikimedia.org/wikipedia/commons/thumb/6/61/HTML5_logo_and_wordmark.svg/240px-HTML5_logo_and_wordmark.svg.png"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
title="General / Script"
|
||||||
|
href="/docs/general"
|
||||||
|
>
|
||||||
|
{' '}
|
||||||
|
</Card>
|
||||||
|
<Card
|
||||||
|
icon={
|
||||||
|
<img
|
||||||
|
style={{ width: 32, height: 32, objectFit: 'contain' }}
|
||||||
|
src="https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/React-icon.svg/2300px-React-icon.svg.png"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
title="React"
|
||||||
|
href="/docs/react"
|
||||||
|
>
|
||||||
|
{' '}
|
||||||
|
</Card>
|
||||||
|
<Card
|
||||||
|
icon={
|
||||||
|
<img
|
||||||
|
style={{ width: 32, height: 32, objectFit: 'contain' }}
|
||||||
|
src="https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/React-icon.svg/2300px-React-icon.svg.png"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
title="React-Native"
|
||||||
|
href="/docs/react-native"
|
||||||
|
>
|
||||||
|
{' '}
|
||||||
|
</Card>
|
||||||
|
<Card
|
||||||
|
icon={
|
||||||
|
<img
|
||||||
|
style={{ width: 32, height: 32, objectFit: 'contain' }}
|
||||||
|
src="https://static-00.iconduck.com/assets.00/nextjs-icon-512x512-y563b8iq.png"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
title="Next.js"
|
||||||
|
href="/docs/nextjs"
|
||||||
|
>
|
||||||
|
{' '}
|
||||||
|
</Card>
|
||||||
|
<Card
|
||||||
|
icon={
|
||||||
|
<img
|
||||||
|
style={{ width: 32, height: 32, objectFit: 'contain' }}
|
||||||
|
src="https://www.datocms-assets.com/205/1642515307-square-logo.svg"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
title="Remix"
|
||||||
|
href="/docs/remix"
|
||||||
|
>
|
||||||
|
{' '}
|
||||||
|
</Card>
|
||||||
|
<Card
|
||||||
|
icon={
|
||||||
|
<img
|
||||||
|
style={{ width: 32, height: 32, objectFit: 'contain' }}
|
||||||
|
src="https://upload.wikimedia.org/wikipedia/commons/thumb/9/95/Vue.js_Logo_2.svg/1024px-Vue.js_Logo_2.svg.png"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
title="Vue"
|
||||||
|
href="/docs/vue"
|
||||||
|
>
|
||||||
|
{' '}
|
||||||
|
</Card>
|
||||||
|
</Cards>
|
||||||
139
apps/docs/src/pages/docs/javascript.mdx
Normal file
139
apps/docs/src/pages/docs/javascript.mdx
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
import { Callout, Steps, Tabs } from 'nextra/components';
|
||||||
|
import { DeviceIdWarning } from 'src/components/device-id-warning';
|
||||||
|
import { PersonalDataWarning } from 'src/components/personal-data-warning';
|
||||||
|
|
||||||
|
import SdkConfig from 'src/components/sdk-config.mdx';
|
||||||
|
|
||||||
|
# Javascript SDK
|
||||||
|
|
||||||
|
This is the base SDK for Openpanel. All other SDKs are built on top of this one.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
<Steps>
|
||||||
|
### Install dependencies
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm install @openpanel/sdk
|
||||||
|
```
|
||||||
|
|
||||||
|
### Initialize
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { Openpanel } from '@openpanel/sdk';
|
||||||
|
|
||||||
|
const op = new Openpanel({
|
||||||
|
url: 'https://api.openpanel.dev',
|
||||||
|
clientId: '{YOUR_CLIENT_ID}',
|
||||||
|
// mostly for backend and apps that can't rely on CORS
|
||||||
|
clientSecret: '{YOUR_CLIENT_SECRET}',
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Config
|
||||||
|
|
||||||
|
- `url` - The url of the openpanel API or your self-hosted instance
|
||||||
|
- `clientId` - The client id of your application
|
||||||
|
- `clientSecret` - The client secret of your application (mostly for backend and apps that can't rely on CORS)
|
||||||
|
|
||||||
|
### Ready!
|
||||||
|
|
||||||
|
You're now ready to use the library.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Sends an event with payload foo: bar
|
||||||
|
op.event('my_event', { foo: 'bar' });
|
||||||
|
|
||||||
|
// Identify with profile id
|
||||||
|
op.setProfileId('123');
|
||||||
|
|
||||||
|
// or with additional data
|
||||||
|
op.setProfile({
|
||||||
|
profileId: '123',
|
||||||
|
firstName: 'John',
|
||||||
|
lastName: 'Doe',
|
||||||
|
email: 'john.doe@openpanel.dev',
|
||||||
|
});
|
||||||
|
|
||||||
|
// Increment a property
|
||||||
|
op.increment('app_opened'); // increment by 1
|
||||||
|
op.increment('app_opened', 5); // increment by 5
|
||||||
|
|
||||||
|
// Decrement a property
|
||||||
|
op.decrement('app_opened'); // decrement by 1
|
||||||
|
op.decrement('app_opened', 5); // decrement by 5
|
||||||
|
```
|
||||||
|
|
||||||
|
</Steps>
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Track event
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
op.event('my_event', { foo: 'bar' });
|
||||||
|
```
|
||||||
|
|
||||||
|
### Identify
|
||||||
|
|
||||||
|
#### Set Profile Id
|
||||||
|
|
||||||
|
Keep track of your users by identifying them with a unique id. This is a good features if you have things behind a login and want to track user behavior.
|
||||||
|
|
||||||
|
<PersonalDataWarning />
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { setProfileId } from '@openpanel/nextjs';
|
||||||
|
|
||||||
|
const profileId = '123';
|
||||||
|
setProfileId(profileId);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Additional data
|
||||||
|
|
||||||
|
This method does the same as `setProfileId` but also allows you to update the profile with additional data.
|
||||||
|
|
||||||
|
<PersonalDataWarning />
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { setProfile } from '@openpanel/nextjs';
|
||||||
|
|
||||||
|
const profileId = '123';
|
||||||
|
setProfile({
|
||||||
|
profileId,
|
||||||
|
// firstName?: string;
|
||||||
|
// lastName?: string;
|
||||||
|
// email?: string;
|
||||||
|
// avatar?: string;
|
||||||
|
// properties?: Record<string, unknown>;
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Increment property
|
||||||
|
|
||||||
|
Increment a property on the profile.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { increment } from '@openpanel/nextjs';
|
||||||
|
|
||||||
|
// Increment by 1
|
||||||
|
increment('app_opened');
|
||||||
|
|
||||||
|
// Increment by 5
|
||||||
|
increment('app_opened', 5);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Decrement property
|
||||||
|
|
||||||
|
Decrement a property on the profile.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { decrement } from '@openpanel/nextjs';
|
||||||
|
|
||||||
|
// Increment by 1
|
||||||
|
decrement('app_opened');
|
||||||
|
|
||||||
|
// Increment by 5
|
||||||
|
decrement('app_opened', 5);
|
||||||
|
```
|
||||||
172
apps/docs/src/pages/docs/nextjs.mdx
Normal file
172
apps/docs/src/pages/docs/nextjs.mdx
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
import { Callout, Steps, Tabs } from 'nextra/components';
|
||||||
|
import { DeviceIdWarning } from 'src/components/device-id-warning';
|
||||||
|
import { PersonalDataWarning } from 'src/components/personal-data-warning';
|
||||||
|
|
||||||
|
import SdkConfig from 'src/components/sdk-config.mdx';
|
||||||
|
|
||||||
|
# Next.js
|
||||||
|
|
||||||
|
Keep in mind that all tracking here happens on the client! If you want to track server-side events, you should use the <Link href="/docs/node">node SDK</Link> 👀.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
<Steps>
|
||||||
|
### Install dependencies
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm install @openpanel/nextjs
|
||||||
|
```
|
||||||
|
|
||||||
|
### Initialize
|
||||||
|
|
||||||
|
Add `OpenpanelProvider` to your root layout component.
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { OpenpanelProvider } from '@openpanel/nextjs';
|
||||||
|
|
||||||
|
export default RootLayout({ children }) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<OpenpanelProvider
|
||||||
|
url="https://api.openpanel.dev"
|
||||||
|
clientId="your-client-id"
|
||||||
|
trackScreenViews={true}
|
||||||
|
// trackAttributes={true}
|
||||||
|
// trackOutgoingLinks={true}
|
||||||
|
/>
|
||||||
|
{children}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Config
|
||||||
|
|
||||||
|
<SdkConfig />
|
||||||
|
|
||||||
|
### Ready!
|
||||||
|
|
||||||
|
You're now ready to use the library.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import {
|
||||||
|
decrement,
|
||||||
|
increment,
|
||||||
|
setProfile,
|
||||||
|
setProfileId,
|
||||||
|
trackEvent,
|
||||||
|
trackScreenView,
|
||||||
|
} from '@openpanel/nextjs';
|
||||||
|
|
||||||
|
// Sends an event with payload foo: bar
|
||||||
|
trackEvent('my_event', { foo: 'bar' });
|
||||||
|
|
||||||
|
// Identify with profile id
|
||||||
|
setProfileId('123');
|
||||||
|
|
||||||
|
// or with additional data
|
||||||
|
setProfile({
|
||||||
|
profileId: '123',
|
||||||
|
firstName: 'John',
|
||||||
|
lastName: 'Doe',
|
||||||
|
email: 'john.doe@openpanel.dev',
|
||||||
|
});
|
||||||
|
|
||||||
|
// Increment a property
|
||||||
|
increment('app_opened'); // increment by 1
|
||||||
|
increment('app_opened', 5); // increment by 5
|
||||||
|
|
||||||
|
// Decrement a property
|
||||||
|
decrement('app_opened'); // decrement by 1
|
||||||
|
decrement('app_opened', 5); // decrement by 5
|
||||||
|
```
|
||||||
|
|
||||||
|
</Steps>
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Track event
|
||||||
|
|
||||||
|
<Tabs items={['JS', 'window', 'HTML']}>
|
||||||
|
<Tabs.Tab>
|
||||||
|
```typescript
|
||||||
|
import { trackEvent } from '@openpanel/nextjs';
|
||||||
|
trackEvent('my_event', { foo: 'bar' });
|
||||||
|
```
|
||||||
|
</Tabs.Tab>
|
||||||
|
<Tabs.Tab>
|
||||||
|
```javascript
|
||||||
|
window.op('event', 'my_event', { foo: 'bar' });
|
||||||
|
```
|
||||||
|
</Tabs.Tab>
|
||||||
|
<Tabs.Tab>
|
||||||
|
For this to work you need to enable `trackAttributes` in the config.
|
||||||
|
```html
|
||||||
|
<button data-event="my_event" data-foo="bar">Track event</button>
|
||||||
|
```
|
||||||
|
</Tabs.Tab>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
### Identify
|
||||||
|
|
||||||
|
#### Set Profile Id
|
||||||
|
|
||||||
|
Keep track of your users by identifying them with a unique id. This is a good features if you have things behind a login and want to track user behavior.
|
||||||
|
|
||||||
|
<PersonalDataWarning />
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { setProfileId } from '@openpanel/nextjs';
|
||||||
|
|
||||||
|
const profileId = '123';
|
||||||
|
setProfileId(profileId);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Additional data
|
||||||
|
|
||||||
|
This method does the same as `setProfileId` but also allows you to update the profile with additional data.
|
||||||
|
|
||||||
|
<PersonalDataWarning />
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { setProfile } from '@openpanel/nextjs';
|
||||||
|
|
||||||
|
const profileId = '123';
|
||||||
|
setProfile({
|
||||||
|
profileId,
|
||||||
|
// firstName?: string;
|
||||||
|
// lastName?: string;
|
||||||
|
// email?: string;
|
||||||
|
// avatar?: string;
|
||||||
|
// properties?: Record<string, unknown>;
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Increment property
|
||||||
|
|
||||||
|
Increment a property on the profile.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { increment } from '@openpanel/nextjs';
|
||||||
|
|
||||||
|
// Increment by 1
|
||||||
|
increment('app_opened');
|
||||||
|
|
||||||
|
// Increment by 5
|
||||||
|
increment('app_opened', 5);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Decrement property
|
||||||
|
|
||||||
|
Decrement a property on the profile.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { decrement } from '@openpanel/nextjs';
|
||||||
|
|
||||||
|
// Increment by 1
|
||||||
|
decrement('app_opened');
|
||||||
|
|
||||||
|
// Increment by 5
|
||||||
|
decrement('app_opened', 5);
|
||||||
|
```
|
||||||
196
apps/docs/src/pages/docs/react-native.mdx
Normal file
196
apps/docs/src/pages/docs/react-native.mdx
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
import { Callout, Steps, Tabs } from 'nextra/components';
|
||||||
|
import { DeviceIdWarning } from 'src/components/device-id-warning';
|
||||||
|
import { PersonalDataWarning } from 'src/components/personal-data-warning';
|
||||||
|
|
||||||
|
import SdkConfig from 'src/components/sdk-config.mdx';
|
||||||
|
|
||||||
|
# React-Native
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
<Steps>
|
||||||
|
### Install dependencies
|
||||||
|
|
||||||
|
We're dependent on `expo-application` for `buildNumber`, `versionNumber` (and `referrer` on android) and `expo-constants` to get the `user-agent`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm install @openpanel/react-native
|
||||||
|
expo install --pnpm expo-application expo-constants
|
||||||
|
```
|
||||||
|
|
||||||
|
### Initialize
|
||||||
|
|
||||||
|
On native we use a clientSecret to authenticate the app.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const op = new Openpanel({
|
||||||
|
url: 'https://api.openpanel.dev',
|
||||||
|
clientId: '{YOUR_CLIENT_ID}',
|
||||||
|
clientSecret: '{YOUR_CLIENT_SECRET}',
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Config
|
||||||
|
|
||||||
|
- `url` - The url of the openpanel API or your self-hosted instance
|
||||||
|
- `clientId` - The client id of your application
|
||||||
|
- `clientSecret` - The client secret of your application
|
||||||
|
|
||||||
|
### Ready!
|
||||||
|
|
||||||
|
You're now ready to use the library.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Sends an event with payload foo: bar
|
||||||
|
op.event('my_event', { foo: 'bar' });
|
||||||
|
|
||||||
|
// Identify with profile id
|
||||||
|
op.setProfileId('123');
|
||||||
|
|
||||||
|
// or with additional data
|
||||||
|
op.setProfile({
|
||||||
|
profileId: '123',
|
||||||
|
firstName: 'John',
|
||||||
|
lastName: 'Doe',
|
||||||
|
email: 'john.doe@openpanel.dev',
|
||||||
|
});
|
||||||
|
|
||||||
|
// Increment a property
|
||||||
|
op.increment('app_opened'); // increment by 1
|
||||||
|
op.increment('app_opened', 5); // increment by 5
|
||||||
|
|
||||||
|
// Decrement a property
|
||||||
|
op.decrement('app_opened'); // decrement by 1
|
||||||
|
op.decrement('app_opened', 5); // decrement by 5
|
||||||
|
```
|
||||||
|
|
||||||
|
</Steps>
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Track event
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
op.event('my_event', { foo: 'bar' });
|
||||||
|
```
|
||||||
|
|
||||||
|
### Navigation / Screen views
|
||||||
|
|
||||||
|
<Tabs items={['expo-router', 'react-navigation (simple)']}>
|
||||||
|
<Tabs.Tab>
|
||||||
|
```typescript
|
||||||
|
import { usePathname, useSegments } from 'expo-router';
|
||||||
|
|
||||||
|
function RootLayout() {
|
||||||
|
// ...
|
||||||
|
const pathname = usePathname()
|
||||||
|
// Segments is optional but can be nice to have if you
|
||||||
|
// want to group routes together
|
||||||
|
// pathname = /posts/123
|
||||||
|
// segements = ['posts', '[id]']
|
||||||
|
const segments = useSegments()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Simple
|
||||||
|
op.screenView(pathname)
|
||||||
|
|
||||||
|
// With extra data
|
||||||
|
op.screenView(pathname, {
|
||||||
|
// segments is optional but nice to have
|
||||||
|
segments: segments.join('/'),
|
||||||
|
// other optional data you want to send with the screen view
|
||||||
|
})
|
||||||
|
}, [pathname,segments])
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</Tabs.Tab>
|
||||||
|
<Tabs.Tab>
|
||||||
|
```tsx
|
||||||
|
import { createNavigationContainerRef } from '@react-navigation/native'
|
||||||
|
import { Openpanel } from '@openpanel/react-native'
|
||||||
|
|
||||||
|
const op = new Openpanel({ /* ... */ })
|
||||||
|
const navigationRef = createNavigationContainerRef()
|
||||||
|
|
||||||
|
export function NavigationRoot() {
|
||||||
|
const handleNavigationStateChange = () => {
|
||||||
|
const current = navigationRef.getCurrentRoute()
|
||||||
|
if (current) {
|
||||||
|
op.screenView(current.name, {
|
||||||
|
params: current.params,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NavigationContainer
|
||||||
|
ref={navigationRef}
|
||||||
|
onReady={handleNavigationStateChange}
|
||||||
|
onStateChange={handleNavigationStateChange}
|
||||||
|
>
|
||||||
|
<Stack.Navigator />
|
||||||
|
</NavigationContainer>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</Tabs.Tab>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
### Identify
|
||||||
|
|
||||||
|
#### Set Profile Id
|
||||||
|
|
||||||
|
Keep track of your users by identifying them with a unique id. This is a good features if you have things behind a login and want to track user behavior.
|
||||||
|
|
||||||
|
<PersonalDataWarning />
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const profileId = '123';
|
||||||
|
op.setProfileId(profileId);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Additional data
|
||||||
|
|
||||||
|
This method does the same as `setProfileId` but also allows you to update the profile with additional data.
|
||||||
|
|
||||||
|
<PersonalDataWarning />
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const profileId = '123';
|
||||||
|
op.setProfile({
|
||||||
|
profileId,
|
||||||
|
// firstName?: string;
|
||||||
|
// lastName?: string;
|
||||||
|
// email?: string;
|
||||||
|
// avatar?: string;
|
||||||
|
// properties?: Record<string, unknown>;
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Increment property
|
||||||
|
|
||||||
|
Increment a property on the profile.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Increment by 1
|
||||||
|
op.increment('app_opened');
|
||||||
|
|
||||||
|
// Increment by 5
|
||||||
|
op.increment('app_opened', 5);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Decrement property
|
||||||
|
|
||||||
|
Decrement a property on the profile.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Increment by 1
|
||||||
|
op.decrement('app_opened');
|
||||||
|
|
||||||
|
// Increment by 5
|
||||||
|
op.decrement('app_opened', 5);
|
||||||
|
```
|
||||||
5
apps/docs/src/pages/docs/react.mdx
Normal file
5
apps/docs/src/pages/docs/react.mdx
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
|
||||||
|
# React
|
||||||
|
|
||||||
|
Use <Link href="/docs/general">script tag</Link> or <Link href="/docs/general">Javascript SDK</Link> for now. We'll add a dedicated react sdk soon.
|
||||||
5
apps/docs/src/pages/docs/remix.mdx
Normal file
5
apps/docs/src/pages/docs/remix.mdx
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
|
||||||
|
# Remix
|
||||||
|
|
||||||
|
Use <Link href="/docs/general">script tag</Link> or <Link href="/docs/general">Javascript SDK</Link> for now. We'll add a dedicated react sdk soon.
|
||||||
122
apps/docs/src/pages/docs/script.mdx
Normal file
122
apps/docs/src/pages/docs/script.mdx
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
import { Callout, Tabs } from 'nextra/components';
|
||||||
|
import { PersonalDataWarning } from 'src/components/personal-data-warning';
|
||||||
|
|
||||||
|
import SdkConfig from 'src/components/sdk-config.mdx';
|
||||||
|
|
||||||
|
# Script tag
|
||||||
|
|
||||||
|
Just insert this snippet and replace `{YOUR_CLIENT_ID}` with your client id.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script src="https://openpanel.dev/op.js"></script>
|
||||||
|
<script>
|
||||||
|
window.op =
|
||||||
|
window.op ||
|
||||||
|
function (...args) {
|
||||||
|
(window.op.q = window.op.q || []).push(args);
|
||||||
|
};
|
||||||
|
window.op('ctor', {
|
||||||
|
url: 'https://api.openpanel.dev',
|
||||||
|
clientId: '{YOUR_CLIENT_ID}',
|
||||||
|
trackScreenViews: true,
|
||||||
|
// trackOutgoingLinks: true,
|
||||||
|
// trackAttributes: true,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Config
|
||||||
|
|
||||||
|
<SdkConfig />
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
You can let the library track screen views, outgoing links and attributes tracking by setting the `trackScreenViews`, `trackOutgoingLinks` and `trackAttributes` options to `true`.
|
||||||
|
|
||||||
|
### Track event
|
||||||
|
|
||||||
|
<Tabs items={['JS', 'HTML']}>
|
||||||
|
<Tabs.Tab>
|
||||||
|
```javascript
|
||||||
|
window.op('event', 'my_event', { foo: 'bar' });
|
||||||
|
```
|
||||||
|
</Tabs.Tab>
|
||||||
|
<Tabs.Tab>
|
||||||
|
For this to work you need to enable `trackAttributes` in the config.
|
||||||
|
```html
|
||||||
|
<button data-event="my_event" data-foo="bar">Track event</button>
|
||||||
|
```
|
||||||
|
</Tabs.Tab>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
### Identify
|
||||||
|
|
||||||
|
#### Set Profile Id
|
||||||
|
|
||||||
|
Keep track of your users by identifying them with a unique id. This is a good features if you have things behind a login and want to track user behavior.
|
||||||
|
|
||||||
|
<PersonalDataWarning />
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const profileId = '123';
|
||||||
|
window.op('setProfileId', profileId);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Additional data
|
||||||
|
|
||||||
|
This method does the same as `setProfileId` but also allows you to update the profile with additional data.
|
||||||
|
|
||||||
|
<PersonalDataWarning />
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const profileId = '123';
|
||||||
|
window.op('setProfile', {
|
||||||
|
profileId,
|
||||||
|
// firstName?: string;
|
||||||
|
// lastName?: string;
|
||||||
|
// email?: string;
|
||||||
|
// avatar?: string;
|
||||||
|
// properties?: Record<string, unknown>;
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Increment property
|
||||||
|
|
||||||
|
Increment a property on the profile.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Increment by 1
|
||||||
|
window.op('increment', 'app_opened');
|
||||||
|
|
||||||
|
// Increment by 5
|
||||||
|
window.op('increment', 'app_opened', 5);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Decrement property
|
||||||
|
|
||||||
|
Decrement a property on the profile.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Increment by 1
|
||||||
|
window.op('decrement', 'app_opened');
|
||||||
|
|
||||||
|
// Increment by 5
|
||||||
|
window.op('decrement', 'app_opened', 5);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Typescript
|
||||||
|
|
||||||
|
Is your IDE mad at you for not using typescript? We got you covered.
|
||||||
|
|
||||||
|
Add this and it will stop complain about `window.op` not being defined.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
op: {
|
||||||
|
q?: [string, ...any[]];
|
||||||
|
(method: string, ...args: any[]): void;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
5
apps/docs/src/pages/docs/vue.mdx
Normal file
5
apps/docs/src/pages/docs/vue.mdx
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
|
||||||
|
# Vue
|
||||||
|
|
||||||
|
Use <Link href="/docs/general">script tag</Link> or <Link href="/docs/general">Javascript SDK</Link> for now. We'll add a dedicated react sdk soon.
|
||||||
14
apps/docs/src/pages/index.mdx
Normal file
14
apps/docs/src/pages/index.mdx
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# Introduction
|
||||||
|
|
||||||
|
Openpanel is an open-source alternative to Mixpanel. Combining the power of Mixpanel with the ease of Plausible, Openpanel is a privacy-focused analytics tool that gives you the insights you need to make data-driven decisions.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- ✅ **Privacy-focused**: Openpanel is built with privacy in mind. We don't track any personal data and we don't use cookies.
|
||||||
|
- ✅ **Open-source**: Openpanel is open-source and you can host it yourself.
|
||||||
|
- ✅ **Cloud-hosted**: You can choose our cloud hosting if you don't want to host it yourself. We take care of the infrastructure and you can focus on your business.
|
||||||
|
- ✅ **Real-time analytics**: Everything is updated in real-time, no delays to see your insights.
|
||||||
|
- ✅ **Event-based tracking**: You can track any event you want, and you can track as many events as you want.
|
||||||
|
- ✅ **Custom properties**: You can add custom properties to your events to track more data.
|
||||||
|
- ✅ **Funnel analysis**: You can create funnels to see how your users are interacting with your product.
|
||||||
|
- ✅ **Reports**: Create as many reports as you want to visualize the data you need.
|
||||||
8
apps/docs/tailwind.config.js
Normal file
8
apps/docs/tailwind.config.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
module.exports = {
|
||||||
|
content: ['./src/**/*.{js,ts,jsx,tsx,mdx}'],
|
||||||
|
theme: {
|
||||||
|
extend: {},
|
||||||
|
},
|
||||||
|
plugins: [],
|
||||||
|
};
|
||||||
75
apps/docs/theme.config.jsx
Normal file
75
apps/docs/theme.config.jsx
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
import Image from 'next/image';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
import { useConfig } from 'nextra-theme-docs';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
logo: (
|
||||||
|
<>
|
||||||
|
<Image
|
||||||
|
src="https://dashboard.openpanel.dev/logo.svg"
|
||||||
|
alt="next-international logo"
|
||||||
|
height="32"
|
||||||
|
width="32"
|
||||||
|
/>
|
||||||
|
<strong style={{ marginLeft: '8px' }}>openpanel</strong>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
head: (props) => {
|
||||||
|
const router = useRouter();
|
||||||
|
const config = useConfig();
|
||||||
|
const title = config.title;
|
||||||
|
const description =
|
||||||
|
config.description || 'An open-source alternative to Mixpanel';
|
||||||
|
const domain = 'https://docs.openpanel.dev';
|
||||||
|
const canonicalUrl =
|
||||||
|
`${domain}${router.asPath === '/' ? '' : router.asPath}`.split('?')[0];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<meta property="description" content={description} />
|
||||||
|
<link rel="canonical" href={canonicalUrl} />
|
||||||
|
<meta name="twitter:card" content="summary_large_image" />
|
||||||
|
<meta
|
||||||
|
name="twitter:site:domain"
|
||||||
|
content={domain.replace('https://', '')}
|
||||||
|
/>
|
||||||
|
<meta name="twitter:url" content={domain} />
|
||||||
|
<meta name="og:type" content={`site`} />
|
||||||
|
<meta name="og:url" content={canonicalUrl} />
|
||||||
|
<meta name="og:title" content={`${title} - Openpanel Docs`} />
|
||||||
|
<meta property="og:description" content={description} />
|
||||||
|
<meta name="og:image" content={'https://openpanel.dev/ogimage.png'} />
|
||||||
|
<meta name="title" content={title} />
|
||||||
|
<meta name="description" content={description} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
search: {
|
||||||
|
placeholder: 'Search',
|
||||||
|
},
|
||||||
|
project: {
|
||||||
|
link: 'https://github.com/openpanel-dev/openpanel',
|
||||||
|
},
|
||||||
|
docsRepositoryBase:
|
||||||
|
'https://github.com/openpanel-dev/openpanel/blob/main/apps/docs',
|
||||||
|
useNextSeoProps() {
|
||||||
|
return {
|
||||||
|
titleTemplate: '%s - Openpanel',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
footer: {
|
||||||
|
text: (
|
||||||
|
<span>
|
||||||
|
Made with ❤️ by{' '}
|
||||||
|
<a
|
||||||
|
href="https://twitter.com/CarlLindesvard"
|
||||||
|
target="_blank"
|
||||||
|
rel="nofollow"
|
||||||
|
>
|
||||||
|
Carl
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
};
|
||||||
25
apps/docs/tsconfig.json
Normal file
25
apps/docs/tsconfig.json
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"extends": "@mixan/tsconfig/base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@/*": [
|
||||||
|
"./src/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"name": "next"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tsBuildInfoFile": "node_modules/.cache/tsbuildinfo.json",
|
||||||
|
"strictNullChecks": true
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
".",
|
||||||
|
".next/types/**/*.ts"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"node_modules"
|
||||||
|
]
|
||||||
|
}
|
||||||
2080
pnpm-lock.yaml
generated
2080
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user