🤖 PR generated for branch `fix/cyrillic-fonts-dev-certs-and-page-head`.
### Changes Summary
- **Fonts**: Add Cyrillic glyph subsets for Lato, EB Garamond, and Fira
Code.
- **Dev**: Support remote Root CA and encrypted dev CA key in
`.env.dev`.
- **UI & Kits**: Add size variant to `Breadcrumbs` component and enlarge
`PageHead` breadcrumbs with tuned collapse scroll threshold.
- **ESLint**: Add `no-hanging-particles` i18n & markdown typography rule
with auto-fixer.
- **Content & i18n**: Apply `ru-text` editorial and typography polish
(em dashes, number ranges, «ё» restoration, non-breaking spaces) across
`services/www` and `services/docs`.
3.2 KiB
title, weight
| title | weight |
|---|---|
| Module Development Workflow | 1 |
Goal: Create a new feature for the Quetza bot by implementing a self-contained module.
1. Conceptualization Phase
Before writing code, determine the module's architecture:
- Simple Command: Needs only a
commands/folder (e.g., utility commands). - Reactive Logic: Needs
events/to listen to Discord lifecycles (e.g., welcome messages). - Stateful Feature: Needs a Controller to manage state across guilds (e.g., music player).
2. Structure Establishment
Create the module directory structure. The presence of these files triggers automatic discovery.
{{< filetree/container >}} {{< filetree/folder name="src" state="open" >}} {{< filetree/folder name="modules" state="open" >}} {{< filetree/folder name="my-feature" state="open" >}} {{< filetree/file name="module.ts" >}} {{< filetree/folder name="commands" >}} {{< /filetree/folder >}} {{< filetree/folder name="events" >}} {{< /filetree/folder >}} {{< filetree/folder name="lib" >}} {{< /filetree/folder >}} {{< /filetree/folder >}} {{< /filetree/folder >}} {{< /filetree/folder >}} {{< /filetree/container >}}
3. Implementation Steps
{{% steps %}}
Step 1: Create the Manifest
Create module.ts to declare the module.
// src/modules/my-feature/module.ts
export const name = 'my-feature';
export const description = 'Adds cool feature capabilities';
// Optional: export const controller = new MyFeatureController();
Step 2: Implement Commands
Create command files in commands/. Each file exports data and an executor.
// src/modules/my-feature/commands/ping.ts
import { SlashCommandBuilder } from 'discord.js';
export const data = new SlashCommandBuilder().setName('ping').setDescription('Replies with Pong!');
export async function execute(interaction) {
await interaction.reply('Pong!');
}
Step 3: Implement Events (Optional)
Create event handlers in events/ to observe Discord state.
// src/modules/my-feature/events/ready.ts
import { Events } from 'discord.js';
export const name = Events.ClientReady;
export const once = true;
export function execute(client) {
console.log(`Ready! Logged in as ${client.user.tag}`);
}
Step 4: Define Controller (Optional)
For stateful logic, implement a controller in lib/ and export it in module.ts.
Step 5: Validate
Restart the bot.
- Check logs for "Loaded module: my-feature".
- Verify the command
/pingappears in Discord.
{{% /steps %}}
Integration Patterns
| Pattern | Use Case | Components |
|---|---|---|
| Simple Command | Stateless utilities (Ping, Dice Roll) | commands/ only |
| Stateful Service | Music, RPGs, Economy | commands/ + lib/Controller |
| Event-Driven | Auto-moderation, Logging | events/ only |
| Hybrid | Complex features (AI Chat) | All components |
See also: