Skip to main content

Flask-Tailwind-Manager

Tailwind CSS v4 integration for Flask, with optional Preline, Flowbite, and daisyUI adapters. Flask-Tailwind-Manager owns stylesheets, Tailwind configuration helpers, and build/watch commands. Flask-Node owns the shared Node environment, npm requirements, execution, package resolution, and browser asset publication.

The distribution remains flask-tailwind-manager, the Python import remains flask_tailwind, and the CLI namespace remains flask tailwind.

Installation

Requires Python 3.10+, Flask 2.2–3.x, and Flask-Node 0.2.0 or newer within the 0.2 series. Flask-Node is installed automatically as a required Python dependency. Install Node.js with npm/npx separately for synchronization, builds, watches, and plugin-entry resolution.

pip install flask-tailwind-manager
# Optional explicit installation spelling:
pip install 'flask-tailwind-manager[preline]'
pip install 'flask-tailwind-manager[flowbite]'
pip install 'flask-tailwind-manager[daisyui]'
pip install 'flask-tailwind-manager[preline,flowbite]'

The built-in integrations have no additional Python dependencies. These extras are intentionally empty: all definitions are available with the base package. An extra does not enable an integration, install npm packages, or create files. Enable integrations explicitly in each Flask application's configuration.

Application setup

from flask import Flask
from flask_tailwind import TailwindCSS

tailwind = TailwindCSS()


def create_app():
    app = Flask(__name__)
    app.config["TAILWIND_INTEGRATIONS"] = ["preline"]
    tailwind.init_app(app)
    return app

TailwindCSS(app) also works. Tailwind initializes Flask-Node if necessary and reuses an existing app.extensions['node'] manager. Other consumers may share that manager. For explicit Node setup, call Node().init_app(app) before Tailwind initialization. Do not initialize Node again afterward; use Node().get_manager(app) to retrieve the manager.

Application initialization only registers state, requirements, and browser asset declarations. It creates no directories, executes no processes, copies no assets, and accesses no network. Settings and enabled integrations are application-local, including when one TailwindCSS() instance serves several application factories. Unknown integration names fail with a list of available integrations.

Application-owned stylesheet and configuration

Configure paths before extension initialization.

Setting Default Meaning
TAILWIND_INPUT_PATH src/input.css Relative to app.static_folder, or absolute
TAILWIND_OUTPUT_PATH css/style.css Relative to app.static_folder
TAILWIND_TEMPLATE_FOLDER app.template_folder Relative to app.root_path, or absolute; overrides the initial template source path
TAILWIND_INTEGRATIONS [] Enabled names: preline, flowbite, daisyui

Flask must have a static folder. If no template folder is configured, initial CSS omits the template source clause. Additional template directories, including blueprint templates, can be added manually to the stylesheet.

Flask-Node configuration is delegated unchanged:

Setting Default Meaning
NODE_DIR .node Relative to app.root_path, or absolute
NODE_PYPROJECT pyproject.toml Application npm declarations; relative to app.root_path, or absolute
NODE_BIN node Node executable
NODE_NPM_BIN npm npm executable
NODE_NPX_BIN npx npx executable

For .node beside an application package, configure an absolute project path:

from pathlib import Path

app.config["NODE_DIR"] = Path(app.root_path).parent / ".node"

That layout becomes:

project/
├── .node/
│   ├── package.json
│   ├── package-lock.json
│   └── node_modules/
└── app/
    ├── templates/
    └── static/
        ├── src/input.css        # Application source: commit this file
        ├── css/style.css        # Compiled CSS
        └── vendor/preline/preline.js

input.css belongs to the developer. Tailwind init creates it once, using exclusive file creation. It never overwrites an existing file. The initial CSS contains a calculated import to the shared environment's Tailwind stylesheet and a calculated source path to Flask's template folder. No path assumes app/static or the shell working directory.

Integrations do not automatically add directives to existing or new stylesheets. Configuration helpers print the required directives for the developer to apply. There is no --apply, template modification, or automatic script injection.

Fresh-project Preline workflow

After enabling Preline as shown above:

flask --app your_app node sync
flask --app your_app tailwind init
flask --app your_app node publish
flask --app your_app tailwind integration preline

node sync realizes all application and extension requirements in the shared Node environment. tailwind init creates missing application-owned input CSS; when Tailwind packages are already installed, it does not repeat installation. node publish copies registered browser assets using Flask-Node.

The integration command reports the input file, npm requirements, calculated CSS directives, and browser asset destinations. Add its CSS directives after the initial Tailwind import. Keep CSS imports before source/plugin directives. Include the published browser script manually in the application template:

<script src="{{ url_for('static', filename='vendor/preline/preline.js') }}"></script>

Then build or watch:

flask --app your_app tailwind build
flask --app your_app tailwind start
flask --app your_app tailwind start -- --poll

Build produces minified CSS. Start watches changes. Commands delegate to Flask-Node's npx runner with absolute input/output paths and streamed output. First-use build/watch can install missing core Tailwind packages and create missing source CSS. Use explicit node sync and node publish to realize enabled integrations. CLI failures retain useful Flask-Node diagnostics and exit nonzero.

Load compiled CSS using the existing helper:

{{ tailwind_css() }}

Available integrations

Name npm requirements Tailwind configuration Browser publication
preline preline ^3, @tailwindcss/forms ^0.5 Source glob, variants import, forms plugin dist/preline.js → vendor/preline/preline.js
flowbite flowbite ^3 Source glob, Flowbite plugin dist/flowbite.min.js → vendor/flowbite/flowbite.min.js
daisyui daisyui ^5 daisyUI plugin None

These definitions target Tailwind v4. Package files were verified against Preline 3.2.3, Flowbite 3.1.2, daisyUI 5.0.0, and forms 0.5.10. Library configuration follows the Preline installation guide, Flowbite configuration, and daisyUI installation guide.

Each definition is immutable data: requirements, sources, imports, plugins, and optional browser assets. Core processes these declarations without library-specific conditionals or lifecycle hooks. The registry is fixed; there is no plugin discovery framework. Full Flask extensions such as Flask-Leaflet remain separate consumers of Flask-Node.

Flask-Node compares requirement strings exactly. An application declaration of a package already required by an integration must agree with its version and section. Keep additional npm declarations in the application's Flask-Node configuration; node sync rebuilds the managed manifest from declarations and does not preserve hand-edited npm scripts or undeclared manifest dependencies.

Path, directive, and diagnostic helpers

flask --app your_app tailwind paths
flask --app your_app tailwind path preline 'dist/*.js'
flask --app your_app tailwind source preline 'dist/*.js'
flask --app your_app tailwind import preline variants.css
flask --app your_app tailwind plugin daisyui
flask --app your_app tailwind plugin flowbite plugin
flask --app your_app tailwind integrations
flask --app your_app tailwind integration preline

paths displays configured input, output, template, static, and Node directories. Use flask node status for executable/environment diagnostics. integrations distinguishes available definitions from enabled ones. Integration output labels assets as registered; registration is not proof that publication has happened.

Python equivalents, inside the appropriate application context:

with app.app_context():
    tailwind.input_path
    tailwind.node_path("preline", "dist/*.js")
    tailwind.source("preline", "dist/*.js")
    tailwind.import_package("preline", "variants.css")
    tailwind.plugin("daisyui")
    tailwind.plugin("flowbite", "plugin")
    tailwind.integration_config("preline")
    tailwind.paths()
    tailwind.integrations  # Enabled immutable definitions

Paths are relative to input_path.parent, normalized to /, and CSS strings are escaped. Package locations come from Flask-Node. Glob helpers resolve their fixed prefix through Flask-Node and retain the wildcard suffix; they do not expand globs. Plugin helpers use Flask-Node's resolve_entry() with its CommonJS require-resolution conditions, without evaluating package code. Plugin inspection requires Node; ordinary explicit-file/source helpers do not launch commands. Different Windows drives cannot be expressed as relative CSS paths and produce a useful error.

Helpers never install packages. Enable the desired integration and run flask node sync first. An available-but-disabled integration can be inspected if its packages are installed, but inspection does not enable it or register assets.

Version control and compatibility

Commit application source CSS and the application's npm declarations. For the shared Node environment, follow Flask-Node's lockfile/reproducibility workflow; use flask node ci when its manifest and lockfile agree with current declarations. Ignore installed modules (adjust the path for your configured Node directory):

.node/node_modules/

Relative TAILWIND_INPUT_PATH now resolves against the Flask static folder rather than the Node directory. The default source location has also changed. This task provides no automatic migration from any earlier input location: existing apps should keep an explicit absolute input path until they are migrated separately. No user files are moved or deleted.

The existing TailwindCSS initialization API, tailwind_css(), init/start/build, and output setting remain. Extension settings and helper methods require an application context. get_output_path() retains its historical relative result; get_absolute_output_path() provides the execution path.

Legacy Node settings remain deprecated aliases for this transition release:

Old setting Replacement
TAILWIND_CWD NODE_DIR
TAILWIND_NPM_BIN_PATH NODE_NPM_BIN
TAILWIND_NPX_BIN_PATH NODE_NPX_BIN

Aliases warn, preserve explicitly configured legacy directory semantics, and fail on conflicts with new configuration or an existing manager. flask tailwind npm and flask tailwind npx remain warning aliases; prefer flask node npm and flask node npx. They require an initialized Node environment. Old standalone ConsoleInterface and package-manifest-generation helpers remain removed.

Development and tests

uv sync --upgrade
uv run pytest

For unreleased local Flask-Node changes, install its sibling checkout editably into your development environment. Production metadata uses the released dependency.

Tests use actual Flask-Node managers and temporary package structures, mocking command execution. An additional offline test uses real Node when available to prove plugin entry resolution without evaluating package code. Tests download no npm packages and require no network access.

Metadata

Release files for flask-tailwind-manager 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for flask-tailwind-manager 0.1.0
File Size Uploaded
flask_tailwind_manager-0.1.0.tar.gz 21.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for flask-tailwind-manager 0.1.0
File Interpreter ABI Platform
flask_tailwind_manager-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 37.3 kB

Release files / flask_tailwind_manager-0.1.0.tar.gz

Download URL flask_tailwind_manager-0.1.0.tar.gz
Size 21.8 kB
Tags Source
SHA-256 checksum
How to use checksums
628473f524f13b79091f9816b0d4edba4cfdcc75b39c065efde546c239db32f1
BLAKE2b-256 checksum
How to use checksums
9de5328b961c0e8b023d11f4c84685277af22d021da03ef7cc6ea11c7978a10d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.9 {"installer":{"name":"uv","version":"0.12.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / flask_tailwind_manager-0.1.0-py3-none-any.whl

Download URL flask_tailwind_manager-0.1.0-py3-none-any.whl
Size 15.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
99431c18c0cf00ade160589444c53c3a6315b7b256061d83746d424c1ac8fc4c
BLAKE2b-256 checksum
How to use checksums
9e98fc669494aca634fb39d3417c0873f93b0cdae10c8a8fc7bce2ecec554ef3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.9 {"installer":{"name":"uv","version":"0.12.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

0.1.1

2 release files

This release

0.1.0 This release

2 release files

0.0.20

2 release files

0.0.19

2 release files

0.0.18

2 release files

0.0.17

2 release files

0.0.13

2 release files

0.0.11

2 release files

0.0.10

2 release files

0.0.9

2 release files

0.0.8

2 release files

0.0.7

2 release files

0.0.6

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page