7 Commits

Author SHA1 Message Date
Carl-Gerhard Lindesvärd
420f540874 fix 2026-02-26 14:04:48 +01:00
Carl-Gerhard Lindesvärd
6ddea4a7bc comments 2026-02-26 12:40:28 +01:00
Carl-Gerhard Lindesvärd
d5513d8a47 final fixes 2026-02-26 11:37:20 +01:00
Carl-Gerhard Lindesvärd
b193ccb7d0 wip 2026-02-25 22:44:51 +01:00
Carl-Gerhard Lindesvärd
41993d3463 wip 2026-02-25 22:44:50 +01:00
Carl-Gerhard Lindesvärd
47adf46625 wip 2026-02-25 22:43:59 +01:00
Carl-Gerhard Lindesvärd
551927af06 wip 2026-02-25 22:43:59 +01:00
25 changed files with 169 additions and 286 deletions

View File

@@ -3,37 +3,55 @@ name: Docker Build and Push
on:
workflow_dispatch:
push:
paths-ignore:
# README and docs
- "**/README*"
- "**/readme*"
- "**/*.md"
- "**/docs/**"
- "**/CHANGELOG*"
- "**/LICENSE*"
# Test files
- "**/*.test.*"
- "**/*.spec.*"
- "**/__tests__/**"
- "**/tests/**"
# SDKs (published separately)
- "packages/sdks/**"
# Public app (docs/marketing, not part of Docker deploy)
# branches: [ "main" ]
paths:
- "apps/api/**"
- "apps/worker/**"
- "apps/public/**"
# Dev / tooling
- "**/.vscode/**"
- "**/.cursor/**"
- "**/.env.example"
- "**/.env.*.example"
- "**/.gitignore"
- "**/.eslintignore"
- "**/.prettierignore"
- "apps/start/**"
- "packages/**"
- "!packages/sdks/**"
- "**Dockerfile"
- ".github/workflows/**"
env:
repo_owner: "openpanel-dev"
jobs:
changes:
runs-on: ubuntu-latest
outputs:
api: ${{ steps.filter.outputs.api }}
worker: ${{ steps.filter.outputs.worker }}
public: ${{ steps.filter.outputs.public }}
dashboard: ${{ steps.filter.outputs.dashboard }}
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v2
id: filter
with:
base: "main"
filters: |
api:
- 'apps/api/**'
- 'packages/**'
- '.github/workflows/**'
worker:
- 'apps/worker/**'
- 'packages/**'
- '.github/workflows/**'
public:
- 'apps/public/**'
- 'packages/**'
- '.github/workflows/**'
dashboard:
- 'apps/start/**'
- 'packages/**'
- '.github/workflows/**'
lint-and-test:
needs: changes
if: ${{ needs.changes.outputs.api == 'true' || needs.changes.outputs.worker == 'true' || needs.changes.outputs.public == 'true' || needs.changes.outputs.dashboard == 'true' }}
runs-on: ubuntu-latest
services:
redis:
@@ -88,7 +106,8 @@ jobs:
permissions:
packages: write
contents: write
needs: lint-and-test
needs: [changes, lint-and-test]
if: ${{ needs.changes.outputs.api == 'true' }}
runs-on: ubuntu-latest
steps:
- name: Checkout repository
@@ -148,7 +167,8 @@ jobs:
permissions:
packages: write
contents: write
needs: lint-and-test
needs: [changes, lint-and-test]
if: ${{ needs.changes.outputs.worker == 'true' }}
runs-on: ubuntu-latest
steps:
- name: Checkout repository
@@ -208,7 +228,8 @@ jobs:
permissions:
packages: write
contents: write
needs: lint-and-test
needs: [changes, lint-and-test]
if: ${{ needs.changes.outputs.dashboard == 'true' }}
runs-on: ubuntu-latest
steps:
- name: Checkout repository

View File

@@ -14,15 +14,14 @@ export async function duplicateHook(
const ip = req.clientIp;
const origin = req.headers.origin;
const clientId = req.headers['openpanel-client-id'];
const body = req?.body;
const isTrackPayload = getIsTrackPayload(req);
const isReplay = isTrackPayload && req.body.type === 'replay';
const isReplay = 'type' in req.body && req.body.type === 'replay';
const shouldCheck = ip && origin && clientId && !isReplay;
const isDuplicate = shouldCheck
? await isDuplicatedEvent({
ip,
origin,
payload: body,
payload: req.body,
projectId: clientId as string,
})
: false;
@@ -31,25 +30,3 @@ export async function duplicateHook(
return reply.status(200).send('Duplicate event');
}
}
function getIsTrackPayload(
req: FastifyRequest<{
Body: ITrackHandlerPayload | DeprecatedPostEventPayload;
}>
): req is FastifyRequest<{
Body: ITrackHandlerPayload;
}> {
if (req.method !== 'POST') {
return false;
}
if (!req.body) {
return false;
}
if (typeof req.body !== 'object' || Array.isArray(req.body)) {
return false;
}
return 'type' in req.body;
}

View File

@@ -61,7 +61,7 @@
"notes": "OpenPanel's SDK is over 20x smaller than PostHog's core library, resulting in faster page loads and better Core Web Vitals."
},
{
"label": "Cookie-Free",
"label": "Cookie-Free by Default",
"openpanel": "Yes",
"competitor": "Requires Configuration",
"notes": "OpenPanel is truly cookie-free out of the box. PostHog requires specific configuration for cookieless tracking with reduced functionality."
@@ -504,4 +504,4 @@
"href": "https://github.com/Openpanel-dev/openpanel"
}
}
}
}

View File

@@ -32,9 +32,7 @@ npx expo install expo-application expo-constants
On native we use a clientSecret to authenticate the app.
```typescript
import { OpenPanel } from '@openpanel/react-native';
const op = new OpenPanel({
const op = new Openpanel({
clientId: '{YOUR_CLIENT_ID}',
clientSecret: '{YOUR_CLIENT_SECRET}',
});

View File

@@ -20,7 +20,7 @@
"@opennextjs/cloudflare": "^1.16.5",
"@openpanel/common": "workspace:*",
"@openpanel/geo": "workspace:*",
"@openpanel/nextjs": "^1.2.0",
"@openpanel/nextjs": "^1.1.1",
"@openpanel/payments": "workspace:^",
"@openpanel/sdk-info": "workspace:^",
"@openstatus/react": "0.0.3",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -6,7 +6,6 @@ import { getRootMetadata } from '@/lib/metadata';
import { cn } from '@/lib/utils';
import './global.css';
import { OpenPanelComponent } from '@openpanel/nextjs';
import { ScrollTracker } from '@/components/scroll-tracker';
const font = Geist({
subsets: ['latin'],
@@ -40,13 +39,9 @@ export default function Layout({ children }: { children: React.ReactNode }) {
<RootProvider>
<TooltipProvider>{children}</TooltipProvider>
</RootProvider>
<ScrollTracker />
{process.env.NEXT_PUBLIC_OP_CLIENT_ID && (
<OpenPanelComponent
clientId={process.env.NEXT_PUBLIC_OP_CLIENT_ID}
sessionReplay={{
enabled: true,
}}
trackAttributes
trackOutgoingLinks
trackScreenViews

View File

@@ -1,43 +0,0 @@
'use client';
import { useOpenPanel } from '@openpanel/nextjs';
import { useRef } from 'react';
interface FeatureCardHoverTrackProps {
title: string;
children: React.ReactNode;
}
export function FeatureCardHoverTrack({
title,
children,
}: FeatureCardHoverTrackProps) {
const { track } = useOpenPanel();
const hoverTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
const handleMouseEnter = () => {
hoverTimerRef.current = setTimeout(() => {
track('feature_card_hover', { title });
hoverTimerRef.current = null;
}, 1500);
};
const handleMouseLeave = () => {
if (hoverTimerRef.current) {
clearTimeout(hoverTimerRef.current);
hoverTimerRef.current = null;
}
};
return (
// Hover handlers for analytics only; no keyboard interaction needed
// biome-ignore lint/a11y/noNoninteractiveElementInteractions: analytics hover tracking
<div
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
role="group"
>
{children}
</div>
);
}

View File

@@ -1,8 +1,6 @@
import type { LucideIcon } from 'lucide-react';
import Link from 'next/link';
import { cn } from '@/lib/utils';
import { FeatureCardHoverTrack } from '@/components/feature-card-hover-track';
interface FeatureCardProps {
link?: {
@@ -66,45 +64,41 @@ export function FeatureCard({
}: FeatureCardProps) {
if (illustration) {
return (
<FeatureCardHoverTrack title={title}>
<FeatureCardContainer className={className}>
{illustration}
<div className="col gap-2" data-content>
<h3 className="font-semibold text-xl">{title}</h3>
<p className="text-muted-foreground">{description}</p>
</div>
{children}
{link && (
<Link
className="mx-6 text-muted-foreground text-sm transition-colors hover:text-primary"
href={link.href}
>
{link.children}
</Link>
)}
</FeatureCardContainer>
</FeatureCardHoverTrack>
);
}
return (
<FeatureCardHoverTrack title={title}>
<FeatureCardContainer className={className}>
{Icon && <Icon className="size-6" />}
<div className="col gap-2">
<h3 className="font-semibold text-lg">{title}</h3>
<p className="text-muted-foreground text-sm">{description}</p>
{illustration}
<div className="col gap-2" data-content>
<h3 className="font-semibold text-xl">{title}</h3>
<p className="text-muted-foreground">{description}</p>
</div>
{children}
{link && (
<Link
className="text-muted-foreground text-sm transition-colors hover:text-primary"
className="mx-6 text-muted-foreground text-sm transition-colors hover:text-primary"
href={link.href}
>
{link.children}
</Link>
)}
</FeatureCardContainer>
</FeatureCardHoverTrack>
);
}
return (
<FeatureCardContainer className={className}>
{Icon && <Icon className="size-6" />}
<div className="col gap-2">
<h3 className="font-semibold text-lg">{title}</h3>
<p className="text-muted-foreground text-sm">{description}</p>
</div>
{children}
{link && (
<Link
className="text-muted-foreground text-sm transition-colors hover:text-primary"
href={link.href}
>
{link.children}
</Link>
)}
</FeatureCardContainer>
);
}

View File

@@ -1,37 +0,0 @@
'use client';
import { useOpenPanel } from '@openpanel/nextjs';
import { usePathname } from 'next/navigation';
import { useEffect, useRef } from 'react';
export function ScrollTracker() {
const { track } = useOpenPanel();
const pathname = usePathname();
const hasFired = useRef(false);
useEffect(() => {
hasFired.current = false;
const handleScroll = () => {
if (hasFired.current) {
return;
}
const scrollTop = window.scrollY;
const docHeight =
document.documentElement.scrollHeight - window.innerHeight;
const percent =
docHeight > 0 ? (scrollTop / docHeight) * 100 : 0;
if (percent >= 50) {
hasFired.current = true;
track('scroll_half_way', { percent: Math.round(percent) });
}
};
window.addEventListener('scroll', handleScroll, { passive: true });
return () => window.removeEventListener('scroll', handleScroll);
}, [track, pathname]);
return null;
}

View File

@@ -38,9 +38,10 @@
"@openpanel/integrations": "workspace:^",
"@openpanel/json": "workspace:*",
"@openpanel/payments": "workspace:*",
"@openpanel/sdk": "^1.0.8",
"@openpanel/sdk-info": "workspace:^",
"@openpanel/validation": "workspace:^",
"@openpanel/web": "^1.0.1",
"@openpanel/web": "^1.0.12",
"@radix-ui/react-accordion": "^1.2.12",
"@radix-ui/react-alert-dialog": "^1.1.15",
"@radix-ui/react-aspect-ratio": "^1.1.7",

View File

@@ -102,18 +102,7 @@ export function KeyValueGrid({
<button
onClick={(e) => {
e.stopPropagation();
if (typeof item.value === 'object') {
try {
const value = JSON.stringify(item.value);
clipboard(value);
}
catch {
clipboard(item.value);
}
}
else {
clipboard(item.value);
}
clipboard(item.value);
}}
type="button"
className="absolute left-2 top-1/2 -translate-y-1/2 -translate-x-full opacity-0 group-hover:translate-x-0 group-hover:opacity-100 transition-all duration-200 ease-out bg-background border border-border rounded p-1 shadow-sm z-10"

View File

@@ -1,26 +1,17 @@
import type { AppRouter } from '@openpanel/trpc';
import { QueryClient } from '@tanstack/react-query';
import { createIsomorphicFn } from '@tanstack/react-start';
import { getRequestHeaders } from '@tanstack/react-start/server';
import { createTRPCClient, httpLink } from '@trpc/client';
import { createTRPCOptionsProxy } from '@trpc/tanstack-react-query';
import { useMemo } from 'react';
import superjson from 'superjson';
import { TRPCProvider } from '@/integrations/trpc/react';
import type { AppRouter } from '@openpanel/trpc';
import { createIsomorphicFn } from '@tanstack/react-start';
import { getRequestHeaders } from '@tanstack/react-start/server';
import { useMemo } from 'react';
export const getIsomorphicHeaders = createIsomorphicFn()
.server(() => {
const headers = getRequestHeaders();
const result: Record<string, string> = {};
// Only forward the cookie header so the API can validate the session.
// Forwarding all headers causes problems with hop-by-hop headers like
// `Connection: upgrade` (common in NGINX WebSocket configs) which makes
// Node.js undici throw UND_ERR_INVALID_ARG ("fetch failed").
const cookie = headers.get('Cookie');
if (cookie) {
result.cookie = cookie;
}
return result;
return getRequestHeaders();
})
.client(() => {
return {};
@@ -36,6 +27,7 @@ export function createTRPCClientWithHeaders(apiUrl: string) {
headers: () => getIsomorphicHeaders(),
fetch: async (url, options) => {
try {
console.log('fetching', url, options);
const response = await fetch(url, {
...options,
mode: 'cors',
@@ -90,8 +82,8 @@ export function getContext(apiUrl: string) {
const client = createTRPCClientWithHeaders(apiUrl);
const serverHelpers = createTRPCOptionsProxy({
client,
queryClient,
client: client,
queryClient: queryClient,
});
return {
queryClient,
@@ -110,10 +102,10 @@ export function Provider({
}) {
const trpcClient = useMemo(
() => createTRPCClientWithHeaders(apiUrl),
[apiUrl]
[apiUrl],
);
return (
<TRPCProvider queryClient={queryClient} trpcClient={trpcClient}>
<TRPCProvider trpcClient={trpcClient} queryClient={queryClient}>
{children}
</TRPCProvider>
);

View File

@@ -2,6 +2,7 @@ import fs from 'node:fs';
import path from 'node:path';
import { TABLE_NAMES } from '../src/clickhouse/client';
import {
addColumns,
createTable,
modifyTTL,
runClickhouseMigrationCommands,
@@ -24,8 +25,8 @@ export async function up() {
'`is_full_snapshot` Bool',
'`payload` String CODEC(ZSTD(6))',
],
orderBy: ['project_id', 'session_id', 'started_at', 'chunk_index'],
partitionBy: 'toYYYYMMDD(started_at)',
orderBy: ['project_id', 'session_id', 'chunk_index'],
partitionBy: 'toYYYYMM(started_at)',
settings: {
index_granularity: 8192,
},
@@ -41,16 +42,16 @@ export async function up() {
];
fs.writeFileSync(
path.join(import.meta.filename.replace('.ts', '.sql')),
path.join(__filename.replace('.ts', '.sql')),
sqls
.map((sql) =>
sql
.trim()
.replace(/;$/, '')
.replace(/\n{2,}/g, '\n')
.concat(';')
.concat(';'),
)
.join('\n\n---\n\n')
.join('\n\n---\n\n'),
);
if (!process.argv.includes('--dry')) {

View File

@@ -1,6 +1,6 @@
{
"name": "@openpanel/astro",
"version": "1.1.0-local",
"version": "1.0.7-local",
"config": {
"transformPackageJson": false,
"transformEnvs": true,
@@ -12,15 +12,10 @@
"scripts": {
"typecheck": "tsc --noEmit"
},
"files": [
"src",
"index.ts"
],
"keywords": [
"astro-component"
],
"files": ["src", "index.ts"],
"keywords": ["astro-component"],
"dependencies": {
"@openpanel/web": "workspace:1.1.0-local"
"@openpanel/web": "workspace:1.0.7-local"
},
"devDependencies": {
"astro": "^5.7.7"

View File

@@ -35,7 +35,7 @@ const methods: { name: OpenPanelMethodNames; value: unknown }[] = [
value: {
...options,
sdk: 'astro',
sdkVersion: '1.1.0',
sdkVersion: '1.0.7',
},
},
];

View File

@@ -1,6 +1,6 @@
{
"name": "@openpanel/express",
"version": "1.1.0-local",
"version": "1.0.5-local",
"module": "index.ts",
"config": {
"docPath": "apps/public/content/docs/(tracking)/sdks/express.mdx"
@@ -10,7 +10,7 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@openpanel/sdk": "workspace:1.1.0-local",
"@openpanel/sdk": "workspace:1.0.4-local",
"@openpanel/common": "workspace:*"
},
"peerDependencies": {

View File

@@ -1,6 +1,6 @@
{
"name": "@openpanel/nextjs",
"version": "1.2.0-local",
"version": "1.1.4-local",
"module": "index.ts",
"config": {
"docPath": "apps/public/content/docs/(tracking)/sdks/nextjs.mdx"
@@ -10,7 +10,7 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@openpanel/web": "workspace:1.1.0-local"
"@openpanel/web": "workspace:1.0.7-local"
},
"peerDependencies": {
"next": "^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0",

View File

@@ -1,6 +1,6 @@
{
"name": "@openpanel/nuxt",
"version": "0.1.0-local",
"version": "0.0.4-local",
"type": "module",
"main": "./dist/module.mjs",
"exports": {
@@ -9,9 +9,7 @@
"import": "./dist/module.mjs"
}
},
"files": [
"dist"
],
"files": ["dist"],
"config": {
"transformPackageJson": false,
"transformEnvs": false,
@@ -24,7 +22,7 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@openpanel/web": "workspace:1.1.0-local"
"@openpanel/web": "workspace:1.0.7-local"
},
"peerDependencies": {
"h3": "^1.0.0",

View File

@@ -1,6 +1,6 @@
{
"name": "@openpanel/react-native",
"version": "1.1.0-local",
"version": "1.0.6-local",
"module": "index.ts",
"config": {
"docPath": "apps/public/content/docs/(tracking)/sdks/react-native.mdx"
@@ -10,7 +10,7 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@openpanel/sdk": "workspace:1.1.0-local"
"@openpanel/sdk": "workspace:1.0.4-local"
},
"devDependencies": {
"@openpanel/tsconfig": "workspace:*",

View File

@@ -1,6 +1,6 @@
{
"name": "@openpanel/sdk",
"version": "1.1.0-local",
"version": "1.0.4-local",
"module": "index.ts",
"config": {
"docPath": "apps/public/content/docs/(tracking)/sdks/javascript.mdx"

View File

@@ -1,6 +1,6 @@
{
"name": "@openpanel/web",
"version": "1.1.0-local",
"version": "1.0.7-local",
"module": "index.ts",
"config": {
"docPath": "apps/public/content/docs/(tracking)/sdks/web.mdx"
@@ -10,7 +10,7 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@openpanel/sdk": "workspace:1.1.0-local",
"@openpanel/sdk": "workspace:1.0.4-local",
"@rrweb/types": "2.0.0-alpha.20",
"rrweb": "2.0.0-alpha.20"
},
@@ -20,4 +20,4 @@
"tsup": "^7.2.0",
"typescript": "catalog:"
}
}
}

55
pnpm-lock.yaml generated
View File

@@ -285,8 +285,8 @@ importers:
specifier: workspace:*
version: link:../../packages/geo
'@openpanel/nextjs':
specifier: ^1.2.0
version: 1.2.0(next@16.0.7(@opentelemetry/api@1.9.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
specifier: ^1.1.1
version: 1.1.1(next@16.0.7(@opentelemetry/api@1.9.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
'@openpanel/payments':
specifier: workspace:^
version: link:../../packages/payments
@@ -465,6 +465,9 @@ importers:
'@openpanel/payments':
specifier: workspace:*
version: link:../../packages/payments
'@openpanel/sdk':
specifier: ^1.0.8
version: 1.0.8
'@openpanel/sdk-info':
specifier: workspace:^
version: link:../../packages/sdks/_info
@@ -472,8 +475,8 @@ importers:
specifier: workspace:^
version: link:../../packages/validation
'@openpanel/web':
specifier: ^1.0.1
version: 1.0.5
specifier: ^1.0.12
version: 1.0.12
'@radix-ui/react-accordion':
specifier: ^1.2.12
version: 1.2.12(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
@@ -1481,7 +1484,7 @@ importers:
packages/sdks/astro:
dependencies:
'@openpanel/web':
specifier: workspace:1.1.0-local
specifier: workspace:1.0.12-local
version: link:../web
devDependencies:
astro:
@@ -1494,7 +1497,7 @@ importers:
specifier: workspace:*
version: link:../../common
'@openpanel/sdk':
specifier: workspace:1.1.0-local
specifier: workspace:1.0.8-local
version: link:../sdk
express:
specifier: ^4.17.0 || ^5.0.0
@@ -1519,7 +1522,7 @@ importers:
packages/sdks/nextjs:
dependencies:
'@openpanel/web':
specifier: workspace:1.1.0-local
specifier: workspace:1.0.12-local
version: link:../web
next:
specifier: ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0
@@ -1547,7 +1550,7 @@ importers:
packages/sdks/nuxt:
dependencies:
'@openpanel/web':
specifier: workspace:1.1.0-local
specifier: workspace:1.0.12-local
version: link:../web
h3:
specifier: ^1.0.0
@@ -1584,7 +1587,7 @@ importers:
packages/sdks/react-native:
dependencies:
'@openpanel/sdk':
specifier: workspace:1.1.0-local
specifier: workspace:1.0.8-local
version: link:../sdk
expo-application:
specifier: 5 - 7
@@ -1630,7 +1633,7 @@ importers:
packages/sdks/web:
dependencies:
'@openpanel/sdk':
specifier: workspace:1.1.0-local
specifier: workspace:1.0.8-local
version: link:../sdk
'@rrweb/types':
specifier: 2.0.0-alpha.20
@@ -5866,8 +5869,8 @@ packages:
next: ~15.0.8 || ~15.1.12 || ~15.2.9 || ~15.3.9 || ~15.4.11 || ~15.5.10 || ~16.0.11 || ^16.1.5
wrangler: ^4.59.2
'@openpanel/nextjs@1.2.0':
resolution: {integrity: sha512-APHnOj34aeOM0JZMqSPWPV1oMDiY9I21MBEm+ne3G00H/fNkE2RyG4F0yxoxripn1EqiZK65a07HZH8qfLgXdQ==}
'@openpanel/nextjs@1.1.1':
resolution: {integrity: sha512-azJSB+SxL4ybj9MA1mDZkLBJ67jbZoDQB52SjaPS0lSBLVEQkcJVMO5x+sZFd9UgVVwWIvkTECdLLF+9eyXf8w==}
peerDependencies:
next: ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
@@ -5876,15 +5879,15 @@ packages:
'@openpanel/sdk@1.0.2':
resolution: {integrity: sha512-WvVWCBcJvJhM5MYKO5Hxjo4G/E0tnK5XK2UC+hKDHtoF+iKvtUWa5bz18pFAPQprq0u/Ev2YqirPsrMQJy5g2g==}
'@openpanel/sdk@1.1.0':
resolution: {integrity: sha512-KxFEbY+s0wP5I+su1+j1AOVn6Uvw0QMO+iXbEcmW2MkFAaIuIIPYkHFELxiLPuePLI54gYfbmTr2ZMlz9GJtZw==}
'@openpanel/sdk@1.0.8':
resolution: {integrity: sha512-mr7HOZ/vqrJaATDFxcv3yyLjXcUXgsfboa0o0GlhiAYUh2B1Q0kgsm5qkfbtZhTqYP4BmNCWRkfRlpFp4pfpPQ==}
'@openpanel/web@1.0.12':
resolution: {integrity: sha512-39oL19HYrw4qAzlxbtFP/rfLOaciWJXCxPwL6bk+u4SUcrrOrwmjSg0CwQYyrd2p3wp1QnsCiyv2n0EtEpjQMA==}
'@openpanel/web@1.0.5':
resolution: {integrity: sha512-n/A9fKiHWcDTH2N6N8MM214ET7aoNJjgpLux0GRW+CD0KDEwI8UosQvvz3UOGHZ3jWqMMsUNdU2B7eYk2W87mg==}
'@openpanel/web@1.1.0':
resolution: {integrity: sha512-5AUG/uBZZaeMKFNsp5l21D3Lj0ddPLK4NS/XIol7Q0jp2n6Za2wO5UlJ9MUatMoSLyLHc4a1BK9t+gbBlN7cMg==}
'@openstatus/react@0.0.3':
resolution: {integrity: sha512-uDiegz7e3H67pG8lTT+op+6w5keTT7XpcENrREaqlWl5j53TYyO8nheOG1PeNw2/Qgd5KaGeRJJFn1crhTUSYw==}
peerDependencies:
@@ -25003,27 +25006,27 @@ snapshots:
- encoding
- supports-color
'@openpanel/nextjs@1.2.0(next@16.0.7(@opentelemetry/api@1.9.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
'@openpanel/nextjs@1.1.1(next@16.0.7(@opentelemetry/api@1.9.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
dependencies:
'@openpanel/web': 1.1.0
'@openpanel/web': 1.0.5
next: 16.0.7(@opentelemetry/api@1.9.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
react: 19.2.3
react-dom: 19.2.3(react@19.2.3)
'@openpanel/sdk@1.0.2': {}
'@openpanel/sdk@1.1.0': {}
'@openpanel/sdk@1.0.8': {}
'@openpanel/web@1.0.12':
dependencies:
'@openpanel/sdk': 1.0.8
'@rrweb/types': 2.0.0-alpha.20
rrweb: 2.0.0-alpha.20
'@openpanel/web@1.0.5':
dependencies:
'@openpanel/sdk': 1.0.2
'@openpanel/web@1.1.0':
dependencies:
'@openpanel/sdk': 1.1.0
'@rrweb/types': 2.0.0-alpha.20
rrweb: 2.0.0-alpha.20
'@openstatus/react@0.0.3(react@19.2.3)':
dependencies:
react: 19.2.3

View File

@@ -1,6 +1,5 @@
NODE_ENV="production"
VITE_SELF_HOSTED="true"
SELF_HOSTED="true"
BATCH_SIZE="5000"
BATCH_INTERVAL="10000"
ALLOW_REGISTRATION="false"
@@ -14,4 +13,4 @@ DASHBOARD_URL="$DASHBOARD_URL"
API_URL="$API_URL"
COOKIE_SECRET="$COOKIE_SECRET"
EMAIL_SENDER="$EMAIL_SENDER"
RESEND_API_KEY="$RESEND_API_KEY"
RESEND_API_KEY="$RESEND_API_KEY"