Bieber 61c0e31840
feat: user integrations management and slack integration T1322 (#2294)
* feat: support slack integrations

* chore: upgrade nextjs

* feat: add user temp internal token

---------

Co-authored-by: Boris <boris2code@outlook.com>
2025-12-17 23:08:19 +08:00
..
2024-10-23 15:24:49 +08:00
2024-09-26 18:57:03 +08:00
2025-12-09 14:43:29 +08:00
2024-09-26 18:57:03 +08:00
2024-09-26 18:57:03 +08:00
2024-10-28 21:52:24 +08:00
2024-11-04 16:25:22 +08:00
2024-09-26 18:57:03 +08:00

Plugin Development Guide

Table of Contents

  1. Overview
  2. Plugin Structure
  3. Creating a Plugin
  4. Plugin Configuration
  5. Plugin Bridge
  6. Internationalization
  7. Publishing

Overview

Plugins are extensions that can be integrated into different positions within the application. All official plugins are managed within a single Next.js project (plugins), allowing for code sharing and simplified maintenance.

Supported Positions

Plugins can be integrated into two main positions:

export enum PluginPosition {
  Dashboard = 'dashboard',
  View = 'view',
}

Plugin Structure

Project Structure

The plugins project uses Next.js App Router structure:

plugins/
├── src/
│   ├── app/
│   │   ├── chart/              # Chart plugin
│   │   │   ├── components/
│   │   │   ├── page.tsx
│   │   │   └── favicon.ico
│   │   ├── sheet-form/         # Sheet Form plugin
│   │   │   ├── components/
│   │   │   ├── page.tsx
│   │   │   └── favicon.ico
│   ├── components/             # Shared components
│   ├── locales/               # i18n translations
│   │   ├── chart/
│   │   │   ├── en.json
│   │   │   └── zh.json
│   │   └── sheet-form/
│   │       ├── en.json
│   │       └── zh.json
│   └── types.ts
├── package.json
└── tsconfig.json

Plugin Page Structure

Each plugin should have its own directory under src/app/ with the following structure:

import type { Metadata } from 'next';
import { EnvProvider } from '../../components/EnvProvider';
import { I18nProvider } from '../../components/I18nProvider';
import QueryClientProvider from '../../components/QueryClientProvider';
import { PageType } from '../../components/types';
import enCommonJson from '../../locales/chart/en.json';
import zhCommonJson from '../../locales/chart/zh.json';
import { Pages } from './components/Pages';

export async function generateMetadata({ searchParams }: Props): Promise<Metadata> {
  const lang = searchParams.lang;
  return {
    title: lang === 'zh' ? '图表' : 'Chart',
    icons: icon.src,
  };
}

export default async function Home(props: { searchParams: IPageParams }) {
  return (
    <main className="flex h-screen flex-col items-center justify-center">
      <EnvProvider>
        <I18nProvider
          lang={props.searchParams.lang}
          resources={resources}
          defaultNS="common"
          pageType={PageType.Chart}
        >
          <QueryClientProvider>
            <Pages {...props.searchParams} />
          </QueryClientProvider>
        </I18nProvider>
      </EnvProvider>
    </main>
  );
}

Creating a Plugin

1. Create Plugin Directory

Add a new directory under src/app/ for your plugin:

src/app/my-plugin/
├── components/
├── page.tsx
└── favicon.ico

2. Configure Plugin

Create a plugin configuration file:

import { PluginPosition } from '@teable/openapi';
import type { IOfficialPluginConfig } from './types';

export const myPluginConfig: IOfficialPluginConfig = {
  id: 'plg-my-plugin',
  name: 'My Plugin',
  description: 'Plugin description',
  detailDesc: `Detailed description with markdown support`,
  helpUrl: 'https://help.teable.ai',
  positions: [PluginPosition.Dashboard],
  i18n: {
    zh: {
      name: '我的插件',
      helpUrl: 'https://help.teable.cn',
      description: '插件描述',
      detailDesc: '详细描述',
    },
  },
  logoPath: 'static/plugin/my-plugin.png',
  pluginUserId: 'plgmypluginuser',
  avatarPath: 'static/plugin/my-plugin.png',
};

Plugin Bridge

The Plugin Bridge enables communication between your plugin and the main application.

Bridge Methods

const methods: IParentBridgeMethods = {
  expandRecord: (recordIds) => {
    console.log('expandRecord', recordIds);
  },
  updateStorage: (storage) => {
    return updateDashboardPluginStorage(baseId, positionId, pluginInstallId, storage).then(
      (res) => res.data.storage ?? {}
    );
  },
  getAuthCode: () => {
    return pluginGetAuthCode(pluginId, baseId).then((res) => res.data);
  },
  expandPlugin: () => {
    onExpand?.();
  },
};

Initializing the Bridge

export const initializeBridge = async () => {
  if (typeof window === 'undefined') {
    return;
  }
  const pluginBridge = new PluginBridge();
  const bridge = await pluginBridge.init();
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  (window as any)._teable_plugin_bridge = bridge;
  return bridge;
};

Internationalization

Add translations for your plugin under src/locales/[plugin-name]/:

{
  "title": "我的插件",
  "description": "插件描述",
  "actions": {
    "save": "保存",
    "cancel": "取消"
  }
}

Publishing

  1. Development Status: Plugins start in developing status
  2. Review Process: Submit for review using the plugin management interface
  3. Publication: Once approved, the plugin will be published and available in the plugin center

Plugin Status Flow

export enum PluginStatus {
  Developing = 'developing',
  Reviewing = 'reviewing',
  Published = 'published',
}

Best Practices

  1. Code Sharing: Utilize shared components and utilities from the plugins project
  2. Consistent UI: Follow the design patterns used by other plugins
  3. Error Handling: Implement proper error handling and display user-friendly messages
  4. Responsive Design: Ensure your plugin works well in different container sizes
  5. Performance: Optimize loading time and resource usage
  6. Security: Never expose sensitive information in the client-side code
  7. Documentation: Document your plugin's features and configuration options

For more detailed information and API references, please refer to our complete API documentation.

Best Practices

  1. Error Handling: Implement proper error handling and display user-friendly messages
  2. Responsive Design: Ensure your plugin works well in different container sizes
  3. Performance: Optimize loading time and resource usage
  4. Security: Never expose sensitive information in the client-side code
  5. Documentation: Provide clear documentation for your plugin's features and configuration options

For more detailed information and API references, please refer to our complete API documentation.