smithery/psincraian

frontend-module

myfy FrontendModule for server-side rendering with Jinja2, Tailwind 4, DaisyUI 5, and Vite. Use when working with FrontendModule, templates, render_template, static files, Tailwind CSS, or Vite HMR.

Installation

$ npx skills add smithery/psincraian --skill frontend-module

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery/psincraian.

npx skills add smithery/psincraian

Browse all from smithery/psincraian

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 6,681 B
  • docs SUMMARY.md 221 B

History

  1. First recorded snapshot · 0 installs

SKILL.md

FrontendModule - Server-Side Rendering

FrontendModule provides Jinja2 templates with Tailwind 4, DaisyUI 5, and Vite bundling.

Quick Start

from myfy.core import Application
from myfy.web import WebModule, route
from myfy.frontend import FrontendModule, render_template

app = Application()
app.add_module(WebModule())
app.add_module(FrontendModule(auto_init=True))  # Auto-scaffolds!

@route.get("/")
async def home() -> str:
    return render_template("home.html", title="Welcome")

Configuration

Environment variables use the MYFYFRONTEND prefix:

Variable Default Description
MYFYFRONTENDENVIRONMENT development Environment mode
MYFYFRONTENDENABLEVITEDEV True Start Vite dev server
MYFYFRONTENDVITEDEVSERVER http://localhost:3001 Vite server URL
MYFYFRONTENDSTATICURLPREFIX /static Static files URL path
MYFYFRONTENDCACHESTATICASSETS True Enable static caching
MYFYFRONTENDCACHEMAXAGE 31536000 Cache max-age (1 year)
MYFYFRONTENDSHOWVITELOGS False Show Vite console output

Module Options

FrontendModule(
    templates_dir="frontend/templates",  # Template directory
    static_dir="frontend/static",        # Static files directory
    auto_init=True,                      # Auto-scaffold if missing
)

Auto-Scaffolding

With auto_init=True, FrontendModule creates:

frontend/
  templates/
    base.html           # Base template with Tailwind
    home.html           # Example home page
  static/
    src/
      main.js           # Entry point
      main.css          # Tailwind imports
package.json            # Node dependencies
vite.config.js          # Vite configuration
tailwind.config.js      # Tailwind configuration

Template Rendering

Basic Rendering

from myfy.frontend import render_template

@route.get("/")
async def home() -> str:
    return render_template("home.html", title="Home")

With Context

@route.get("/users/{user_id}")
async def user_profile(user_id: int, session: AsyncSession) -> str:
    user = await session.get(User, user_id)
    return render_template("profile.html", user=user)

With Request Context

from starlette.requests import Request

@route.get("/dashboard")
async def dashboard(request: Request, user: User) -> str:
    return render_template(
        "dashboard.html",
        request=request,  # For url_for, CSRF, etc.
        user=user,
    )

Base Template

<!-- frontend/templates/base.html -->
<!DOCTYPE html>
<html lang="en" data-theme="light">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{% block title %}My App{% endblock %}</title>
    {{ vite_assets("src/main.js") }}
</head>
<body class="min-h-screen bg-base-100">
    <div class="navbar bg-base-200">
        <a class="btn btn-ghost text-xl" href="/">My App</a>
    </div>
    <main class="container mx-auto px-4 py-8">
        {% block content %}{% endblock %}
    </main>
</body>
</html>

Page Template

<!-- frontend/templates/home.html -->
{% extends "base.html" %}

{% block title %}{{ title }} - My App{% endblock %}

{% block content %}
<div class="hero min-h-[50vh]">
    <div class="hero-content text-center">
        <div class="max-w-md">
            <h1 class="text-5xl font-bold">Hello, World!</h1>
            <p class="py-6">Welcome to your myfy application.</p>
            <button class="btn btn-primary">Get Started</button>
        </div>
    </div>
</div>
{% endblock %}

DaisyUI Components

DaisyUI 5 provides ready-to-use components:

<!-- Buttons -->
<button class="btn btn-primary">Primary</button>
<button class="btn btn-secondary">Secondary</button>
<button class="btn btn-outline">Outline</button>

<!-- Cards -->
<div class="card bg-base-100 shadow-xl">
    <div class="card-body">
        <h2 class="card-title">Card Title</h2>
        <p>Card content here.</p>
        <div class="card-actions justify-end">
            <button class="btn btn-primary">Action</button>
        </div>
    </div>
</div>

<!-- Forms -->
<div class="form-control">
    <label class="label">
        <span class="label-text">Email</span>
    </label>
    <input type="email" class="input input-bordered" />
</div>

<!-- Alerts -->
<div class="alert alert-success">
    <span>Success! Your action was completed.</span>
</div>

Theme Switching

<!-- Theme toggle -->
<label class="swap swap-rotate">
    <input type="checkbox" class="theme-controller" value="dark" />
    <svg class="swap-on w-6 h-6" fill="currentColor"><!-- sun icon --></svg>
    <svg class="swap-off w-6 h-6" fill="currentColor"><!-- moon icon --></svg>
</label>

Static Assets

Vite Helper

<!-- Loads JS and CSS with HMR in development -->
{{ vite_assets("src/main.js") }}

Manual Asset URLs

<img src="{{ asset_url('images/logo.png') }}" alt="Logo">

Development Workflow

  1. Start the application:

``bash myfy run `` Vite dev server starts automatically with HMR.

  1. Edit templates and CSS - changes reflect instantly.
  1. Build for production:

``bash npm run build ` Creates optimized assets in frontend/static/dist/`.

Production Build

# Build assets
npm run build

# Set production mode
export MYFY_FRONTEND_ENVIRONMENT=production
export MYFY_FRONTEND_ENABLE_VITE_DEV=false

# Run application
myfy run

Assets are served from the built manifest with cache headers.

Custom Jinja Filters

from myfy.frontend import FrontendModule
from starlette.templating import Jinja2Templates

# After module initialization
templates: Jinja2Templates = container.get(Jinja2Templates)
templates.env.filters["currency"] = lambda x: f"${x:.2f}"

Use in templates:

<span>{{ price | currency }}</span>

Best Practices

  1. Use auto_init for new projects - Gets you started quickly
  2. Extend base.html - Keep consistent layout
  3. Use DaisyUI components - Pre-styled, accessible
  4. Enable caching in production - Set long cache max-age
  5. Build assets before deploy - Don't rely on Vite in production
  6. Use template inheritance - Keep templates DRY
  7. Pass request for url_for - Enables dynamic URL generation