Skip to content

Разработка тем ​

Темы mineproj — это npm-пакеты, которые управляют внешним видом вашего сайта.

Контракт темы ​

Тема — это объект со следующими свойствами:

СвойствоТипОбязательноОписание
namestring✅Уникальное имя темы
layoutsRecord<string, Component>✅Макеты для каждого типа маршрута
componentsRecord<string, Component>НеобязательноПереиспользуемые компоненты
slotsstring[]НеобязательноИменованные точки вставки
configSchemaZodSchemaНеобязательноСхема для themeConfig
localesRecord<string, Record<string, string>>НеобязательноСловари перевода интерфейса
stylesstring[]НеобязательноCSS-строки, встраиваемые в <head> каждой страницы
headScriptsstring[]НеобязательноВстроенные скрипты, внедряемые в <head> страницы
islandsRecord<string, Component>НеобязательноИнтерактивные компоненты, гидратируемые на клиенте
extendsTheme | stringНеобязательноРодительская тема для наследования

Пример ​

ts
import { defineTheme } from '@mineproj/core';

const theme = defineTheme({
  name: 'my-theme',
  layouts: {
    home: ({ data, config }) => (
      <main>
        <h1>{config.title}</h1>
        <ul>
          {data.projects.map(p => <li key={p.slug}>{p.name}</li>)}
        </ul>
      </main>
    ),
  },
  styles: [`:root { --mp-color-accent: #ff5500; }`],
});

export default theme;

Использование локальной темы ​

Создайте .mineproj/theme/index.mts:

ts
import { defineTheme } from '@mineproj/core';
export default defineTheme({ ... });

Затем установите theme: '.mineproj/theme' в вашей конфигурации.

Макеты ​

Семь обязательных типов макетов:

МакетМаршрутНазначение
home/Главная страница с героем, избранными проектами, сеткой
list/projects/Фильтруемая сетка проектов
detail/projects/<slug>/Детальная страница проекта с боковой панелью
tag/tags/<name>/Проекты, отфильтрованные по тегу
collection/collections/<slug>/Курируемая коллекция
about/about/Профиль автора
notFound404.htmlПользовательская страница 404

Острова ​

Интерактивные компоненты помечаются как острова:

tsx
export function MyCounter({ start }: { start: number }) {
  const [count, setCount] = useState(start);
  return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}

Регистрация в теме:

ts
const theme = defineTheme({
  name: 'my-theme',
  layouts: { ... },
  islands: { 'my-counter': MyCounter },
  islandsImport: 'my-theme/islands',
});

Контрактное тестирование ​

ts
import { runThemeContract } from '@mineproj/test-utils';
const result = runThemeContract(myTheme, { requireAllLayouts: true });
console.log(result.errors); // [] если валидно

Публикация ​

  1. Назовите ваш пакет mineproj-theme-* или @scope/mineproj-theme-*
  2. Добавьте "keywords": ["mineproj-theme"] в package.json
  3. Запустите runThemeContract для проверки
  4. Опубликуйте в npm

Released under the Apache-2.0 License.