Skip to content

Latest commit

 

History

History
475 lines (349 loc) · 8.91 KB

File metadata and controls

475 lines (349 loc) · 8.91 KB

Technology Stack Reference

Complete list of available dependencies and their usage patterns for SillyTavern development.

Package Manager

pnpm only - Do not use npm or yarn.

pnpm install
pnpm add lodash
pnpm add -D @types/lodash

UI Frameworks

Vue 3 Ecosystem (Recommended)

Core:

  • vue@3.5.24 - Progressive JavaScript framework
  • vue-router@4.6.3 - Official router (use createMemoryHistory() for iframe)
  • pinia@3.0.4 - State management

Vue Composition Utilities:

  • @vueuse/core@13.9.0 - Collection of composition APIs
  • @vueuse/components@14.0.0 - Renderless components
  • @vueuse/integrations@13.9.0 - Third-party library integrations
  • @vueuse/shared@13.9.0 - Shared utilities

Additional Vue Libraries:

  • vue-final-modal@4.5.5 - Modal/dialog management
  • vue3-pixi@1.0.0-beta.3 - PixiJS integration for Vue

Usage:

import { createApp } from 'vue';
import { createPinia } from 'pinia';
import { createRouter, createMemoryHistory } from 'vue-router';
import { useMouse, useLocalStorage } from '@vueuse/core';

// Router MUST use createMemoryHistory for iframe
const router = createRouter({
  history: createMemoryHistory(),
  routes: [/* ... */],
});

$(() => {
  const app = createApp(App);
  app.use(createPinia());
  app.use(router);
  app.mount('#app');
});

React Ecosystem

Core:

  • react@19.2.0 - UI library
  • react-dom@19.2.0 - DOM rendering

Usage:

import React from 'react';
import ReactDOM from 'react-dom/client';

$(() => {
  const root = ReactDOM.createRoot(document.getElementById('app')!);
  root.render(<App />);
});

PixiJS (Game/Multimedia)

Core:

  • pixi.js@8.14.1 - 2D WebGL renderer
  • @pixi/react@8.0.0-beta.25 - React renderer for PixiJS

Use when: Heavy multimedia assets, game-like interfaces, animation-intensive UIs

Usage:

import { Application, Assets } from 'pixi.js';
import { Stage, Sprite } from '@pixi/react';

// Preload assets
Assets.addBundle('game', {
  bgm: '/audio/bgm.mp3',
  sprite: '/img/sprite.png',
});

await Assets.loadBundle('game');

DOM Manipulation

jQuery

Core:

  • jquery@3.7.1 - DOM manipulation
  • jqueryui@1.11.1 - UI interactions (draggable, resizable, etc.)

Script vs Frontend Interface:

// In scripts: $ operates on SillyTavern page
window.$ = window.parent.$;
$('body'); // SillyTavern <body>

// In frontend interfaces: $ operates on iframe
$('body'); // Iframe <body>

Common usage:

// Event binding
$('#button').on('click', handler);

// DOM manipulation
$('<div>').addClass('my-class').appendTo('body');

// AJAX
$.ajax({
  url: '/api/data',
  method: 'POST',
  data: { key: 'value' },
  success: (data) => console.log(data),
});

// Draggable (jQueryUI)
$('#element').draggable({
  containment: 'parent',
  handle: '.drag-handle',
});

Data Utilities

Lodash

Package: lodash@4.17.21

Common functions:

import _ from 'lodash';

// Deep clone
const copy = _.cloneDeep(obj);

// Get nested value safely
const value = _.get(obj, 'path.to.value', defaultValue);

// Set nested value
_.set(obj, 'path.to.value', newValue);

// Debounce
const debouncedFn = _.debounce(fn, 300);

// Throttle
const throttledFn = _.throttle(fn, 1000);

// Array operations
_.uniq([1, 2, 2, 3]); // [1, 2, 3]
_.chunk([1, 2, 3, 4], 2); // [[1, 2], [3, 4]]

Zod (Validation)

Package: zod@4.1.12

Usage:

import { z } from 'zod';

// Define schema with defaults
const Settings = z.object({
  volume: z.number().min(0).max(1).default(0.5),
  autoPlay: z.boolean().default(true),
  theme: z.enum(['light', 'dark']).default('dark'),
  tags: z.array(z.string()).default([]),
}).prefault({}); // Auto-fill missing fields with defaults

type Settings = z.infer<typeof Settings>;

// Parse (throws on error)
const settings = Settings.parse(data);

// Safe parse
const result = Settings.safeParse(data);
if (!result.success) {
  console.error(z.prettifyError(result.error));
  return;
}

// Use parsed data
const { volume, autoPlay } = result.data;

Klona (Deep Clone)

Package: klona@2.0.6

Purpose: Remove Vue Proxy layer before saving to Tavern variables

Usage:

import { klona } from 'klona';
import { watchEffect, ref } from 'vue';

const settings = ref({ score: 0 });

// Auto-save without Proxy
watchEffect(() => {
  replaceVariables(klona(settings.value), { type: 'chat' });
});

Animation

GSAP

Package: gsap@3.13.0

Use for: All animations, including typewriter effects

Common patterns:

import gsap from 'gsap';

// Typewriter effect
gsap.to('#text', {
  duration: 2,
  text: {
    value: "New text appears character by character",
    delimiter: ""
  },
  ease: "none"
});

// Fade in/out
gsap.to('#element', {
  duration: 0.5,
  opacity: 0,
  onComplete: () => $('#element').remove()
});

// Timeline
const tl = gsap.timeline();
tl.to('#a', { x: 100, duration: 1 })
  .to('#b', { y: 50, duration: 0.5 })
  .to('#c', { rotation: 360, duration: 1 });

// Scroll trigger (requires gsap/ScrollTrigger)
import { ScrollTrigger } from 'gsap/ScrollTrigger';
gsap.registerPlugin(ScrollTrigger);

gsap.to('#element', {
  scrollTrigger: {
    trigger: '#element',
    start: 'top center',
    end: 'bottom center',
    scrub: true
  },
  x: 500
});

Notifications

Toastr

Package: toastr@2.1.4

Usage:

import toastr from 'toastr';

// Success
toastr.success('Operation completed');

// Info
toastr.info('Loading...');

// Warning
toastr.warning('Are you sure?');

// Error
toastr.error('Something went wrong');

// Options
toastr.options = {
  closeButton: true,
  progressBar: true,
  positionClass: 'toast-top-right',
  timeOut: 3000,
};

Data Formats

YAML

Package: yaml@2.8.1

Usage:

import YAML from 'yaml';

// Parse
const data = YAML.parse(yamlString);

// Stringify
const yamlString = YAML.stringify(data);

Dedent

Package: dedent@1.7.0

Purpose: Clean indentation in multi-line strings

Usage:

import dedent from 'dedent';

const prompt = dedent`
  You are a helpful assistant.
  Please respond in a friendly manner.
  Keep answers concise.
`;
// Removes leading whitespace while preserving relative indentation

Styling

Tailwind CSS

Package: tailwindcss@4.1.17

Setup:

// Create tailwind.css
// Content: @import 'tailwindcss';

import './tailwind.css';

Usage in HTML:

<div class="flex items-center justify-center p-4 bg-gray-100 rounded-lg">
  <button class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">
    Click me
  </button>
</div>

Sass/SCSS

Package: sass@1.94.0

Usage:

// In TypeScript
import './styles.scss';

// In Vue component
<style lang="scss" scoped>
.my-component {
  $primary-color: #3498db;

  background: $primary-color;

  &:hover {
    background: darken($primary-color, 10%);
  }
}
</style>

Special Import Methods

Raw File Import

// Import file content as string
import htmlContent from './file.html?raw';
import jsonContent from './data.json?raw';

// Import compiled files
import jsContent from './script.ts?raw';    // Gets compiled JS
import cssContent from './style.scss?raw';  // Gets compiled CSS

HTML Import (Minified)

// Uses html-loader for minification
import html from './template.html';

Markdown Import (to HTML)

// Uses remark-loader for parsing
import markdown from './content.md';

Vue Component Import

import Component from './Component.vue';

Build Tools

TypeScript

Package: typescript@6.0.0-dev.20250807

Config: tsconfig.json

Webpack

Core: webpack@5.102.1 + webpack-cli@6.0.1

Loaders:

  • ts-loader@9.5.4 - TypeScript
  • vue-loader@17.4.2 - Vue SFC
  • sass-loader@16.0.6 - Sass/SCSS
  • css-loader@7.1.2 - CSS
  • style-loader@4.0.0 - CSS injection
  • html-loader@5.1.0 - HTML
  • remark-loader@6.0.0 - Markdown

Build commands:

pnpm run build:dev    # Development build
pnpm run build        # Production build
pnpm run watch        # Watch mode

Code Quality

ESLint

Package: eslint@9.39.1

Plugins:

  • @typescript-eslint/parser@8.46.4
  • eslint-plugin-vue@10.5.1
  • eslint-plugin-pinia@0.4.1
  • eslint-plugin-better-tailwindcss@3.7.10

Commands:

pnpm run lint
pnpm run lint:fix

Prettier

Package: prettier@3.6.2

Command:

pnpm run format

Version Compatibility

All packages are tested together in this environment. Do not arbitrarily upgrade versions as it may cause compatibility issues.

Critical constraints:

  • ⚠️ Browser-only environment (no Node.js APIs)
  • ⚠️ Vue Router must use createMemoryHistory() for iframe
  • ⚠️ Scripts' jQuery operates on parent window
  • ⚠️ Vue reactive data needs klona() before saving