Skip to content

Instantly share code, notes, and snippets.

@eonist
Last active June 7, 2025 15:21
Show Gist options
  • Save eonist/ee07682be2903fea071dd16eca2cb299 to your computer and use it in GitHub Desktop.
Save eonist/ee07682be2903fea071dd16eca2cb299 to your computer and use it in GitHub Desktop.
Build research.md

You're correct that Figma plugins have strict file constraints - they can only accept a single JavaScript file and a single HTML file, with no ability to load external files[10]. Here are the main approaches to bundle TypeScript, CSS, and HTML files into the required single-file format:

Webpack with TypeScript

Webpack is the most commonly recommended solution for Figma plugin bundling[1]. Here's how to set it up:

Install dependencies:

npm install --save-dev typescript ts-loader webpack webpack-cli
npm install --save-dev html-webpack-plugin style-loader css-loader

Basic webpack.config.js:

const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');

module.exports = {
  entry: {
    ui: './src/ui.ts',
    code: './src/code.ts'
  },
  module: {
    rules: [
      { test: /\.tsx?$/, use: 'ts-loader', exclude: /node_modules/ },
      { test: /\.css$/, use: ['style-loader', 'css-loader'] },
      { test: /\.(png|jpg|gif|webp|svg)$/, loader: 'url-loader' }
    ]
  },
  output: {
    filename: '[name].js',
    path: path.resolve(__dirname, 'dist')
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/ui.html',
      filename: 'ui.html',
      chunks: ['ui']
    })
  ]
};

For inlining JavaScript directly into HTML (eliminating the separate JS file), you can use the html-webpack-inline-source-plugin[9].

Rollup Alternative

Rollup offers another approach, particularly good for Figma plugins[4]:

Install dependencies:

npm install --save-dev rollup @rollup/plugin-node-resolve @rollup/plugin-commonjs
npm install --save-dev rollup-plugin-postcss rollup-plugin-html-bundle rollup-plugin-terser

Rollup configuration example:

import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import postcss from 'rollup-plugin-postcss';
import htmlBundle from 'rollup-plugin-html-bundle';
import { terser } from 'rollup-plugin-terser';

export default [
  {
    input: 'src/main.js',
    output: {
      format: 'umd',
      name: 'ui',
      file: 'public/bundle.js'
    },
    plugins: [
      resolve({ browser: true }),
      commonjs(),
      postcss({ extensions: ['.css'] }),
      htmlBundle({
        template: 'src/template.html',
        target: 'public/index.html',
        inline: true  // This inlines JS into HTML
      }),
      terser()
    ]
  },
  {
    input: 'src/code.js',
    output: {
      file: 'public/code.js',
      format: 'iife'
    },
    plugins: [resolve(), commonjs(), terser()]
  }
];

HTML Bundler Plugin (Modern Webpack Approach)

The newer HTML Bundler Plugin simplifies the entire process[8]:

npm install --save-dev html-bundler-webpack-plugin

This plugin allows you to use HTML as the entry point and automatically processes all referenced CSS and JS files, bundling everything together.

Ready-Made Boilerplates

Several boilerplates handle this complexity for you:

Thomas Lowry's Boilerplate[7]:

  • Pre-configured with Gulp build process
  • Write HTML, SCSS, and vanilla JavaScript normally
  • Automatically inlines and bundles everything into single files
  • Handles image assets by converting them to data URIs

Advanced Boilerplate[10]:

  • Supports TypeScript, React, Sass/SCSS
  • Handles SVG imports as React components
  • Includes communication patterns between plugin code and UI
  • Pre-configured bundling with Vite/Rollup

Project Structure

Your typical project structure should look like this[1]:

src/
  ├── code.ts          # Main plugin logic
  ├── ui.html          # UI template
  ├── ui.ts           # UI JavaScript
  ├── styles/
  │   └── main.css    # Stylesheets
  └── components/     # Additional modules
dist/
  ├── code.js         # Bundled plugin code
  └── ui.html         # Bundled UI with inline CSS/JS

The key is that your build process must inline all CSS and JavaScript into the final HTML file, as Figma plugins cannot reference external assets[7][10]. Choose Webpack if you prefer a mature ecosystem, or Rollup for simpler configuration and smaller bundle sizes.

[1] https://www.figma.com/plugin-docs/libraries-and-bundling/ [2] https://www.fabiofranchino.com/log/use-rollup-to-inject-bundled-javascript-into-an-html-file/ [3] https://stackoverflow.com/questions/46866228/how-to-bundle-html-js-and-css-in-one-html-file-with-webpack [4] https://tomquinonero.com/blog/write-a-figma-plugin-using-svelte/ [5] https://dev.to/geekygeeky/how-we-built-a-figma-plugin-in-300-lines-of-code-4l24 [6] https://www.figma.com/plugin-docs/typescript/ [7] https://github.com/thomas-lowry/figma-plugin-boilerplate/blob/master/README.md [8] https://hackernoon.com/the-right-way-to-utilize-webpack-for-bundling-a-html-page-with-css-and-js [9] https://stackoverflow.com/questions/68512734/how-to-bundle-js-inline-into-html-file [10] https://github.com/brreg/designsystem-figma-plugin [11] https://forum.figma.com/ask-the-community-7/solved-use-functions-from-bundled-js-files-in-ui-split-ui-js-into-multiple-files-11818 [12] https://evilmartians.com/chronicles/how-to-make-next-level-figma-plugins-auth-routing-storage-and-more [13] https://forum.figma.com/ask-the-community-7/external-javascript-file-for-my-plugin-36295 [14] https://stackoverflow.com/questions/78399749/how-can-i-bundle-my-full-stack-ts-application-with-html-all-into-one-html-js-and [15] webpack/webpack#15163 [16] https://www.coryetzkorn.com/writing/building-a-figma-plugin [17] https://github.com/aarongarciah/figma-plugin-typescript-boilerplate [18] https://www.youtube.com/watch?v=3rT4tHsbC1k [19] https://www.youtube.com/watch?v=fCAZ5JuUygw [20] https://dev.to/markliu2013/multiple-html-files-using-webpack-1116 [21] https://stackoverflow.com/questions/47546300/webpack-bundle-multiple-vendor-css-in-one-separate-file/47549457 [22] https://tripleten.com/blog/posts/merging-a-web-project-into-a-single-file-the-magic-of-webpack [23] https://www.matthewsimo.com/posts/2024-03-05-figma-plugin-template

You're right that Webpack can be bloated for simple use cases. Here are several lighter, faster alternatives that work perfectly for Figma plugin bundling:

ESBuild (Recommended for Figma Plugins)

ESBuild is extremely fast and well-suited for Figma plugins. It's written in Go and is 10-100x faster than Webpack[1][3].

Installation:

npm install --save-dev esbuild

For Figma plugins specifically, here's a proven setup:

tsconfig.json configuration:

{
  "compilerOptions": {
    "allowImportingTsExtensions": true,
    "isolatedModules": true,
    "noEmit": true
  }
}

Build commands:

# Bundle your plugin code
./node_modules/.bin/esbuild code.ts --bundle --outfile=code.js

# For UI with CSS inlining
esbuild ui.ts --bundle --outfile=ui.js --loader:.css=text

Auto-watch setup in package.json:

{
  "scripts": {
    "typecheck": "tsc --project tsconfig.json",
    "bundle": "./node_modules/.bin/esbuild code.ts --bundle --outfile=code.js",
    "watch_typecheck": "npm run typecheck -- --watch --preserveWatchOutput", 
    "watch_bundle": "npm run bundle -- --watch=forever",
    "watch": "parallel --ungroup 'npm run' ::: watch_typecheck watch_bundle"
  }
}

ESBuild supports TypeScript and JSX syntax natively, performs tree shaking, and doesn't require a cache[1][2].

Vite

Vite is modern, fast, and much simpler than Webpack. It uses ESBuild under the hood for development and Rollup for production builds[3].

Installation:

npm install --save-dev vite

vite.config.js:

import { defineConfig } from 'vite'

export default defineConfig({
  build: {
    rollupOptions: {
      input: {
        code: 'src/code.ts',
        ui: 'src/ui.html'
      },
      output: {
        entryFileNames: '[name].js'
      }
    }
  }
})

There's a proven Figma plugin boilerplate using Vite and ESBuild that separates the plugin logic and UI into different folders with their own configurations[5].

Parcel

Parcel offers zero configuration and is much faster than Webpack[6]. It automatically handles different file types including CSS, images, and HTML without any setup.

Installation:

npm install --save-dev parcel

Usage:

# Start with your HTML file as entry point
parcel build src/ui.html --dist-dir dist

# For the plugin code
parcel build src/code.ts --dist-dir dist

Parcel automatically bundles any assets referenced in your HTML file. It supports advanced features without heavy configuration and has an extensible plugin system[6].

Rollup

Rollup excels at producing smaller bundles through excellent tree-shaking. It's perfect for libraries and lightweight projects[3].

Installation:

npm install --save-dev rollup @rollup/plugin-node-resolve @rollup/plugin-commonjs @rollup/plugin-typescript

rollup.config.js:

import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import typescript from '@rollup/plugin-typescript';

export default {
  input: 'src/code.ts',
  output: {
    file: 'dist/code.js',
    format: 'iife'
  },
  plugins: [
    resolve(),
    commonjs(),
    typescript()
  ]
};

FuseBox

FuseBox is designed to be a simpler, faster alternative to Webpack. It allows importing non-JavaScript files without extra workarounds and includes built-in plugins like WebIndexPlugin for auto-generating HTML files[4].

For Figma plugin development, ESBuild is likely your best choice due to its speed, TypeScript support, and the existing community solutions specifically for Figma plugins[2]. It provides the minimal setup you want while handling all the bundling requirements effectively.

[1] https://blog.openreplay.com/top-five-alternatives-to-webpack/ [2] https://gist.github.com/lzell/bcedfd754f2d8015fbd850a56f1eae92 [3] https://dev.to/mohamedlaminef/which-javascript-bundler-is-right-for-you-a-deep-dive-into-webpack-vite-and-more-50bc [4] https://www.sitepoint.com/fusebox-faster-webpack-alternative/ [5] https://github.com/gnchrv/figma-plugin-boilerplate [6] https://blixtdev.com/you-dont-need-webpack-3-better-alternatives-for-building-your-javascript/ [7] https://css-tricks.com/comparing-the-new-generation-of-build-tools/ [8] https://stackoverflow.com/questions/58945488/bundle-ts-and-css-into-single-files-with-webpack [9] https://nomadicsoft.io/top-5-webpack-alternatives-revolutionize-your-javascript-build-tools/ [10] https://www.antforfigma.com/theme-buddy-figma-plugin [11] https://www.reddit.com/r/typescript/comments/a7z2we/can_i_import_css_into_typescript_without_webpack/ [12] https://www.figma.com/plugin-docs/libraries-and-bundling/ [13] https://webpack.js.org/guides/typescript/ [14] https://esbuild.github.io/plugins/ [15] https://esbuild.github.io/api/ [16] https://auth0.com/blog/introducing-fusebox-an-alternative-to-webpack/ [17] https://yuanqing.github.io/create-figma-plugin/

Based on the search results and your specific needs for a Figma plugin with substantial JavaScript logic, here's my analysis of the main alternatives:

ESBuild

Pros:

  • Extremely fast performance (10-100x faster than Webpack)[1][5]
  • Minimal configuration required[8]
  • Built-in TypeScript and JSX support[5]
  • Specifically mentioned as good for Figma plugins[5]
  • Simple learning curve[8]

Cons:

  • Limited CSS bundling capabilities - "there may be problems with bundling css files"[1]
  • Smaller plugin ecosystem compared to other tools[8]
  • Less mature for complex asset handling

Vite

Pros:

  • Exceptional development experience with fast HMR[2]
  • Uses ESBuild for development (speed) and Rollup for production (optimization)[6]
  • Excellent tree-shaking and code splitting[2]
  • Strong TypeScript support out of the box[2]
  • Well-documented and growing community[2]
  • Proven Figma plugin boilerplate available[7]

Cons:

  • More complex than pure ESBuild[2]
  • Potential overkill for very simple projects[2]
  • Learning curve for developers new to modern tooling[2]

Rollup

Pros:

  • Excellent tree-shaking creates smaller bundles[3][8]
  • ES6 module support encourages modern JavaScript[3]
  • Optimized output perfect for production[8]

Cons:

  • No native hot module replacement support[3]
  • More complex configuration[8]
  • Smaller plugin ecosystem[3]
  • Less ideal for development workflow

My Recommendation: Vite

For your Figma plugin with substantial JavaScript logic, I recommend Vite for these reasons:

Best fit for your use case:

  • The "lots of JavaScript logic" requirement benefits from Vite's excellent tree-shaking and code splitting[2]
  • Fast development iteration is crucial when building complex logic - Vite's HMR is consistently fast regardless of application size[2]
  • There's already a proven Figma plugin boilerplate using Vite + React that handles the single-file bundling requirement[7]

Balanced approach:

  • You get ESBuild's speed during development and Rollup's optimization for production[6]
  • This dual approach gives you the best of both worlds without the complexity of managing separate tools

Future-proofing:

  • Vite has strong momentum and community support[2]
  • It's designed to handle everything from simple to complex applications[2]
  • The configuration is intuitive while still allowing advanced customization when needed[2]

Alternative recommendation: If you prioritize absolute simplicity and your CSS needs are minimal, ESBuild would be my second choice due to its speed and minimal setup, especially since it's specifically mentioned as good for Figma plugins[5].

Avoid Rollup for this project since the lack of HMR would significantly slow down development of complex JavaScript logic[3].

[1] https://elixirforum.com/t/is-it-worth-using-esbuild/47881 [2] https://blog.logrocket.com/vite-adoption-guide/ [3] https://proxify.io/articles/webpack-vs-rollup [4] https://snipcart.com/blog/javascript-module-bundler [5] https://www.figma.com/plugin-docs/libraries-and-bundling/ [6] https://www.reddit.com/r/AskProgramming/comments/13x94zl/vite_vs_rollup_vs_webpack_vs_esbuild_difference/ [7] https://github.com/CoconutGoodie/figma-plugin-react-vite [8] https://npm-compare.com/@swc/core,esbuild,rollup,vite,webpack [9] https://news.ycombinator.com/item?id=28862454 [10] https://forum.figma.com/archive-21/which-is-the-best-structure-for-spliting-code-26793 [11] https://css-tricks.com/comparing-the-new-generation-of-build-tools/ [12] https://www.telerik.com/blogs/introduction-esbuild [13] https://www.reddit.com/r/Frontend/comments/1fjuphq/best_free_plugin_to_convert_figma_designs_to_code/ [14] https://github.com/gnchrv/figma-plugin-boilerplate [15] https://news.ycombinator.com/item?id=21961963 [16] https://evilmartians.com/chronicles/how-to-make-next-level-figma-plugins-auth-routing-storage-and-more [17] https://blog.khaleelgibran.com/posts/chromakey/ [18] https://www.wearedevelopers.com/magazine/figma-plugins-for-frontend-developers [19] https://www.reddit.com/r/FigmaDesign/comments/1itc5vd/what_are_the_best_figma_plugins_and_tools_for_ui/

@eonist
Copy link
Author

eonist commented Jun 7, 2025

Based on the search results, yes, Rollup is an excellent choice for CSS import structures, especially for your Figma plugin needs. Here are the main approaches:

rollup-plugin-import-css (Recommended)

This plugin specifically handles CSS import structures and supports three different import methods:

import "./styles.css"; /* extract the styles to a external css bundle */
import styles from "./styles.css"; /* import the styles as a string */
import styles from "./styles.css" with { type: "css" }; /* import the styles as a CSSStyleSheet */

Installation:

npm install --save-dev rollup-plugin-import-css

Configuration:

import css from "rollup-plugin-import-css";

export default {
    input: "index.js",
    output: { file: "dist/index.js", format: "esm" },
    plugins: [
        css({
            inject: true,  // Injects CSS into document head at runtime
            minify: true,  // Minifies the CSS
            modules: false // Set to true for CSS modules support
        })
    ]
};

rollup-plugin-postcss (Popular Alternative)

This plugin processes CSS files and supports extraction to separate files:

import postcss from 'rollup-plugin-postcss';

export default {
    plugins: [
        postcss({
            extract: true,    // Extract to separate CSS file
            minimize: true,   // Minify CSS
            modules: true,    // CSS modules support
            extensions: ['.css']
        })
    ]
};

For Figma Plugin (Single File Requirement)

Since you need everything bundled into single files, here's a proven Rollup setup from the search results that handles CSS imports and inlines everything:

import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import postcss from 'rollup-plugin-postcss';
import htmlBundle from 'rollup-plugin-html-bundle';

export default {
    input: 'src/main.js',
    output: {
        format: 'umd',
        name: 'ui',
        file: 'public/bundle.js'
    },
    plugins: [
        resolve({ browser: true }),
        commonjs(),
        postcss({
            extensions: ['.css'],
            inject: false,  // Don't inject, we'll inline manually
            extract: false  // Don't extract to separate file
        }),
        htmlBundle({
            template: 'src/template.html',
            target: 'public/index.html',
            inline: true  // This inlines everything into single HTML
        })
    ]
};

CSS Import Structure Benefits with Rollup

Import order preservation: All these plugins respect the import order of your CSS files[1][2][7], which is crucial for CSS specificity.

Modular structure: You can organize CSS like this:

// main.js
import './styles/reset.css';
import './styles/layout.css';
import './components/button.css';

Nested imports: CSS files can also use @import statements:

/* layout.css */
@import './nested.css';
@import './more.css';

Why Rollup Over Other Options

Given your earlier preference against Webpack's complexity, Rollup is perfect because:

  • Simple configuration for CSS imports[1][4]
  • Preserves import order[1][2][7]
  • Multiple bundling strategies (inline, extract, or inject)[1][8]
  • Proven Figma plugin workflows[6] with single-file output
  • Smaller bundle sizes due to excellent tree-shaking

For your Figma plugin with substantial JavaScript logic and CSS import structures, rollup-plugin-import-css with the inject: true option would be ideal, as it allows you to use normal CSS import syntax while ensuring everything gets bundled into your single required files.

[1] https://www.npmjs.com/package/rollup-plugin-import-css
[2] https://classic.yarnpkg.com/en/package/rollup-plugin-css-bundle
[3] https://dev.to/bhargab/rollupjs-made-easy-a-step-by-step-guide-to-building-and-publishing-npm-packages-1c1k
[4] https://github.com/Evercoder/rollup-plugin-css-bundle
[5] https://github.com/jleeson/rollup-plugin-import-css
[6] https://tomquinonero.com/blog/write-a-figma-plugin-using-svelte/
[7] https://github.com/thgh/rollup-plugin-css-only
[8] https://codetv.dev/blog/learn-rollup-css
[9] https://www.dhiwise.com/post/the-ultimate-guide-to-bundling-css-with-rollup
[10] https://anidetrix.github.io/rollup-plugin-styles/
[11] https://rollupjs.org/configuration-options/
[12] rollup/rollup#5307
[13] https://github.com/LekoArts/figma-theme-ui/blob/main/rollup.config.mjs
[14] https://github.com/the-dataface/figma2html/blob/main/rollup.config.mjs
[15] https://forum.figma.com/ask-the-community-7/linking-css-to-ui-html-31363
[16] https://fabulousdesignspro.hashnode.dev/a-beginners-guide-to-rollup-module-bundler

@eonist
Copy link
Author

eonist commented Jun 7, 2025

Converting Conduit MCP Plugin to TypeScript: A Comprehensive Migration Guide

Based on the analysis of the Conduit project and current best practices for MCP server development with TypeScript, migrating this plugin from its current implementation to a modern TypeScript-based architecture presents both opportunities for improvement and specific challenges that require careful planning. The Conduit project is a sophisticated Model Context Protocol implementation that enables AI agents to communicate directly with Figma, and converting it to TypeScript will provide better type safety, improved developer experience, and enhanced maintainability.

Project Architecture and Setup Strategy

Initial Project Foundation

The recommended approach for starting your TypeScript conversion involves establishing a robust foundation with proper tooling and configuration. Create a new project directory and initialize it with modern Node.js and TypeScript tooling[21]. Begin by setting up your development environment with the essential dependencies including the official MCP TypeScript SDK, which provides comprehensive support for building MCP servers and clients[15].

Your initial project structure should follow established patterns for MCP server development. Create a src directory structure that separates concerns between the MCP server logic, Figma plugin interface, and WebSocket communication layer[2]. The TypeScript configuration should target ES2022 or later to take advantage of modern JavaScript features while maintaining compatibility with Node.js environments[21].

Install the core dependencies including @modelcontextprotocol/sdk for MCP functionality, zod for runtime type validation, and development tools like ts-node and nodemon for efficient development workflows[4][21]. Configure your tsconfig.json with strict type checking enabled and proper module resolution settings to ensure robust type safety throughout the migration process.

Development Environment Configuration

Establish a comprehensive development setup that supports both local development and testing with MCP clients. Configure your TypeScript project to support both CommonJS and ESM modules depending on your target environment[14]. The MCP TypeScript SDK provides excellent support for both stdio and HTTP-based transports, allowing flexibility in how your server communicates with clients[15].

Set up development scripts in your package.json that enable hot reloading during development. Use nodemon with ts-node to automatically restart your server when source files change[21]. This setup is crucial for rapid iteration during the migration process, allowing you to test individual components as you port them from the original implementation.

Migration Strategy and Component Breakdown

Incremental Migration Approach

The most effective strategy for migrating the Conduit plugin involves a systematic, component-by-component approach that maintains functionality throughout the process. Start by examining the existing codebase structure and identifying the core functional areas: MCP server implementation, Figma API integration, WebSocket communication, and plugin management[2].

Begin the migration with the foundational MCP server infrastructure. The original Conduit implementation includes sophisticated features like real-time Figma interaction, component management, and design token support[2]. Create TypeScript interfaces and types that represent the core data structures used throughout the application. This includes defining types for Figma nodes, design properties, color systems, and layout configurations.

Implement the basic MCP server skeleton using the official TypeScript SDK, establishing the core server instance and basic tool registration patterns[15]. This foundation will serve as the target architecture for migrating individual features from the original implementation. The MCP SDK provides excellent TypeScript support with proper type definitions for all protocol messages and server lifecycle events.

Core Component Migration Priority

Prioritize migrating components in order of dependency and complexity. Start with utility functions and data transformation logic, as these typically have fewer external dependencies and can be easily unit tested[12]. Move the basic Figma API interaction functions next, ensuring proper TypeScript typing for all Figma plugin API calls and responses.

The WebSocket communication layer should be migrated as a distinct module with clear interfaces for message handling and connection management[2]. This component is critical to the real-time collaboration features that make Conduit unique among MCP servers. Implement proper error handling and reconnection logic with TypeScript's strong typing to catch potential issues at compile time.

Migrate the advanced features like batch operations, component variants management, and design token systems after establishing the core functionality[2]. These sophisticated features benefit significantly from TypeScript's type system, particularly in ensuring consistency across different Figma element types and property structures.

TypeScript-Specific Enhancements

Type Safety and Interface Design

One of the primary benefits of migrating to TypeScript is the ability to create robust type definitions that prevent runtime errors and improve developer experience. Design comprehensive interfaces for all Figma-related data structures, including nodes, styles, components, and design tokens[2]. Create union types for the various Figma element types and use discriminated unions to ensure type safety when working with different node types.

Implement proper error handling with custom error types that extend the base Error class. This approach provides better debugging information and allows for more sophisticated error recovery strategies[15]. Use TypeScript's strict null checks and optional chaining features to handle the dynamic nature of Figma plugin environments safely.

Define clear interfaces for MCP tool parameters and responses, leveraging the zod library for runtime validation that aligns with TypeScript compile-time types[4]. This dual validation approach ensures that both the TypeScript compiler and runtime environment maintain consistency in data handling.

Modern JavaScript Features Integration

Take advantage of modern JavaScript features that work well with TypeScript's type system. Use async/await patterns throughout the codebase for handling asynchronous operations, which are common in both MCP communication and Figma plugin interactions[15]. Implement proper Promise typing and error handling to maintain type safety across asynchronous boundaries.

Utilize ES6 modules with proper import/export patterns that support tree shaking and efficient bundling[20]. This is particularly important for the plugin component that needs to maintain a reasonable bundle size for Figma's plugin environment. Implement barrel exports through index.ts files judiciously, avoiding patterns that might prevent effective tree shaking[8][20].

Development Workflow and Testing Strategy

Local Development and Testing

Establish a robust local development workflow that supports rapid iteration and testing. Configure the MCP server to work with development tools like the MCP Inspector for testing server functionality[15]. Set up proper debugging configurations in your IDE to step through both server and client code during development.

Create a comprehensive testing strategy that includes unit tests for individual components and integration tests for MCP protocol compliance[12]. The TypeScript ecosystem provides excellent testing tools that work well with the async nature of MCP servers. Use Jest or similar testing frameworks with proper TypeScript configuration to maintain type safety in your test code.

Implement proper logging and monitoring throughout the application to facilitate debugging during the migration process. Use structured logging that provides clear information about MCP message handling, Figma API interactions, and WebSocket communication status[11].

Plugin Development Integration

Configure your development environment to support both the MCP server and Figma plugin development workflows. The Figma plugin component requires compilation to JavaScript and proper manifest configuration[7][16]. Set up webpack or similar bundling tools to handle the plugin's build requirements while maintaining the TypeScript development experience.

Establish clear interfaces between the MCP server and Figma plugin components, ensuring that message passing and state synchronization work reliably. This separation of concerns is crucial for maintaining the real-time collaboration features that distinguish Conduit from simpler MCP implementations[2].

Conclusion

Converting the Conduit MCP plugin to TypeScript represents a significant opportunity to modernize the codebase while maintaining its sophisticated functionality. The migration strategy should prioritize establishing a solid TypeScript foundation with proper tooling and configuration, followed by systematic migration of components in order of dependency complexity. The resulting TypeScript implementation will provide better type safety, improved developer experience, and enhanced maintainability while preserving the innovative real-time Figma collaboration features that make Conduit valuable. Success in this migration depends on careful planning, comprehensive testing, and leveraging TypeScript's strengths in API design and error handling.

[1] https://github.com/eonist/conduit/blob/main/src/conduit_mcp_plugin
[2] https://github.com/eonist/conduit
[3] https://github.com/steipete/conduit-mcp
[4] https://dev.to/shadid12/how-to-build-mcp-servers-with-typescript-sdk-1c28
[5] https://stackoverflow.com/questions/40441252/typescript-typings-give-me-index-d-ts-is-not-a-module
[6] https://www.youtube.com/watch?v=odAIrlamMXc
[7] https://help.figma.com/hc/en-us/articles/4407531166743-BYFP-Plugin-Environment-Setup
[8] https://www.reddit.com/r/Angular2/comments/1amnupf/nx_monorepo_libs_and_indexts/
[9] https://stackoverflow.com/questions/56379875/how-to-write-a-plugin-loader-for-a-module-written-in-typescript
[10] https://learn.microsoft.com/en-us/semantic-kernel/concepts/plugins/adding-mcp-plugins
[11] https://learn.microsoft.com/en-us/microsoftteams/platform/teams-ai-library/typescript/in-depth-guides/ai/mcp/mcp-server
[12] https://dev.to/alexmercedcoder/building-a-basic-mcp-server-with-python-5ci7
[13] https://www.youtube.com/watch?v=L6yKk7EQYZc
[14] TypeStrong/ts-node#2100
[15] https://github.com/modelcontextprotocol/typescript-sdk
[16] https://github.com/aarongarciah/figma-plugin-typescript-boilerplate
[17] https://www.serverless.com/plugins/serverless-plugin-typescript
[18] https://www.a2e.ai/supercharge-your-vibe-coding-with-a2e-mcp-server/
[19] https://blog.platformatic.dev/accelerating-nodejs-development-with-mcp-node
[20] https://www.linkedin.com/pulse/best-practices-using-indexts-files-avoiding-tree-shaking-amin-atwi-bexmf
[21] https://www.infyways.com/build-your-first-mcp-server-with-typescript/
[22] https://mcp.pizza/mcp-server/jYB2/conduit
[23] https://conduit.io/docs/cli
[24] https://devblogs.microsoft.com/microsoft365dev/announcing-the-updated-teams-ai-library-and-mcp-support/
[25] TypeStrong/ts-node#935
[26] https://learn.microsoft.com/en-us/microsoftteams/platform/teams-ai-library/typescript/in-depth-guides/ai/mcp/mcp-client
[27] https://github.com/eonist/conduit/issues
[28] https://www.reddit.com/r/neovim/comments/189rqq7/home_made_plugin_better_formatted_typescript/
[29] https://nextjs.org/docs/app/api-reference/config/typescript
[30] https://docs.theconduit.dev/db/db_tools/
[31] https://www.typescriptlang.org/docs/handbook/declaration-files/templates/global-plugin-d-ts.html
[32] https://docs.pipecat.ai/server/base-classes/mcp/mcp
[33] https://code.visualstudio.com/api/references/vscode-api
[34] https://github.com/Heavybullets8/TT-Migration
[35] https://www.youtube.com/watch?v=AthL1lVrSv0
[36] https://dev.to/jneums/why-we-ditched-python-for-typescript-and-survived-oauth-in-our-ai-agent-mcp-server-45al

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment