Provides frontend development guidelines for Nette. Use when working with Vite, SCSS, JavaScript, Nette Assets, or build configuration.
Frontend built with modern tooling and seamlessly integrated with Nette backend through Nette Assets.
See the Nette Assets reference for asset management. See the Vite integration guide for build configuration.
"type": "module" in package.jsonSource vs Built Assets separation:
assets/ directory with source files (SCSS, TypeScript, images)www/assets/ with optimized, versioned files for browsersUse separate entry points when:
Example strategy:
// assets/front.js - Public website (custom design)
import './css/front.scss';
import './js/components/product-gallery.js';
// assets/admin.js - Administration (Bootstrap-based)
import 'bootstrap/dist/css/bootstrap.css';
import './css/admin.scss';
File-per-component approach:
assets/js/
├── components/
│ ├── product-form.js ← Reusable form component
│ ├── image-gallery.js ← Product image viewer
├── pages/
│ ├── blog.css ← Page-specific enhancements
│ └── checkout.css ← Multi-step checkout flow
└── utils/
├── ajax.js ← AJAX utilities
└── validation.js ← Form validation helpers
Basic asset loading
{* Loads complete bundle with all dependencies *}
{asset 'front.js'}
Configuration
assets:
mapping:
default:
type: vite
path: assets # REQUIRED in practice - must match Vite's build.outDir
path is optional in the schema and nothing validates it, but when omitted it falls back to
%wwwDir%, so the manifest is looked up in www/.vite/manifest.json instead of
www/assets/.vite/manifest.json and you get RuntimeException: Failed to read Vite manifest.
devServer defaults to true, so there is no need to write it.
Passing data to JavaScript:
{* In template *}
<script>
window.appConfig = {
apiUrl: {$baseUrl . '/api'},
userId: {$user->isLoggedIn() ? $user->getId() : null},
locale: {$locale},
csrfToken: {$csrfToken}
};
</script>
{asset 'front.js'}
Latte automatically applies context-sensitive escaping – values inside <script> are JSON-encoded, so strings get quoted and null stays null.
// In JavaScript component
const { apiUrl, userId, csrfToken } = window.appConfig;
fetch(`${apiUrl}/user-data`, {
headers: { 'X-CSRF-Token': csrfToken }
});
Naja is the standard AJAX library for Nette – it handles snippet redrawing, form submissions, and history integration:
npm install naja
import naja from 'naja';
// Initialize after DOM is ready
naja.initialize();
Naja automatically intercepts links and forms with the ajax CSS class and handles snippet updates from the server. See Naja documentation for configuration and extensions.
Requires nette-forms npm package:
npm install nette-forms
Standard enhancement pattern:
import netteForms from 'nette-forms';
// Initialize Nette Forms validation
netteForms.initOnLoad();
npm install --save-dev @nette/eslint-plugin eslint
Basic configuration with recommended rules:
// eslint.config.js
import nette from '@nette/eslint-plugin';
import { defineConfig } from 'eslint/config';
export default defineConfig([
{
extends: [nette.configs.recommended],
},
]);
Linting JavaScript in Latte templates:
npm install --save-dev eslint-plugin-html
// eslint.config.js
import nette from '@nette/eslint-plugin';
import pluginHtml from 'eslint-plugin-html';
import { defineConfig } from 'eslint/config';
export default defineConfig([
{
extends: [nette.configs.recommended],
},
{
files: ['app/**/*.latte'],
plugins: {
html: pluginHtml,
},
processor: '@nette/latte', // Handles Latte tags in JS
},
]);
This allows ESLint to check JavaScript inside <script> tags with Latte variables:
<script>
let name = {$name};
</script>
TypeScript support:
npm install --save-dev typescript typescript-eslint
import nette from '@nette/eslint-plugin/typescript';
export default defineConfig([
{
extends: [nette.configs.typescript],
},
]);
Custom rules:
@nette/no-this-in-arrow-except - Prevents this binding issues in arrow functions@nette/prefer-line-comments - Enforces // over /* */ for single-line commentsWhen using Tailwind CSS, configure it to scan Latte templates for class names:
/* assets/css/app.css */
@import 'tailwindcss';
@source '../app/**/*.latte';
For detailed information, use WebFetch on these URLs:
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer