Skip to the content.

Your First NUXP Plugin

Captain NUXP

This tutorial walks you through creating a simple Illustrator tool using NUXP. By the end, you’ll have a working button that creates a rectangle in your Illustrator document.

Prerequisites

Step 1: Start in Mock Mode

First, let’s develop the UI without needing Illustrator. This is faster and lets you iterate on the frontend independently.

cd shell
VITE_USE_MOCK=true npm run dev

Open http://localhost:5173 in your browser.

Step 2: Create a Simple Component

Create a new file shell/src/components/CreateRectangle.vue:

<template>
  <div class="create-rectangle">
    <h3>Create Rectangle</h3>

    <div class="inputs">
      <label>
        Width:
        <input v-model.number="width" type="number" min="1" />
      </label>
      <label>
        Height:
        <input v-model.number="height" type="number" min="1" />
      </label>
    </div>

    <button @click="createRectangle" :disabled="loading">
      {{ loading ? 'Creating...' : 'Create Rectangle' }}
    </button>

    <p v-if="message" :class="{ error: isError }">{{ message }}</p>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { callCpp } from '@/sdk/bridge'

const width = ref(100)
const height = ref(100)
const loading = ref(false)
const message = ref('')
const isError = ref(false)

async function createRectangle() {
  loading.value = true
  message.value = ''
  isError.value = false

  try {
    const result = await callCpp('demo', 'createRectangle', {
      x: 100,
      y: 100,
      width: width.value,
      height: height.value
    })

    if (result.success) {
      message.value = 'Rectangle created!'
    } else {
      message.value = result.error || 'Failed to create rectangle'
      isError.value = true
    }
  } catch (err) {
    message.value = err instanceof Error ? err.message : 'Unknown error'
    isError.value = true
  } finally {
    loading.value = false
  }
}
</script>

<style scoped>
.create-rectangle {
  padding: 1rem;
  border: 1px solid #ccc;
  border-radius: 8px;
  max-width: 300px;
}

.inputs {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin: 1rem 0;
}

.inputs label {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.inputs input {
  width: 100px;
  padding: 0.25rem;
}

button {
  width: 100%;
  padding: 0.5rem;
  background: #0066cc;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

button:disabled {
  background: #ccc;
  cursor: not-allowed;
}

button:hover:not(:disabled) {
  background: #0052a3;
}

.error {
  color: red;
}
</style>

Step 3: Add to a View

Import and use your component in shell/src/views/HomeView.vue or create a new view.

Step 4: Test with Mock Mode

In mock mode, the callCpp function routes to MockBridge.ts which returns simulated responses. This lets you develop the UI flow without the real plugin.

Step 5: Connect to Real Illustrator

  1. Build and install the plugin (see README)
  2. Launch Illustrator
  3. Stop the dev server and restart without mock mode:
npm run dev
  1. Click your button - a rectangle should appear in Illustrator!

Understanding the Call Flow

Your Component
    ↓ callCpp('demo', 'createRectangle', {...})
SDK Bridge (bridge.ts)
    ↓ HTTP POST to localhost:8080
C++ HTTP Server
    ↓ Routes to DemoEndpoints::CreateRectangle
Adobe SDK
    ↓ Creates actual rectangle
Illustrator Document

What You Can Do From Here

NUXP ships with 442+ TypeScript functions covering 19 SDK suites. You can build most Illustrator tools entirely in TypeScript without touching any C++.

Browse what’s available:

Advanced: Adding Custom C++ Endpoints

If you need SDK functionality not already covered by the 442+ generated functions, you can write custom C++ endpoints. See Adding Custom Endpoints for a step-by-step guide. Most users won’t need this.

Troubleshooting

“Connection refused” errors:

“No document open” errors:

Changes not appearing: