Skip to content

Начало работы

Эта страница проведёт вас от нуля до собственного дополнения, загруженного и отображающегося в разделе Панель → Дополнения, с быстрым циклом «правка-обновление», которым вы будете пользоваться на протяжении всех остальных руководств. Предыдущий опыт работы с Pano не нужен — достаточно немного знать Kotlin и JavaScript.

Дополнение Pano добавляет возможности на сайт Pano: новые страницы в панели (админ-панель по адресу /panel), новые разделы в теме (публичный сайт, который видят ваши посетители) и новые API на бэкенде (сам сервер Pano) — всё в одном устанавливаемом файле. Вы собираете его из готового шаблона и помещаете в работающий экземпляр Pano.

Дополнение и плагин — это одно и то же

Дополнения — это плагины Pano: API уровня кода, названия папок и классы используют слово plugin (например, PanoPlugin, pluginId). На этой странице (и в остальной документации) в тексте говорится дополнение, но в коде вы постоянно будете видеть plugin. Так и должно быть, ничего не переименовано.

Дополнение — это единственный JAR-файл (JAR — это zip-архив скомпилированного кода Kotlin/Java плюс ресурсы), содержащий две половины, работающие вместе:

  • бэкенд на Kotlin, который выполняется внутри сервера Pano. Pano загружает его через библиотеку PF4J — PF4J это просто «сантехника», которую Pano использует для загрузки jar-файлов дополнений, и вы напрямую с ней не взаимодействуете. Бэкенд может добавлять таблицы базы данных, JSON API, разрешения и многое другое — каждый из этих элементов вы будете собирать шаг за шагом в разделе Разработка бэкенда.
  • UI на Svelte, который выполняется в браузере. Вот что поначалу удивляет: ваш единственный UI внедряется в тот сайт, на котором находится посетитель, — админ-панель или публичную тему («тема» — это тот фронтенд-дизайн, который активировал владелец сайта).

Использовать обе половины не обязательно — дополнение только с UI или только с бэкендом вполне допустимо, — но шаблон поставляется с уже связанными обеими половинами. Сначала пройдите эту страницу; затем Архитектура объяснит внутреннее устройство, показав, где именно выполняется каждая часть. Если вы просто хотите устанавливать дополнения, а не создавать их, смотрите пользовательскую страницу Дополнения.

Наш сквозной пример во всех этих руководствах — небольшое дополнение под названием Shoutbox: посетители видят последние «выкрики» на главной странице, а админы управляют ими из панели, — поэтому мы с самого начала назовём наш проект pano-plugin-shoutbox.

Прежде чем начать: запустите Pano локально

Всё на этой странице предполагает, что у вас уже запущен Pano на той же машине, где вы будете писать код. Ваше дополнение живёт внутри этой установки Pano, пока вы работаете, — вы помещаете его в папку plugins/ установки, — поэтому для разработки дополнений запускайте Pano локально на вашей машине разработки, а не на удалённом сервере или VPS.

Если локального Pano у вас пока нет, сначала пройдите руководство Установка, затем возвращайтесь.

Контрольная точка

Вы можете открыть ваш сайт Pano в браузере (адрес, который вы выбрали при настройке, например http://localhost:<port>) и войти в /panel.

Включите режим разработки

Режим разработки заставляет ваши файлы UI и локализации загружаться вживую с диска, а не браться из кэша — именно это позже даёт быстрый цикл обновления. Включите его в панели:

Панель → Настройки платформы → Режим разработки → Вкл, затем сохраните.

После сохранения настройка отображается как Вкл. Это всё, что нужно сделать.

TIP

Под капотом это ключ конфигурации development-mode, но вам никогда не придётся трогать файл конфигурации вручную — переключатель в панели делает всю работу.

Что вам понадобится

Четыре вещи на вашей машине разработки. Проверьте каждую показанной командой — если команда «не найдена», сначала установите этот инструмент.

  1. JDK версии 11 или новее. Установите любую Java 11+ (именно JDK, а не только JRE). Сборка автоматически скачивает и использует нужную ей внутреннюю версию Java (Java 11) — вы этим никогда не управляете сами, так что подойдёт любой JDK, способный запустить Gradle.
    • Проверка: выполните java -version. Любой номер версии 11 или выше означает, что всё в порядке. «Command not found» означает, что нужно установить JDK.
  2. Bun — инструмент, который устанавливает и собирает UI. Установите его с bun.sh. Он нужен для наблюдателя разработки (bun run dev). (Релизные сборки скачивают собственную копию Bun; пока не обращайте на это внимания.)
    • Проверка: выполните bun --version.
  3. Git — используется для скачивания шаблона на следующем шаге.
    • Проверка: выполните git --version.
  4. Редактор кода. Подойдёт любой редактор, но для Kotlin полноценная IDE избавит от многих мучений — IntelliJ IDEA Community Edition бесплатна, и шаблон уже содержит файлы проекта IntelliJ.

Пользователям Windows

Эта документация предполагает Unix-подобную оболочку (macOS, Linux, WSL или Git Bash). В cmd или PowerShell выполняйте gradlew.bat (или .\gradlew) везде, где встречается ./gradlew.

Создайте дополнение из шаблона

Pano поставляет готовый шаблон pano-boilerplate-plugin с уже связанными бэкендом и UI. Вы клонируете его, затем переименовываете всё под своё дополнение.

Клонируйте его в папку plugins/ вашей установки Pano — это та папка, где вы завершили настройку, содержащая jar Pano, его конфигурацию и подпапку plugins/. Это важно: дополнение горячо перезагружает свой UI только тогда, когда живёт внутри папки plugins/ работающей установки.

Последний аргумент в строке git clone ниже (pano-plugin-shoutbox) — это имя папки, которую git создаёт для вашего клона, — и оно должно точно совпадать с pluginId, который вы зададите в следующем разделе, потому что Pano связывает папку с id.

bash
cd <your-pano-instance>/plugins
git clone https://github.com/PanoMC/pano-boilerplate-plugin.git pano-plugin-shoutbox
cd pano-plugin-shoutbox

Переименуйте шаблон под своё дополнение

Шаблон называет себя pano-boilerplate-plugin в нескольких местах. Каждое из них вы измените на имя своего дополнения. Большинство из них находятся в gradle.properties — считайте этот файл манифестом вашего дополнения: файлом метаданных (id, имя, версия, главный класс и так далее).

Необязательно: проверьте окружение перед переименованием

Если хотите убедиться, что ваша настройка Java и Bun работает, до того как что-либо трогать, соберите нетронутый шаблон один раз сейчас — из папки дополнения выполните bun install, затем ./gradlew build. BUILD SUCCESSFUL здесь означает, что любой сбой после переименования — это ошибка переименования, а не сломанное окружение. (Эта первая сборка скачивает много всего и может занять несколько минут — это нормально, не отменяйте её.)

Сделайте эти правки по порядку. Шаги 1–3 описывают один и тот же класс в трёх местах, поэтому они должны согласовываться друг с другом:

  1. gradle.properties — задайте эти ключи:

    • pluginIdpano-plugin-shoutbox
    • pluginNameShoutbox
    • pluginClasscom.panomc.plugins.shoutbox.ShoutboxPlugin
    • pluginDescription, pluginDeveloper, pluginLicense, pluginSourceUrl, organization → ваши собственные значения

    pluginClass — это полностью квалифицированное имя класса: имя пакета плюс имя класса. Пакет повторяет путь папки под src/main/kotlin, где слэши заменены точками. Так что это значение, папка на шаге 2 и имя класса на шаге 3 должны обозначать одно и то же.

  2. Переименуйте папку пакета Kotlin. Переименуйте папку src/main/kotlin/com/panomc/plugins/boilerplatesrc/main/kotlin/com/panomc/plugins/shoutbox. Затем откройте единственный .kt-файл в этой папке, BoilerplatePlugin.kt, и измените его первую строку — строку package — чтобы она соответствовала: package com.panomc.plugins.shoutbox.

  3. Переименуйте главный класс Kotlin. В том же файле переименуйте класс BoilerplatePluginShoutboxPlugin. Он должен совпадать с именем класса в конце pluginClass из шага 1. (В IntelliJ правый клик по имени класса → Refactor → Rename делает это и обновляет имя файла и все ссылки за вас.)

  4. src/main.js — измените две вещи:

    • константу pluginId 'pano-boilerplate-plugin''pano-plugin-shoutbox'
    • имя класса в строке export default class PanoExamplePlugin … → своё собственное имя (например, ShoutboxUiPlugin)
  5. package.json — задайте "name"pano-plugin-shoutbox.

  6. settings.gradle.kts — шаблон здесь не задаёт имя проекта, поэтому добавьте эту строку:

    rootProject.name = "pano-plugin-shoutbox"

    Без неё Gradle назовёт проект по имени папки. Задайте имя явно, чтобы собранный jar всегда нёс правильное имя и совпадал с идентичностью вашего дополнения, даже если папку когда-нибудь назовут иначе.

Это всё, что требуется. Ещё две вещи — это содержимое, а не связка; измените их сейчас или в любой момент позже:

  • src/main/resources/locales/en-US.json — текстовые строки вашего UI. Шаблон поставляется с одним ключом hello-world.
  • src/main/resources/logo.png — замените на свой логотип.

Выберите pluginId один раз и никогда не меняйте

pluginId, который вы задаёте в gradle.properties, — не просто ярлык: Pano вписывает его во множество мест за кулисами, поэтому выберите его один раз и оставьте неизменным. Страница Конфигурация манифеста перечисляет точно, где он используется.

Теперь соберите и загрузите его (следующий раздел) — успешная сборка подтвердит, что ваши шесть переименований согласованы.

Соберите и загрузите дополнение

Из папки дополнения (plugins/pano-plugin-shoutbox/) установите зависимости UI и соберите один раз:

bash
# in plugins/pano-plugin-shoutbox/ (your addon folder)
bun install
./gradlew build

Первая сборка скачивает сам Gradle, внутренний набор инструментов Java и все зависимости — она может несколько минут выглядеть зависшей. Это нормально, не отменяйте её. Она заканчивается словами BUILD SUCCESSFUL и создаёт jar в папке build/libs/ (с именем pano-plugin-shoutbox-local-build.jar).

Контрольная точка

BUILD SUCCESSFUL означает, что ваши переименования согласованы. Если сборка завершается ошибкой, две правки противоречат друг другу — самые частые причины:

  • ClassNotFoundException / «plugin class not found»pluginClass (шаг 1) не совпадает с вашим пакетом + именем класса (шаги 2–3). Все три должны обозначать один и тот же com.panomc.plugins.shoutbox.ShoutboxPlugin.
  • Ошибка компиляции unresolved-reference / package → строка package внутри .kt-файла (шаг 2) не совпадает с папкой, которую вы переименовали.

Pano обнаруживает jar-файлы только непосредственно в папке plugins/ установки — он не сканирует вложенную папку build/libs/ внутри вашего клона, — поэтому из папки дополнения скопируйте свежесобранный jar на уровень выше:

bash
cp build/libs/pano-plugin-shoutbox-local-build.jar ..   # into the instance's plugins/ folder

Теперь перезапустите Pano: остановите работающий процесс (нажмите Ctrl+C в терминале, где запущен Pano) и запустите его снова точно так же, как при установке. Затем откройте Панель → Дополнения — ваше дополнение должно быть в списке. Это проверка «загрузилось ли оно?». (Новые jar-файлы подхватываются только при запуске; действия панели над дополнением — это включить / отключить / удалить / загрузить, а не пересканировать.) Если оно появилось, значит бэкенд-половина загрузилась правильно, и вы готовы к итерациям.

Дополнение не в списке?

Если оно не появилось: находится ли jar непосредственно в plugins/ (а не всё ещё в build/libs/)? Проверьте лог сервера на ошибку загрузки плагина и перепроверьте, что pluginClass совпадает с вашим пакетом + именем класса.

Клон и загружаемый jar — две разные вещи

Теперь две копии вашего дополнения живут бок о бок в plugins/:

plugins/
├── pano-plugin-shoutbox/                       ← your clone (source)
│   └── src/…, locales/…, plugin-ui/…
└── pano-plugin-shoutbox-local-build.jar        ← the built jar Pano loads
  • jar — это бэкенд-код, который Pano реально выполняет.
  • папка (её имя совпадает с вашим pluginId) — это то, что Pano читает для живых файлов UI и локализации, пока включён режим разработки.

Обе спокойно сосуществуют — jar выполняет ваш бэкенд, папка питает живые перезагрузки UI и локализации.

Цикл разработки

Это самая важная часть страницы. Во время разработки вы почти никогда не хотите запускать полный ./gradlew build — он каждый раз пересобирает UI, что медленно. Вместо этого используйте две команды, по одной на каждую половину дополнения. Запускайте обе из папки дополнения, plugins/pano-plugin-shoutbox/.

Для работы над бэкендом (Kotlin) соберите быстрый JAR только с бэкендом, пропускающий UI. (-P передаёт флаг в сборку Gradle; здесь noui означает «пропустить сборку UI».)

bash
./gradlew build -Pnoui   # fast backend-only jar, skips the UI build

Для работы над UI (Svelte) запустите наблюдатель и оставьте его работать. Он следит за вашими исходными файлами UI и каждый раз при сохранении пересобирает результат в src/main/resources/plugin-ui/. (Заметка про rollup watch в комментарии просто называет инструмент, который делает работу, — вы не запускаете его напрямую.)

bash
bun run dev              # rollup watch → src/main/resources/plugin-ui/{client,server}

Пока включён режим разработки и дополнение живёт в папке plugins/ установки, обновление любой страницы вашего сайта Pano — по тому же адресу, что вы использовали при настройке, например http://localhost:<port> — мгновенно подхватывает новую сборку UI без пересборки JAR.

Однако не всякое изменение так быстро. Вот что именно требует каждый вид изменения:

Что вы изменилиЧтобы увидеть это
Svelte UI (src/main.js, src/panel/**, src/theme/**)запущенный bun run dev + обновление в браузере (F5)
locales/*.jsonпри включённом режиме разработки — обновление в браузере (F5); локализации читаются вживую из вашего дерева исходников
Код на Kotlin./gradlew build -Pnoui, копирование нового jar в plugins/, затем перезапуск Pano
gradle.properties, исходный config.confполный ./gradlew build, копирование jar в plugins/, затем перезапуск Pano

(config.conf — это шаблон конфигурации дополнения по умолчанию в src/main/resources/config.conf — вы встретите его в разделе Разработка бэкенда.)

Изменения Kotlin требуют пересборки и перезапуска

Код Kotlin не горячий. После правки .kt-файла: пересоберите (./gradlew build -Pnoui достаточно для кода только бэкенда), скопируйте новый jar в папку plugins/ вашей установки и перезапустите Pano. Отключение и повторное включение дополнения в панели не подхватывает ваш новый код — сервер держит старый код в памяти, пока полный перезапуск не загрузит новый jar. Изменения в gradle.properties или исходном config.conf требуют полного ./gradlew build таким же образом.

Ваше первое изменение за 2 минуты

Давайте сделаем по одному изменению каждого вида, чтобы разделение «горячее против пересборки» действительно улеглось в голове.

Изменение UI (горячее — достаточно F5). Откройте src/main.js. Внутри onLoad() вы добавите одну строку console.log. Строка const pano = this.pano; и окружающий код уже есть в файле — не перепечатывайте их, а // ... ниже просто заменяет уже существующий там код. Добавьте только строку с логом:

js
onLoad() {
  const pano = this.pano;
  console.log('Shoutbox UI loaded! isPanel =', pano.isPanel);
  // ...
}

Убедитесь, что bun run dev запущен, сохраните файл, затем обновите ваш сайт Pano (http://localhost:<port>) и откройте консоль браузера (F12 → Console). Ваше сообщение там — пересборка не нужна.

Нет сообщения?

Проверьте, что bun run dev всё ещё запущен в терминале, что режим разработки Вкл в панели и что ваш клон находится под папкой plugins/ установки. Это три обычные причины.

Изменение локализации (тоже горячее в режиме разработки). Откройте src/main/resources/locales/en-US.json и измените единственную строку шаблона:

json
{
  "hello-world": "Hello from Shoutbox!"
}

Сохраните и нажмите F5. Поскольку режим разработки включён и ваш клон живёт в plugins/<pluginId>/, Pano читает файлы локализации вживую из вашего дерева исходников — так что пересборка не нужна.

Одна честная оговорка: стандартный шаблон определяет строку hello-world, но пока не отображает её ни на одной странице (папки panel и theme поставляются пустыми — вы подключите строки локализации в свой UI в разделе Разработка фронтенда). Так что на экране пока нечего наблюдать. Вывод, который стоит запомнить, — это правило: как только ваш UI действительно покажет строку локализации, редактирования JSON и нажатия F5 достаточно, — и проверка с console.log выше уже доказала, что эта живая перезагрузка работает.

Изменение Kotlin (требует пересборки + перезапуска). Вот это изменение, которое не горячее. Откройте файл с вашим классом ShoutboxPlugin и измените сообщение в строке logger.info("Starting..."), которая уже находится внутри onStart() — например:

kotlin
logger.info("Shoutbox is starting up!")

Затем из папки дополнения пересоберите и скопируйте jar на уровень выше:

bash
# in plugins/pano-plugin-shoutbox/ (your addon folder)
./gradlew build -Pnoui
cp build/libs/pano-plugin-shoutbox-local-build.jar ..

Теперь перезапустите Pano (Ctrl+C для работающего процесса, затем запустите снова). Пока Pano загружается, следите за терминалом, где он запущен, — ваше новое сообщение появится в консоли сервера. Отключение → включение в панели продолжало бы выполнять старый код, и именно поэтому нужен перезапуск.

Вот и весь цикл в двух словах: UI и локализации горячие в режиме разработки; изменения Kotlin и манифеста (gradle.properties) требуют пересборки и перезапуска Pano. Держите это разделение в голове, и остальные руководства будут ощущаться быстрыми.

Когда что-то не работает

Большинство проблем у новичков сводятся к пяти вещам. Проверяйте их по порядку:

  1. Дополнения нет в списке Панель → Дополнения. Находится ли собранный jar непосредственно в папке plugins/ установки (а не всё ещё в build/libs/)? Новые jar-файлы загружаются только при запуске — вы перезапустили Pano? Проверьте лог сервера на ошибку загрузки плагина и перепроверьте, что pluginClass совпадает с вашим пакетом + именем класса.
  2. Правка UI или локализации не отображается. Запущен ли ещё bun run dev? Включён ли режим разработки в панели? Находится ли ваш клон под папкой plugins/ установки (в plugins/<pluginId>/)?
  3. Правка Kotlin не вступает в силу. Kotlin не горячий — нужно пересобрать (./gradlew build -Pnoui), скопировать jar в plugins/ и перезапустить Pano. Отключения/включения в панели недостаточно.
  4. Сборка падает сразу после переименования. Две ваши правки переименования противоречат друг другу — смотрите причины сбоя в контрольной точке Соберите и загрузите. Перепроверьте, что pluginClass, папка пакета и имя класса обозначают одно и то же.
  5. Ваш dev-сервер зависает (актуально, только если вы также запускаете dev-сервер темы или панели). Не добавляйте правило прокси для /plugins в конфигурацию Vite этого dev-сервера. UI-сервер уже обслуживает этот путь; проксирование обратно создаёт цикл запросов, который вешает dev-сервер.

Куда дальше

Теперь у вас загружено собственное дополнение, и вы знаете, какие изменения горячие, а какие нет. Вот рекомендованный путь:

  • Архитектура — модель мышления: что происходит, когда Pano загружает ваш JAR, и где каждый файл оказывается во время выполнения. Прочтите это перед написанием реального кода.
  • Разработка бэкенда — соберите бэкенд Shoutbox: таблицу базы данных, JSON API, разрешение и журнал активности.
  • Разработка фронтенда — соберите UI Shoutbox: разместите виджет на главной странице, добавьте раздел настроек в панели и полноценную страницу панели.
  • Сборка и публикация — превратите дополнение в релиз и отправьте его в маркетплейс.