View Source Tailwind Setup
Beacon has built-in support for Tailwind, any page can use tailwind classes out of the box and a stylesheet will be generated and served to style the pages correctly.
A default and simple configuration is already provided by Beacon, if you don't need custom config or plugins then you can skip this guide. Otherwise keep reading to set up a custom Tailwind configuration with more advanced features.
Objective
Make sure the proper Tailwind version is installed, create a Tailwind config in the ESM format, and if you intend to use plugins, then bundle everything together in a single module.
Steps
- Install Tailwind v3.3.0 or higher
- Install Esbuild
- Tailwind config in the ESM format
- Heroicons
- Install plugins
- Bundle the config
- Use the config in your site configuration
Let's go through each one to set up Tailwind properly for your sites.
Tailwind v3.3.0 or higher
Any recent Phoenix application should have the tailwind library already installed and updated but let's double check by executing:
mix run -e "IO.inspect Tailwind.bin_version()"
If it fails or the version is lower than 3.3.0 then follow the tailwind install guide to get it installed or updated. It's important to install a recent Tailwind version higher than 3.3.0
Esbuild
Similar to Tailwind, any recent Phoenix application should have it installed already but let's check by executing:
mix run -e "IO.inspect Esbuild.bin_version()"
If it fails then follow the esbuild install guide to get it installed. Any recent version that is installed should work just fine.
Config in the ESM format
We need the tailwind config file in the ESM format, ie: default export
instead of module.exports
.
That's because Beacon uses Tailwind to generate stylesheets for published pages (your deployed site) and also to preview pages in the Visual Editor (in your admin interface).
The former uses the tailwind-cli binary (a node application) while the latter compiles the stylesheet in the browser, so we need to reuse the same config file in both environments and ESM is the format that works in this scenario.
Most likely the existing config assets/tailwind.config.js
was created in the CommonJS format, so given a file like this:
module.exports = {
theme: {
colors: {
'blue': '#1fb6ff'
}
}
}
Replace how the module is exported to have a valid ESM config:
export default {
theme: {
colors: {
'blue': '#1fb6ff'
}
}
}
More info at https://tailwindcss.com/blog/tailwindcss-v3-3#esm-and-type-script-support
Heroicons
Some built-in components use Heroicons, which must be configured properly to let the Tailwind compiler find the SVG icon files.
See the Heroicons guide for more information.
Install plugins
The default config generated by Phoenix requires the @tailwindcss/froms
plugin so we need to install it first. Execute in the root of your project:
npm install --prefix assets --include=dev @tailwindcss/forms
Bundled config
We'll change 3 files to make it work:
config/config.exs
Open the file config/config.exs
, find the :esbuild
config, and add a new tailwind_bundle
that will look like this:
config :esbuild,
version: "0.23.0",
my_app: [
# omitted for brevity
],
# add this block
tailwind_bundle: [
args: ~w(tailwind.config.js --bundle --platform=node --format=esm --target=es2020 --outfile=../priv/tailwind.config.bundle.js),
cd: Path.expand("../assets", __DIR__),
env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
]
config/dev.exs
Open the file config/dev.exs
, find the :watchers
key in the endpoint config, and add a new tailwind_bundle
that will look like this:
config :my_app, MyAppWeb.Endpoint,
# omitted for brevity
watchers: [
esbuild: {Esbuild, :install_and_run, [:my_app, ~w(--sourcemap=inline --watch)]},
esbuild: {Esbuild, :install_and_run, [:tailwind_bundle, ~w(--watch)]}, # add this line
tailwind: {Tailwind, :install_and_run, [:my_app, ~w(--watch)]}
]
mix.exs
In the list of aliases, add the following command in both "assets.build"
and "assets.deploy"
:
"esbuild tailwind_bundle"
It will look like this:
defp aliases do
[
# omitted for brevity
"assets.build": ["tailwind my_app", "esbuild my_app", "esbuild tailwind_bundle"],
"assets.deploy": [
"tailwind my_app --minify",
"esbuild my_app --minify",
"esbuild tailwind_bundle",
"phx.digest"
]
]
end
Site Configuration
Note that if you're setting up the environment for the first time and have no site created yet, for example if you're following the "Your first site" or the "Create a blog" guide,
you won't have any site configuration to update. In this case, you can skip this step and come back to it later after executing the beacon.install
command.
Open the file lib/my_app/application.ex
(replace my_app with your actual application name), find the configuration of the site you'll be using
this Tailwind config and add the tailwind_config
key pointing to the bundled file:
tailwind_config: Path.join(Application.app_dir(:my_app, "priv"), "tailwind.config.bundle.js"),
It will look somewhat like this:
@impl true
def start(_type, _args) do
children = [
# omitted for brevity
{Beacon,
sites: [
[
site: :my_site,
repo: MyApp.Repo,
endpoint: MyAppWeb.Endpoint,
router: MyAppWeb.Router,
tailwind_config: Path.join(Application.app_dir(:my_app, "priv"), "tailwind.config.bundle.js") # add this line
]
]},
MyAppWeb.Endpoint
]
# omitted for brevity
end
Remember to replace my_app with the actual name of your application.