Skip to main content

Hooks Reference

Hooks allow plugins to react to events and modify behavior throughout LusterCMS.

How Hooks Work

LusterCMS uses Pluggy for its hook system:

from core.hooks import hookimpl

class MyPlugin:
@hookimpl
def after_content_save(self, entry_id: str) -> None:
# Your code runs after content is saved
pass

Available Hooks

Content Lifecycle

HookTriggerParameters
before_content_saveBefore saving contententry_id, data
after_content_saveAfter content is savedentry_id
before_content_publishBefore publishingentry_id
after_content_publishAfter content is publishedentry_id
before_content_deleteBefore deletingentry_id
after_content_deleteAfter content is deletedentry_id

Media Lifecycle

HookTriggerParameters
before_media_uploadBefore uploadfile, metadata
after_media_uploadAfter uploadmedia_id, file_path
before_media_deleteBefore deletingmedia_id
after_media_deleteAfter deletionmedia_id

User Lifecycle

HookTriggerParameters
after_user_registerAfter registrationuser_id
after_user_loginAfter loginuser_id
before_user_deleteBefore deletinguser_id

Theme & Plugin Lifecycle

HookTriggerParameters
before_theme_switchBefore switching themetheme_name
after_theme_switchAfter theme switchtheme_name
before_plugin_activateBefore activatingplugin_name
after_plugin_activateAfter activationplugin_name
before_plugin_deactivateBefore deactivatingplugin_name
after_plugin_deactivateAfter deactivationplugin_name

AI Lifecycle

HookTriggerParameters
before_ai_content_suggestBefore AI generationprompt, context
after_ai_content_suggestAfter AI generationresult, credits_used

Hook Examples

Logging Content Changes

from core.hooks import hookimpl
import logging

logger = logging.getLogger(__name__)

class AuditPlugin:
@hookimpl
def after_content_save(self, entry_id: str) -> None:
logger.info(f"Content saved: {entry_id}")

@hookimpl
def after_content_publish(self, entry_id: str) -> None:
logger.info(f"Content published: {entry_id}")

Sending Notifications

from core.hooks import hookimpl
from myapp.notifications import send_email

class NotificationPlugin:
@hookimpl
def after_content_publish(self, entry_id: str) -> None:
# Send notification to subscribers
send_email(
to="team@example.com",
subject="New content published",
body=f"Entry {entry_id} was just published."
)

Validating Content

from core.hooks import hookimpl
from core.exceptions import ValidationError

class ValidationPlugin:
@hookimpl
def before_content_save(self, entry_id: str, data: dict) -> None:
# Validate content before saving
if len(data.get("title", "")) < 5:
raise ValidationError("Title must be at least 5 characters")

Modifying AI Prompts

from core.hooks import hookimpl

class AIEnhancerPlugin:
@hookimpl
def before_ai_content_suggest(self, prompt: str, context: dict) -> dict:
# Add brand guidelines to AI prompts
enhanced_prompt = f"""
{prompt}

Brand Guidelines:
- Use friendly, conversational tone
- Avoid jargon
- Keep sentences short
"""
return {"prompt": enhanced_prompt, "context": context}

Hook Priority

Control execution order with hookimpl options:

from core.hooks import hookimpl

class MyPlugin:
@hookimpl(tryfirst=True)
def before_content_save(self, entry_id: str, data: dict) -> None:
# Runs before other plugins
pass

@hookimpl(trylast=True)
def after_content_save(self, entry_id: str) -> None:
# Runs after other plugins
pass

Best Practices

  1. Keep hooks fast — Don't block the main request
  2. Handle errors gracefully — Log and continue
  3. Use async for I/O — Offload heavy work
  4. Be idempotent — Hooks may run multiple times
  5. Document side effects — Make behavior clear

⚠️ Important

Hooks run synchronously in the request cycle. For heavy operations, use background tasks or queues.