justdev / starter_frontend_twig
Vite front-end twig boilerplate
Package info
github.com/kirilldorozhynskyi/starter_frontend_twig
Language:Twig
Type:project
pkg:composer/justdev/starter_frontend_twig
Requires
- php: >=7.3
- composer/installers: ^1.11
README
Starter template for static frontends built with Vite, Twig, Vue 3, and Tailwind CSS 4. It combines file-based pages, reusable Twig components, a small Vue app layer, image helpers, SVG spritemap generation, and a simple WordPress handoff for production themes.
Stack
- Vite 8
- Vituum + Twig
- Vue 3 + TypeScript
- Tailwind CSS 4
vanilla-lazyloadvue-i18n@spiriit/vite-plugin-svg-spritemapvite-plugin-imagemin
Requirements
- Node.js LTS, preferably Node 20+
- npm
- Optional: PHP and Composer if you want to bootstrap a project via
composer create-project
Installation
Use this repository directly
npm install
Create a new project from Composer
composer create-project justdev/starter_frontend_twig your-project-name
cd your-project-name
The Composer installer will:
- remove template-only Composer files
- rename the workspace file
- initialize a new Git repository
- run
npm install
Available scripts
npm run dev npm run build npm run preview npm run webp npm run i18n:add npm run i18n:remove
npm run dev: start the Vite development servernpm run build: create a production build indist/npm run preview: preview the production build locallynpm run webp: convert.pngand.jpgfiles insidesrc/public/assets/images/to.webpnpm run i18n:add: add missing translation keys found in Vue filesnpm run i18n:remove: remove unused translation keys
Project structure
.
├── config.js
├── doc/
├── scripts/
├── src/
│ ├── data/
│ ├── pages/
│ ├── public/
│ ├── resources/fonts/
│ ├── scripts/
│ ├── styles/
│ └── views/
└── vite.config.js
src/data/main.json: global site data shared across pagessrc/pages/: routes generated from.twigand.jsonfilessrc/views/: layouts, templates, and Twig componentssrc/scripts/: Vue components, directives, i18n config, and the main app entrysrc/styles/: Tailwind entry file, Sass partials, and Tailwind safelistsrc/public/: static assets copied to the final buildsrc/resources/fonts/: local font filesdoc/: WordPress integration helpers
Working with pages
The project supports both direct Twig pages and data-driven JSON pages.
Twig page
Create a file such as src/pages/about.twig:
{% extends 'views/layouts/main.twig' %}
{% block page %}
<section class="container py-16">
<h1>About</h1>
</section>
{% endblock %}
JSON page
Create a file such as src/pages/about.json:
{
"title": "About",
"template": "views/templates/page.twig",
"flexible": [
{
"name": "content",
"title": "About",
"text": "Page content defined in JSON."
}
]
}
The default page templates in src/views/templates/ loop over flexible blocks and include matching Twig partials from src/views/components/flexible/<name>/_<name>.twig.
Styling
src/styles/app.css is the main entry point. It uses Tailwind CSS 4 and can also pull in Sass partials with @use.
- add reusable utilities directly in
src/styles/app.css - keep shared Sass helpers in
src/styles/base/ - keep always-included Tailwind classes in
src/styles/safelist.txt
Vue layer
src/scripts/app.ts mounts Vue on #page and wires up:
- lazy loading for images and background assets
- locale detection through
vue-i18n - a small page transition/unload handler
- scroll-to-top behavior
- custom directives such as PhotoSwipe
Put Vue components in src/scripts/components/ and directives in src/scripts/directives/.
Assets and Twig helpers
Images
Store image files in src/public/assets/images/ and render them with the Twig image() helper:
{% set media = {
pictureClass: 'picture',
image: {
src: 'content/example',
src_2x: 'content/example@2x',
ext: 'png',
webp: true,
alt: 'Example image',
width: 1200,
height: 800
}
} %}
{{ image(media) }}
When webp is enabled, the helper adds a WebP source in production builds.
SVG spritemap
Place icons in src/public/assets/icons/. They are bundled into a spritemap automatically.
{{ sprite('instagram') }}
{{ sprite('instagram', 'h-6 w-6') }}
SVG object helper
Use the svg() helper for standalone SVG files from src/public/assets/images/:
{{ svg({
title: 'Brand logo',
width: '40',
height: '32',
src: '/brand/logo.svg'
}) }}
Fonts
Store local fonts in src/resources/fonts/. The Vite config exposes them through the ~fonts alias.
Configuration
Main build options live in config.js.
base: public base path used by ViterootDir: Twig root directory passed to VituumassetsDir: source directory used for icons and favicon generationfonts: font source and output path settingshtmlMinify: HTML minification optionshtmlBeautify: optional beautify step after buildimagemin: image optimization settingsSvgSpritemap: SVG spritemap generation settings
Production favicon files are generated from src/public/assets/favicon.svg.
WordPress integration
If the built assets need to be consumed by a WordPress theme, see:
doc/README.mddoc/wp_vite_plugin.phpdoc/wp_vite_enqueue.php
Those files cover both an MU plugin approach and a functions.php include approach.