Modern Frontend Techs for Wagtail

Table of Contents

Wagtail Tutorial Series:

To learn more about Wagtail CMS, please check Build Blog With Wagtail CMS (4.0.0)

  1. Create Wagtail Project
  2. Modern Frontend Techs for Wagtail
  3. Dockerizing Wagtail App
  4. Add Blog Models to Wagtail
  5. How to write Wagtail page template
  6. Create Stylish Wagtail Pages with Tailwind CSS
  7. How to use StreamField in Wagtail
  8. Wagtail Routable Page
  9. Add Pagination Component to Wagtail
  10. Customize Wagtail Page URL
  11. Add Full Text Search to Wagtail
  12. Add Markdown Support to Wagtail
  13. Add LaTeX Support & Code Highlight In Wagtail
  14. How to Build Form Page in Wagtail
  15. How to Create and Manage Menus in Wagtail
  16. Wagtail SEO Guide
  17. Online Demo http://wagtail-blog.accordbox.com/
  18. Source code: https://github.com/AccordBox/wagtail-tailwind-blog

Wagtail Tips:

  1. Wagtail Tip #1: How to replace ParentalManyToManyField with InlinePanel
  2. Wagtail Tip #2: How to Export & Restore Wagtail Site

Write style in Wagtail:

  1. How to use SCSS/SASS in your Django project (Python Way)
  2. How to use SCSS/SASS in your Django project (NPM Way)

Other Wagtail Topics:

  1. How to make Wagtail project have good coding style
  2. How to do A/B Testing in Wagtail CMS 
  3. How to build a landing page using Wagtail CMS 
  4. How to support multi-language in Wagtail CMS 
  5. Add Bootstrap Theme to Wagtail

More Wagtail articles and eBooks written by me

Objective

By the end of this chapter, you should be able to:

  1. Use python-webpack-boilerplate to jump start frontend project bundled by Webpack.
  2. Import Tailwind CSS as the style solution.
  3. Setup Live Reload with webpack-dev-server

Install python-webpack-boilerplate

python-webpack-boilerplate can help you jump start a frontend project that is bundled by Webpack

Add python-webpack-boilerplate to the requirements.txt

python-webpack-boilerplate==1.0.0
(venv)$ pip install -r requirements.txt

Update wagtail_app/settings.py to add 'webpack_boilerplate' to INSTALLED_APPS

INSTALLED_APPS = [
    ...

    'webpack_boilerplate',               # new
]

Let's run Django command to create frontend project from the python-webpack-boilerplate

(venv)$ python manage.py webpack_init

project_slug [frontend]:
run_npm_command_at_root [n]: y
 [SUCCESS]: Frontend app 'frontend' has been created. To know more, check https://python-webpack-boilerplate.rtfd.io/en/latest/frontend/

Here we set run_npm_command_at_root to y so we can run npm command at the root of the Django project

.
├── db.sqlite3
├── frontend                    # new
├── manage.py
├── package-lock.json
├── package.json
├── postcss.config.js
├── requirements.txt
├── venv
└── wagtail_app

Notes:

  1. Now a new frontend directory is created which contains predefined files for our frontend project.
  2. package.json and some other config files are placed at the root directory.

Run Frontend Project

If you have no nodejs installed, please install it first by using below links

  1. On nodejs homepage
  2. Using nvm or fnm I recommend this way.
$ node -v
v16.17.0
$ npm -v
8.15.0
# install dependency packages
$ npm install

# launch webpack dev server
$ npm run start

If the command run without error, that means the setup works, let's terminate the npm run start by pressing Ctrl + C

Install Tailwind

By default Python Webpack Boilerplate does not contain Tailwind CSS (it is just a boilerplate), let's add it.

# install packages
$ npm install -D tailwindcss@latest postcss-import

You should see something like this in the frontend/package.json

"postcss-import": "^15.0.0",
"tailwindcss": "^3.1.8",

Next, let's edit postcss.config.js

// https://tailwindcss.com/docs/using-with-preprocessors

module.exports = {
  plugins: [
    require('postcss-import'),
    require('tailwindcss/nesting')(require('postcss-nesting')),
    require('tailwindcss'),
    require('postcss-preset-env')({
      features: { 'nesting-rules': false }
    }),
  ]
};

Next, generate a config file for your frontend project using the Tailwind CLI utility included when you install the tailwindcss npm package

$ npx tailwindcss init

Now tailwind.config.js is generated

module.exports = {
    content: [],
    theme: {
        extend: {},
    },
    plugins: [],
}

We will edit this file in a bit.

Write Tailwind CSS

Update src/application/app.js

// This is the scss entry file
import "../styles/index.scss";

window.document.addEventListener("DOMContentLoaded", function () {
  window.console.log("dom ready 1");
});

Update src/styles/index.scss

@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";

.jumbotron {
  // should be relative path of the entry scss file
  background-image: url("../../vendors/images/sample.jpg");
  background-size: cover;
}

.btn-blue {
  @apply inline-flex items-center;
  @apply px-4 py-2;
  @apply font-semibold rounded-lg shadow-md;
  @apply text-white bg-blue-500;
  @apply hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-400 focus:ring-opacity-75;
}

Let's test again.

$ npm run start

Now the tailwindcss should be compiled successfully, let's test in the Django template.

Test in Django Template

Add code below to wagtail_app/settings.py

STATICFILES_DIRS = [
    str(BASE_DIR / "frontend/build"),
]

WEBPACK_LOADER = {
    'MANIFEST_FILE': str(BASE_DIR / "frontend/build/manifest.json"),
}
  1. We add the above frontend/build to STATICFILES_DIRS so Django can find the static assets built by the frontend app (img, font and others)
  2. We add MANIFEST_FILE location to the WEBPACK_LOADER so our custom loader can help us load the JS and CSS.

Update wagtail_app/urls.py

from django.views.generic import TemplateView

urlpatterns = [
    path('', TemplateView.as_view(template_name="index.html")),     # new
    ...
]

Here we use TemplateView to help us test the frontend app on http://localhost:8000/

Create a folder for templates

$ mkdir wagtail_app/templates

├── wagtail_app
│   ├── __init__.py
│   ├── asgi.py
│   ├── settings.py
│   ├── templates               # new
│   ├── urls.py
│   └── wsgi.py

Update TEMPLATES in wagtail_app/settings.py, so Django can know where to find the templates

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': ['wagtail_app/templates'],                             # new
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

Add index.html to the above wagtail_app/templates

{% load webpack_loader static %}

<!DOCTYPE html>
<html>
<head>
  <title>Index</title>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  {% stylesheet_pack 'app' %}
</head>
<body>

<div class="jumbotron py-5">
  <div class="w-full max-w-7xl mx-auto px-4">
    <h1 class="text-4xl mb-4">Hello, world!</h1>
    <p class="mb-4">This is a template for a simple marketing or informational website. It includes a large callout called a
      jumbotron and three supporting pieces of content. Use it as a starting point to create something more unique.</p>

    <p><a class="btn-blue mb-4" href="#" role="button">Learn more »</a></p>

    <div class="flex justify-center">
      <img src="{% static 'vendors/images/webpack.png' %}" />
    </div>
  </div>
</div>

{% javascript_pack 'app' %}

</body>
</html>
  1. We load webpack_loader at the top of the template, which comes from the python-webpack-boilerplate
  2. We can still use static to import images from the frontend project.
  3. We use stylesheet_pack and javascript_pack to load CSS and JS bundle files to Django
# please make sure 'npm run start' is still running
(venv)$ python manage.py runserver

Now check on http://127.0.0.1:8000/ and you should be able to see a welcome page.

Here we can see:

  1. The button style is working.
  2. Some styles in the Django templates such as w-full max-w-7xl mx-auto px-4 is not working.

JIT

From Tailwind V3, it enabled JIT (Just-in-Time) all the time.

Tailwind CSS works by scanning all of your HTML, JavaScript components, and any other template files for class names, then generating all of the corresponding CSS for those styles.

In order for Tailwind to generate all of the CSS you need, it needs to know about every single file in your project that contains any Tailwind class names.

So we should config the content section of the tailwind.config.js, then Tailwind will know which css classes are used.

Let's update tailwind.config.js

const Path = require("path");
const pwd = process.env.PWD;

// We can add current project paths here
const projectPaths = [
    Path.join(pwd, "./wagtail_app/templates/**/*.html"),
    // add js file paths if you need
];

const contentPaths = [...projectPaths];
console.log(`tailwindcss will scan ${contentPaths}`);

module.exports = {
    content: contentPaths,
    theme: {
        extend: {},
    },
    plugins: [],
}

Notes:

  1. Here we add Django templates path to the projectPaths
  2. And then we pass the contentPaths to the content
  3. The final built css file will contain css classes used in the Django templates
# restart webpack
$ npm run start

tailwindcss will scan wagtail_app/templates/**/*.html

As you can see, now Tailwind css can detect the Django templates and generate css classes in the final css file.

Setup Live Reload

With webpack-dev-server, we can use it to auto reload the web page when the code of the project changes.

Update frontend/webpack/webpack.config.dev.js

devServer: {
  // add this
  watchFiles: [
    Path.join(__dirname, '../../wagtail_app/**/*.py'),
    Path.join(__dirname, '../../wagtail_app/**/*.html'),
  ],
},

Let's restart webpack dev server.

# restart webpack
$ npm run start
  1. Here we tell webpack-dev-server to watch all .py and .html files under the wagtail_app directory.
  2. Now if we edit Django template in the editor, the web page will auto reload automatically, which is awesome!

You can open http://127.0.0.1:8000/ in a new browser tab and test.

More details can be found on Python Webpack Boilerplate Doc

Notes:

The frontend app created by python-webpack-boilerplate will use eslint and Stylelint to help developers keep javascript and css/scss code in good style.

Cleanup

Update wagtail_app/urls.py to remove the TemplateView route.

urlpatterns = [
    path('admin/', admin.site.urls),

    path('cms/', include(wagtailadmin_urls)),
    path('documents/', include(wagtaildocs_urls)),

    # For anything not caught by a more specific rule above, hand over to
    # Wagtail's serving mechanism
    path('', include(wagtail_urls)),
]

Remove below files since they are useless in this project

# those files are created by python-webpack-boilerplate
$ rm -rf frontend/src/components
$ rm -f frontend/src/application/app2.js

$ rm wagtail_app/templates/index.html

Wagtail Tutorial Series:

To learn more about Wagtail CMS, please check Build Blog With Wagtail CMS (4.0.0)

  1. Create Wagtail Project
  2. Modern Frontend Techs for Wagtail
  3. Dockerizing Wagtail App
  4. Add Blog Models to Wagtail
  5. How to write Wagtail page template
  6. Create Stylish Wagtail Pages with Tailwind CSS
  7. How to use StreamField in Wagtail
  8. Wagtail Routable Page
  9. Add Pagination Component to Wagtail
  10. Customize Wagtail Page URL
  11. Add Full Text Search to Wagtail
  12. Add Markdown Support to Wagtail
  13. Add LaTeX Support & Code Highlight In Wagtail
  14. How to Build Form Page in Wagtail
  15. How to Create and Manage Menus in Wagtail
  16. Wagtail SEO Guide
  17. Online Demo http://wagtail-blog.accordbox.com/
  18. Source code: https://github.com/AccordBox/wagtail-tailwind-blog

Wagtail Tips:

  1. Wagtail Tip #1: How to replace ParentalManyToManyField with InlinePanel
  2. Wagtail Tip #2: How to Export & Restore Wagtail Site

Write style in Wagtail:

  1. How to use SCSS/SASS in your Django project (Python Way)
  2. How to use SCSS/SASS in your Django project (NPM Way)

Other Wagtail Topics:

  1. How to make Wagtail project have good coding style
  2. How to do A/B Testing in Wagtail CMS 
  3. How to build a landing page using Wagtail CMS 
  4. How to support multi-language in Wagtail CMS 
  5. Add Bootstrap Theme to Wagtail

More Wagtail articles and eBooks written by me

Launch Products Faster with Django

SaaS Hammer helps you launch products in faster way. It contains all the foundations you need so you can focus on your product.

Michael Yin

Michael is a Full Stack Developer from China who loves writing code, tutorials about Django, and modern frontend tech.

He has published some ebooks on leanpub and tech course on testdriven.io.

He is also the founder of the AccordBox which provides the web development services.

Django SaaS Template

It aims to save your time and money building your product

Learn More

This book will teach you how to build a SPA (single-page application) with React and Wagtail CMS

Read More
© 2018 - 2024 AccordBox