Hello, I’m working on the reation of a static site for a professionnel work.
I’m building a Hugo site using the Blowfish theme and integrating some React components. Furthermore, I’m using a single custom.css file to update the style of my pages and some specific react components depending on their classes. Now, I’m trying to load an additional custom CSS file from assets/css/.
However, simply importing the file or adding it to customCSS in params.toml does not work, and I don’t know why.
Originally, my goal was to reuse a Modular Forms component (a Preact-based library) to build a contact form inside Hugo similar to this one: Playground: Login form (Preact) | Modular Forms
Since Hugo doesn’t support React natively, Preact is the recommended alternative (I call Preact with CDNs).
The problem is that the Modular Forms components rely on Tailwind CSS classes, but my Hugo site does not have Tailwind enabled at runtime. As a result, classes like bg-blue-500 or rounded-lg are not recognized, and the components render without styling.
Because Tailwind is not active in the final Hugo build, I had to manually recreate the required styles inside custom.css using plain CSS, refreshing it each time to update the site, and making the file even bigger.
This is not ideal, and it’s ind of annoying since plan to add more react components in the future. I would prefer to either use Tailwind directly or load additional CSS files properly from assets/css/.
Project Architecture:
inovStatique/
├── assets/
│ └── css/
│ ├── custom.css
│ └── contact.css (not loaded by Hugo)
│
├── static/
│
├── content/
│ ├── _index.md/
│ ├── Welcome/
│ ├── Team/
│ ├── Projects/
│ ├── Services/
│ └── Contact/
│ ├── _index.md
│ └── contact.md
│
├── layouts/
│ ├── partials/
│ │ └── preact-contact-script.html
│ └── shortcodes/
│ └── contact-modular-forms.html
│
├── themes/
│ └── blowfish/
│
├── config/_default/
│ └── params.toml
Params.toml:
# -- Theme Options --
# These options control how the theme functions and allow you to
# customise the display of your website.
#
# Refer to the theme docs for more details about each of these parameters.
# https://blowfish.page/docs/configuration/#theme-parameters
colorScheme = "blowfish"
defaultAppearance = "light"
autoSwitchAppearance = false
disableThemeToggle = true
[params]
customCSS = ["css/custom.css"]
enableA11y = false
enableSearch = true
enableCodeCopy = false
enableStructuredBreadcrumbs = false
replyByEmail = false
# mainSections = ["section1", "section2"]
# robots = ""
disableImageOptimization = false
disableImageOptimizationMD = false
disableTextInHeader = false
# backgroundImageWidth = 1200
# defaultBackgroundImage = "IMAGE.jpg" # used as default for background images
# defaultFeaturedImage = "IMAGE.jpg" # used as default for featured images in all articles
# defaultSocialImage = "/android-chrome-512x512.png" # used as default for social media sharing (Open Graph and Twitter)
hotlinkFeatureImage = false
# imagePosition = "50% 50%"
# highlightCurrentMenuArea = true
# smartTOC = true
# smartTOCHideUnfocusedChildren = true
fingerprintAlgorithm = "sha512" # Valid values are "sha512" (default), "sha384", "sha256"
giteaDefaultServer = "https://git.fsfe.org"
forgejoDefaultServer = "https://v11.next.forgejo.org"
[header]
layout = "basic" # valid options: basic, fixed, fixed-fill, fixed-gradient, fixed-fill-blur
showTitle = false
[footer]
showMenu = true
showCopyright = true
showThemeAttribution = true
showAppearanceSwitcher = false
showScrollToTop = true
[homepage]
layout = "page"
homepageImage = "" # image de fond
logo = "inov_logo-bg-free.png" # logo centré
showRecent = false
layoutBackgroundBlur = false
disableHeroImageFilter = true
[page]
showHero = false
heroStyle = "background"
[article]
showDate = false
showViews = false
showLikes = false
showDateOnlyInArticle = false
showDateUpdated = false
showAuthor = false
# showAuthorBottom = false
showHero = false
heroStyle = "background"
layoutBackgroundBlur = true # only used when heroStyle equals background or thumbAndBackground
layoutBackgroundHeaderSpace = true # only used when heroStyle equals background
showBreadcrumbs = false
showDraftLabel = true
showEdit = false
# editURL = "https://github.com/username/repo/"
editAppendPath = true
seriesOpened = false
showHeadingAnchors = false
showPagination = false
invertPagination = false
showReadingTime = false
showTableOfContents = false
# showRelatedContent = false
# relatedContentLimit = 3
showTaxonomies = false # use showTaxonomies OR showCategoryOnly, not both
showCategoryOnly = false # use showTaxonomies OR showCategoryOnly, not both
showAuthorsBadges = false
showWordCount = false
# sharingLinks = [ "linkedin", "twitter", "bluesky", "mastodon", "reddit", "pinterest", "facebook", "email", "whatsapp", "telegram", "line"]
showZenMode = false
[list]
showHero = false
# heroStyle = "background" # valid options: basic, big, background, thumbAndBackground
layoutBackgroundBlur = true # only used when heroStyle equals background or thumbAndBackground
layoutBackgroundHeaderSpace = true # only used when heroStyle equals background
showBreadcrumbs = false
showSummary = false
showViews = false
showLikes = false
showTableOfContents = false
showCards = false
orderByWeight = false
groupByYear = false
cardView = false
cardViewScreenWidth = false
constrainItemsWidth = false
[sitemap]
excludedKinds = ["taxonomy", "term"]
[taxonomy]
showTermCount = true
showHero = false
# heroStyle = "background" # valid options: basic, big, background, thumbAndBackground
showBreadcrumbs = false
showViews = false
showLikes = false
showTableOfContents = false
cardView = false
[term]
showHero = false
# heroStyle = "background" # valid options: basic, big, background, thumbAndBackground
showBreadcrumbs = false
showViews = false
showLikes = false
showTableOfContents = true
groupByYear = false
cardView = false
cardViewScreenWidth = false
[firebase]
# apiKey = "XXXXXX"
# authDomain = "XXXXXX"
# projectId = "XXXXXX"
# storageBucket = "XXXXXX"
# messagingSenderId = "XXXXXX"
# appId = "XXXXXX"
# measurementId = "XXXXXX"
[fathomAnalytics]
# site = "ABC12345"
# domain = "llama.yoursite.com"
[umamiAnalytics]
# websiteid = "ABC12345"
# domain = "llama.yoursite.com"
# dataDomains = "yoursite.com,yoursite2.com"
# scriptName = ""
# enableTrackEvent = true
[selineAnalytics]
# token = "XXXXXX"
# enableTrackEvent = true
[buymeacoffee]
# identifier = ""
# globalWidget = true
# globalWidgetMessage = "Hello"
# globalWidgetColor = "#FFDD00"
# globalWidgetPosition = "right"
[verification]
# google = ""
# bing = ""
# pinterest = ""
# yandex = ""
# fediverse = ""
[rssnext]
# feedId = ""
# userId = ""
[advertisement]
# adsense = ""
preact-contact-script.html
contact-modular-forms.html
{{ partial “preact-contact-script.html” . }}
custom.css
@import “./contact.css”;
/* Élargir les zones de contenu Blowfish */
.prose,
.container,
.max-w-prose,
.max-w-3xl {
max-width: 1200px !important;
}
/* Centrer proprement */
.prose,
.container {
margin-left: auto !important;
margin-right: auto !important;
}
/* Ajouter un padding horizontal pour éviter que le texte touche les bords */
.prose,
.container {
padding-left: 1.5rem;
padding-right: 1.5rem;
}
/* Corriger la hiérarchie des titres dans Blowfish /
.prose h2 {
font-size: 2rem !important; / 32px */
font-weight: 700 !important;
}
.prose h3 {
font-size: 1.5rem !important; /* 24px */
font-weight: 600 !important;
}
/* Agrandir les paragraphes /
.prose p, li {
font-size: 1.25rem !important; / 19.2px */
line-height: 1.75 !important;
color: rgba(var(–color-neutral-500), 1);
}
/* Agrandir les légendes des images /
.prose figcaption {
font-size: 1.05rem !important; / 16.8px */
line-height: 1.5 !important;
color: #444 !important;
text-align: center !important;
margin-top: 0.5rem !important;
}
.main-menu {
position: sticky;
top: 0;
z-index: 1000;
background-color: white;
}
.contact-form {
border: none !important;
box-shadow: none !important;
}
/* .contact-button {
width: 100%;
background-color: #2563eb;
color: #ffffff;
padding: 0.75rem 1rem;
border-radius: 0.5rem;
font-weight: 600;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
border: none;
cursor: pointer;
transition: background-color 150ms ease, transform 150ms ease;
}
.contact-button:hover {
background-color: #1d4ed8;
}
.contact-button:focus {
outline: 2px solid #2563eb;
outline-offset: 2px;
} */
/* Taille du label /
.contact-label {
display: inline-block;
font-weight: 500;
font-size: 1.125rem; / text-lg */
margin-bottom: 0.5rem;
}
@media (min-width: 1024px) {
.contact-label {
font-size: 1.25rem; /* text-xl */
margin-bottom: 1.25rem;
}
}
/* Astérisque rouge /
.contact-label-required {
margin-left: 0.25rem;
color: #dc2626; / red-600 */
}
@media (prefers-color-scheme: dark) {
.contact-label-required {
color: #f87171; /* red-400 */
}
}
/* Couleur inversée /
.contact-title {
font-size: 1.5rem; / text-2xl /
color: #e2e8f0; / slate-200 */
margin-bottom: 1rem;
font-weight: 600;
}
@media (prefers-color-scheme: dark) {
.contact-title {
color: #0f172a; /* slate-900 */
}
}
/* Responsiveness identique à ton exemple /
@media (min-width: 768px) {
.contact-title {
font-size: 1.875rem; / md:text-3xl */
}
}
@media (min-width: 1024px) {
.contact-title {
font-size: 2.25rem; /* lg:text-4xl */
}
}
/* Style de base des inputs /
.contact-input {
width: 100%;
padding: 0.75rem 1rem;
border: 2px solid #475569; / slate-600 : gris sombre */
border-radius: 0.75rem;
background: white;
transition: border-color 150ms ease;
}
/* Effet hover sombre (comme ModularForms mais inversé) /
.contact-input:hover {
border-color: #334155; / slate-700 : encore plus sombre */
}
contact.css
.contact-button {
width: 100%;
background-color: #2563eb; /* bleu */
color: #ffffff;
padding: 0.75rem 1rem;
border-radius: 0.5rem;
font-weight: 600;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
border: none;
cursor: pointer;
transition: background-color 150ms ease, transform 150ms ease;
}
.contact-button:hover {
background-color: #1d4ed8; /* bleu plus foncé */
}
.contact-button:focus {
outline: 2px solid #2563eb;
outline-offset: 2px;
}
Versions used
- Hugo: v0.152.2
- Blowfish: v2.93.0
- React:19.2.3
- NPM: 11.6.2
- Tailwind: 4.1.18
So, I need a clean way to:
- Load additional CSS files from assets/css/
OR - Enable Tailwind globally so Modular Forms components render correctly
OR - Integrate Preact + Tailwind in a way that works with Hugo and Blowfish
Answer me as soon as possible please, it’s for an important work.