Exploring Hugo Framework - Part 2: Advanced Implementations
Exploring Hugo Framework - Part 2
What are other ways of hugo implementation for my project?
In Hugo, Modules are the modern, recommended way to manage themes, dependencies, and reusable components. However, there are several other ways to implement and structure Hugo websites, depending on your project goals, complexity, and need for maintainability.
Here’s a breakdown of Hugo implementation approaches apart from Modules:
1. Standalone Theme Folder
- What: Download or clone a theme directly into the
/themes/
folder. - Use case: Simple static sites that don’t need updates or external component sharing.
- Pros: Easy to set up, no need for Go tooling or internet access after download.
- Cons: Harder to update and share components across multiple projects.
2. Git Submodule for Theme
- What: Add a theme as a Git submodule in the
/themes/
directory. -
Command:
git submodule add https://github.com/<theme-repo> themes/<theme-name>
- Use case: When you want to track a remote theme repo but don’t use Hugo Modules.
- Pros: Keeps theme updated with Git; better than copy-paste.
- Cons: Submodules can be tricky to manage; not as flexible as Hugo Modules.
3. Monorepo with Multiple Hugo Sites
- What: A single Git repo contains multiple Hugo sites or content sets, often for large documentation sites.
- Use case: Organizations managing multiple brands/sites in one repo.
- Pros: Centralized version control.
- Cons: Can get messy without clear structure.
4. Copy-Paste Theme (Manual Integration)
- What: Copy theme files directly into your project’s
/layouts
,/static
, etc. - Use case: When you want full control and don’t plan to update the theme.
- Pros: Maximum customization.
- Cons: No future updates from original theme, higher maintenance.
5. Custom-Built from Scratch
- What: Create your own layouts, partials, and assets without using a theme.
- Use case: Full design control or learning Hugo deeply.
- Pros: Tailored to your needs.
- Cons: Time-consuming; you have to build everything.
6. Headless Content Repository
- What: Use Hugo as a headless CMS backend, generating JSON/HTML content for use in another front-end.
- Use case: Sites that use Hugo to generate API-like endpoints (e.g., for a React frontend).
- Pros: Hugo’s speed + separation of concerns.
- Cons: Requires front-end integration.
7. Scripted Builds with Makefile or Shell Scripts
- What: Use scripts to automate builds, configuration changes, deployment, etc.
- Use case: CI/CD pipelines, complex setups.
- Pros: Full automation.
- Cons: Adds devops complexity.
Summary Table
Approach | Best For | Auto Updates | Easy Setup | Modular |
---|---|---|---|---|
Standalone Theme Folder | Simple personal sites | ❌ | ✅ | ❌ |
Git Submodule Theme | Mid-level sites needing updates | ✅ | ⚠️ | ❌ |
Hugo Modules | Professional, modular sites | ✅ | ⚠️ | ✅ |
Manual Theme Copy | Custom heavy sites | ❌ | ✅ | ❌ |
From Scratch | Learning, custom design | N/A | ❌ | ✅ |
Headless Output | Front-end apps (e.g., React) | N/A | ❌ | ✅ |
Scripted CI/CD | Team workflows | N/A | ❌ | ✅ |
Can I use multiple themes in my Hugo Project?
I am planning Hugo modules way. If I use a theme say docsy and I like some shortcode from other theme then I can I use it simply copying that shortcode in shortcode folder?
Yes, you can absolutely copy a shortcode from another theme and use it in your Hugo project — even if you’re using the Hugo Modules approach with Docsy. Here’s how to do it safely and effectively:
✅ How to Use a Shortcode from Another Theme in a Hugo Modules Project
1. Locate the shortcode
Find the *.html
shortcode file in the layouts/shortcodes/
folder of the other theme.
2. Copy it to your project
Place it in your own project’s layouts/shortcodes/
directory:
your-hugo-site/
├── layouts/
│ └── shortcodes/
│ └── myshortcode.html
Hugo prioritizes your local
layouts/
folder over the theme’s modules, so this works perfectly.
3. Use the shortcode in content
You can now use it like any regular shortcode:
🔄 Alternative: Import the Theme as a Hugo Module Too
If you want to use many components (shortcodes, partials, assets) from another theme, consider adding it as a second Hugo module.
Steps:
- Add the module in your
config.toml
orconfig.yaml
:
[module]
[[module.imports]]
path = "github.com/google/docsy"
[[module.imports]]
path = "github.com/theother/theme"
- Hugo will merge layouts from both themes.
- You can override specific shortcodes by adding them to your local
layouts/shortcodes/
.
⚠️ Notes & Gotchas
- If the shortcode depends on other theme partials, CSS, or JS, you might need to copy or adapt those too.
- Check for custom
.Site.Params
used in the shortcode and define them in your ownconfig.toml
. - If the shortcode uses assets (like images, icons, or JS libraries), ensure those are also available in
assets/
orstatic/
.
How multiple these are handle in Hugo project?
If I import multiple modules then theme directory will have multiple folder? When I am using those shortcode then how to handle the path of those shortcodes?
🧩 1. Do Multiple Hugo Modules Create Multiple Folders in themes/
?
No — if you’re using Hugo Modules properly, you don’t need to use the themes/
folder at all.
Instead, Hugo handles everything under the hood by cloning/importing the modules into the hugo_cache
directory (usually inside $HOME/.cache
or your project directory under resources/
).
So:
- You don’t see multiple folders inside
/themes/
. - Instead, you define them in your
config.toml
orconfig.yaml
.
📦 Example: config.toml
with Multiple Modules
[module]
[[module.imports]]
path = "github.com/google/docsy"
[[module.imports]]
path = "github.com/theother/theme"
No need to manually place anything in themes/
.
⚙️ 2. How Does Hugo Resolve Shortcodes from Multiple Modules?
Hugo looks for shortcodes in the following order of precedence:
layouts/shortcodes/
in your project root — 🥇 highest priority.layouts/shortcodes/
in the first imported module.- Then, it checks the next imported module, and so on.
So:
- If two modules have a
gallery.html
shortcode, the one from the module listed first in yourconfig.toml
will be used. - If you place
gallery.html
in your ownlayouts/shortcodes/
, it will override all others.
🧠 3. How to Use a Shortcode from a Specific Module?
You cannot directly call a shortcode from a specific module by path like:
❌ not supported
Instead, you do this:
- Ensure the shortcode has a unique name (e.g.,
card-docsy.html
,card-papermod.html
). - Then use it by that name:
Alternatively, if there’s a name clash (e.g., both modules have alert.html
), and you want both:
🛠️ Option A: Copy and Rename the Shortcode
- Copy one version of
alert.html
from the module repo to your locallayouts/shortcodes/alert-docsy.html
. - Rename and use it like this:
This is a Docsy alert.
✅ Summary
Question | Answer |
---|---|
Multiple modules = multiple theme folders? | ❌ No. Modules are managed by Hugo internally. |
Can I use shortcodes from all modules? | ✅ Yes, based on order and uniqueness. |
How do I control which one is used? | 🥇 Put the desired one earlier in config.toml , or copy+rename it locally. |
Can I call a shortcode by module path? | ❌ No. Only by shortcode name. Ensure names don’t clash. |
What is use of ‘hugo mod vendor’ command?
There is some concept of hugo mod vendor, will that physically import those theme folder? Is that a good practice?
Yes, you’re absolutely right — hugo mod vendor
is a command in Hugo Modules that physically downloads the imported module code (like themes or components) into a local ./vendor
directory within your project.
🧩 What Is hugo mod vendor
?
hugo mod vendor
This command copies all currently used Hugo modules (themes, components, etc.) into a local vendor/
folder inside your project. It’s Hugo’s way of “vendoring” external dependencies — similar to npm install
in Node.js or go mod vendor
in Go.
📁 What Happens After Running It?
Your project will have:
your-hugo-site/
├── vendor/
│ └── github.com/
│ └── google/
│ └── docsy/
│ └── layouts/
│ └── assets/
│ └── ...
✅ Why Use hugo mod vendor
?
Benefit | Explanation |
---|---|
✅ Offline builds | No internet needed once vendored. Ideal for CI/CD pipelines or air-gapped environments. |
✅ Lock dependencies | Ensures consistent builds even if upstream module changes. |
✅ Version control | You can commit vendor/ if you want to fully lock dependencies for collaboration. |
❌ When NOT to Use It
Concern | Why |
---|---|
❌ Active theme development | You lose the auto-update benefit. If the upstream theme updates, you must re-vendor. |
❌ Unnecessary commits | Vendoring adds a lot of files; can bloat your Git repo unless .gitignore d or handled carefully. |
❌ Beginners/experiments | If you’re still exploring themes or modules, vendoring adds friction. |
🎯 Best Practice Recommendation
Use Case | Should You Vendor? |
---|---|
✅ Production build in CI/CD | Yes — to ensure reproducibility |
✅ Air-gapped or offline builds | Yes |
❌ You’re testing themes | No — use dynamic (non-vendored) modules |
✅ You want full control over theme source code | Yes — vendor, then customize |
❌ You want auto updates from remote repo | No — vendoring freezes the state |
🔁 How to Update a Vendored Module
You must:
- Delete or update the
vendor/
folder. - Run:
hugo mod get -u
hugo mod tidy
hugo mod vendor
✍️ Summary
Command | Purpose |
---|---|
hugo mod vendor |
Physically copies modules to vendor/ |
hugo mod get -u |
Updates module versions |
hugo mod tidy |
Cleans up unused module imports |
Can you give example how to import mulitple themes in Hugo?
Here’s a complete working example of how to use Hugo Modules with two themes (like Docsy + another one), how to vendor them, and how to control whether or not you commit the vendor/
folder.
✅ 1. config.toml
– Importing Docsy + Another Module
baseURL = "https://example.com/"
languageCode = "en-us"
title = "My Hugo Site"
theme = "docsy" # Only used for legacy fallback. Optional with Hugo Modules.
[module]
proxy = "direct"
vendor = "vendor"
[[module.imports]]
path = "github.com/google/docsy"
disable = false
[[module.imports]]
path = "github.com/someauthor/other-theme"
disable = false
You can add more modules in this list.
📦 2. Run These Commands
First-time setup:
hugo mod tidy
To vendor all modules locally:
hugo mod vendor
This will generate:
your-hugo-site/
├── vendor/
│ └── github.com/
│ ├── google/docsy/
│ └── someauthor/other-theme/
🔁 3. Updating Module Versions Later
hugo mod get -u
hugo mod tidy
hugo mod vendor
This updates the modules and re-vendors them.
🔒 4. Git Ignore or Commit Vendor?
Option A: Ignore it (default recommendation)
.gitignore
/vendor/
/resources/_gen/
/public/
You rely on Hugo to download modules fresh each time.
Option B: Commit it (for reproducible CI builds or air-gapped machines)
- Do not add
/vendor/
to.gitignore
. - Commit the entire folder.
-
Recommended when:
- You have strict version locking needs.
- You need the site to build without internet access.
🔁 5. Regenerate go.sum
if needed
Sometimes after pulling a new repo or changing config.toml
, run:
hugo mod tidy
This fixes inconsistencies and removes unused module references.
✅ Summary
Action | Command |
---|---|
Download & cache modules | hugo mod tidy |
Vendor modules into project | hugo mod vendor |
Update module versions | hugo mod get -u |
Cleanup unused modules | hugo mod tidy again |
What are different hugo commands?
Even if you don’t use hugo mod vendor
, the following commands are still essential for managing Hugo modules (themes, components, etc.):
🔁 hugo mod tidy
- Purpose: Cleans up your module metadata.
-
Does:
- Removes unused module imports.
- Ensures
go.mod
andgo.sum
are up-to-date. - Downloads any missing modules into the Hugo module cache (not the
vendor/
folder).
📌 Use this regularly, especially:
- After modifying
config.toml
’s module section. - After pulling someone else’s repo.
⬆️ hugo mod get -u
- Purpose: Updates all modules to their latest versions (unless version-pinned).
- Like
go get -u
in Go. - Updates module references in
.hugo.toml
/go.mod
(depending on Hugo version).
🔄 Combine with:
hugo mod get -u
hugo mod tidy
To update + clean.
💡 Summary: Command Roles (with or without vendor/
)
Command | Updates Cache? | Affects vendor/ ? |
When to Use |
---|---|---|---|
hugo mod tidy |
✅ Yes | ❌ No | After changing config.toml or cloning a repo |
hugo mod get -u |
✅ Yes | ❌ No | To fetch newer versions of imported modules |
hugo mod vendor |
❌ No | ✅ Yes | To copy current modules to vendor/ for offline or locked builds |
How to customize your theme?
If I customize some layout or shortcode or partial then I should keep that in my project’s layout folder and even if theme is updated it will not effect my project. Am I right?
✅ Yes, you are absolutely right. That’s exactly how Hugo’s layout resolution system works — and it’s one of Hugo’s greatest strengths.
📂 Layout Override System in Hugo
When Hugo builds your site, it looks for templates (layouts, shortcodes, partials, etc.) in this order of priority:
- Your project’s
layouts/
folder ✅ (highest priority — always preferred if present) - Then each imported module’s
layouts/
folder, in the order they appear in yourconfig.toml
.
So:
➕ If you customize:
layouts/_default/single.html
layouts/partials/header.html
layouts/shortcodes/card.html
…inside your project folder, Hugo will use your version even if the theme/module also has one with the same name.
✨ Why This Is Awesome
Advantage | Explanation |
---|---|
✅ Safe from updates | Theme or module updates won’t affect your customizations. |
✅ Clean separation | You don’t have to fork the theme or touch its source code. |
✅ Easy to revert | Just delete or rename your custom file to fall back to the theme’s version. |
✅ Supports fine-grained overrides | You can override only what you need — not entire layout trees. |
👩🔧 Example
Suppose you’re using Docsy as a Hugo module and you want to customize the header.
- Create this in your project:
layouts/partials/header.html
- Add your changes there.
Even if Docsy later updates its partials/header.html
, your custom file takes precedence and remains unaffected.
🛡️ Bonus Tip: Version Control
Keep your custom layout files under Git so you can easily track what you’ve overridden and why.
✅ Summary
Change | Effect |
---|---|
Add layout/partial/shortcode in your project | ✅ Overrides theme/module |
Theme gets updated | ❌ No impact on your overridden files |
Delete your custom file | 🔁 Falls back to theme’s version |
How to use boostrap (css) or javascript libraries in my project?
If I want to use some javascript library or bootstrap css or tailwind css in my project’s front matter or partial then how to do that? What are different ways?
In Hugo, you have multiple ways to include and use JavaScript libraries, Bootstrap, Tailwind CSS, or any other frontend asset — either via CDN, local assets, or using Hugo Pipes for advanced processing.
Let’s break it down clearly:
✅ 1. Using CDN (simplest method)
Add external libraries like Bootstrap, Tailwind, Alpine.js, etc. using a <script>
or <link>
in your layouts/partials/head.html
or directly in baseof.html
.
Example for Bootstrap (CDN):
<!-- In layouts/partials/head.html -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
Tailwind via CDN (only suitable for prototypes):
<script src="https://cdn.tailwindcss.com"></script>
✅ Pros: Easy and fast ❌ Cons: No customization, slower than local, can’t tree-shake unused CSS
✅ 2. Using Local Assets (Static Folder)
You can download and place .css
, .js
, fonts, etc. inside the static/
directory.
File structure:
static/
├── css/bootstrap.min.css
├── js/bootstrap.bundle.min.js
In head.html
or your partial:
<link href="/css/bootstrap.min.css" rel="stylesheet">
<script src="/js/bootstrap.bundle.min.js"></script>
These files are copied as-is to the root of the final site (
/public
) during build.
✅ 3. Using Hugo Pipes for SCSS/SASS (for Bootstrap or Tailwind)
If you want custom theming, minification, PostCSS, or Tailwind JIT, use Hugo Pipes.
Example: Custom Bootstrap with SCSS
- Place Bootstrap’s SCSS files in
assets/scss/bootstrap/
- Create
assets/scss/main.scss
:
@import "bootstrap/bootstrap";
- In
head.html
:
<link rel="stylesheet" href="">
For Tailwind (with PostCSS):
You’ll need:
postcss.config.js
tailwind.config.js
assets/css/styles.css
with Tailwind directives:
@tailwind base;
@tailwind components;
@tailwind utilities;
- Add in
head.html
:
<link rel="stylesheet" href="">
✅ Pros: Tree-shaking, fast, production-ready ❌ Cons: Needs setup of
postcss
,tailwind.config.js
,npm
✅ 4. Theme-Specific Integration
Some Hugo themes (like Docsy) have their own way of injecting scripts and styles.
- Check if
partials/head.html
,partials/scripts.html
, orassets/js/
is present. - Use built-in
block
anddefine
templates to inject custom code.
Example (baseof.html
):
Your layout:
<script src="/js/mylib.js"></script>
✅ Summary Table
Method | Use Case | Pros | Cons |
---|---|---|---|
CDN | Quick prototyping | Easy, no build tools | No customization, external dependency |
Static assets | Simple sites | Fast, controlled | No processing (minify, purge) |
Hugo Pipes + SCSS/Tailwind | Advanced production | Tree-shaking, JIT, theme customization | Needs setup (postcss , npm ) |
Theme override (partials/blocks) | Custom themes like Docsy | Works with theme’s structure | Slightly complex |
What is postCSS? What are other similar related concepts?
Understanding PostCSS and its ecosystem is essential for modern frontend development, especially when working with Hugo + Tailwind or other CSS tooling.
🔧 What is PostCSS?
PostCSS is a tool for transforming CSS using JavaScript plugins.
- It’s not a CSS framework (like Tailwind or Bootstrap).
- It’s a processor — like a compiler for CSS — that takes your CSS and modifies it using a chain of plugins.
🧠 Think of it as a pipeline: Write CSS → Process with PostCSS plugins → Output optimized CSS.
🛠️ What Can PostCSS Do?
PostCSS itself does nothing unless you configure it with plugins. Some popular PostCSS plugins:
Plugin | Purpose |
---|---|
autoprefixer |
Adds browser vendor prefixes (-webkit- , -moz- , etc.) |
tailwindcss |
Enables Tailwind’s utility-based framework |
postcss-import |
Allows @import syntax to work like ES Modules |
cssnano |
Minifies and optimizes CSS for production |
postcss-nested |
Allows nesting CSS like SCSS |
🔄 How PostCSS Fits into Hugo (via Hugo Pipes)
In a Hugo project, you can use PostCSS via resources.Get
+ postCSS
:
✅ Example:
<link rel="stylesheet" href="">
You need to set up a postcss.config.js
like:
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
📦 Related Concepts
Term | Role | Example | ||
---|---|---|---|---|
SCSS/SASS | CSS preprocessor (adds variables, nesting, mixins) | @import , $primary-color |
||
Hugo Pipes | Hugo’s asset pipeline that can process SCSS, JS, images, etc. | `resources.Get | toCSS | minify` | ||
Tailwind CSS | Utility-first CSS framework built on PostCSS | @tailwind utilities |
||
Autoprefixer | PostCSS plugin to add vendor prefixes | display: flex; → -webkit-box , -ms-flexbox , etc. |
||
CSS Modules | Scope styles to components (used in React, Vue, etc.) | .button {} → .button_xyz123 |
||
Webpack/Vite/Rollup | Build tools that often include PostCSS as part of their pipeline | Used in large JS projects |
✅ When to Use PostCSS in Hugo?
You should consider using PostCSS if:
- You use Tailwind CSS.
- You want Autoprefixer or CSS minification.
- You want advanced CSS transformations without switching to SCSS.
⚡ Bonus Tip: Hugo Auto-detects PostCSS
If you have:
postcss
installed (npm install postcss autoprefixer
)postcss.config.js
in your root
Then postCSS
processing in Hugo will just work.
What are important tags which are used in <head>
tag?
To include CSS and JavaScript in HTML…
Purpose | Tag | Example | Placement |
---|---|---|---|
CSS (stylesheet) | <link rel="stylesheet"> |
<link rel="stylesheet" href="/css/main.css"> |
Usually in <head> |
JavaScript | <script src="..."></script> |
<script src="/js/app.js"></script> |
Usually at the end of <body> or in <head> with defer |
🚀 Why JS usually goes at the end of <body>
?
- To prevent render-blocking — JavaScript can slow down page load if placed in
<head>
withoutdefer
orasync
.
🧠 2. Other common <head>
elements
The <head>
tag is where you include metadata and resources needed before rendering. Key tags:
Tag | Purpose |
---|---|
<meta charset="UTF-8"> |
Define character encoding |
<meta name="viewport"> |
Responsive design for mobile |
<title> |
Page title (shown in browser tab) |
<meta name="description"> |
SEO meta description |
<meta property="og:title"> |
Open Graph for social previews |
<meta name="robots" content="index,follow"> |
Search engine behavior |
<link rel="icon" href="/favicon.ico"> |
Website icon |
<link rel="manifest"> |
Progressive Web App manifest |
<link rel="canonical"> |
SEO canonical URL |
<link rel="preconnect"> |
Performance: hint to browser to preconnect to a domain |
<link rel="dns-prefetch"> |
DNS resolution in advance |
🎯 3. <link>
Tag: More Than Just CSS
The <link>
tag has many other uses besides linking stylesheets:
Example | Usage |
---|---|
<link rel="stylesheet" href="style.css"> |
CSS |
<link rel="icon" href="favicon.ico"> |
Favicon |
<link rel="manifest" href="/site.webmanifest"> |
PWA manifest |
<link rel="alternate" hreflang="fr" href="/fr/"> |
Language/region alternatives |
<link rel="canonical" href="https://example.com/page"> |
SEO canonical URL |
<link rel="preload" as="font" href="font.woff2" type="font/woff2" crossorigin> |
Performance: preload font |
<link rel="modulepreload" href="main.js"> |
Preload ES modules |
<link rel="dns-prefetch" href="//cdn.example.com"> |
Performance: DNS prefetch |
<link rel="preconnect" href="//cdn.example.com"> |
Performance: open early TCP connections |
🔄 Summary
Task | Tag | Where |
---|---|---|
Load CSS | <link rel="stylesheet"> |
<head> |
Load JS | <script src="..."> |
<body> (or <head> with defer ) |
Add metadata | <meta> |
<head> |
Add favicon / manifest / SEO info | <link> / <meta> |
<head> |
How to use node.js modules in Hugo project?
To use a Node.js module installed via npm install
in a Hugo project, you need to distinguish between frontend usage (browser) and backend/build-time usage (like PostCSS, Tailwind, or Hugo Pipes).
🧭 First, clarify:
Are you trying to:
- Use a Node.js package like TailwindCSS, Autoprefixer, etc. to build your CSS? → This is build-time usage.
- Use a frontend JavaScript module (like lodash, moment.js, etc.) in the browser? → This is runtime (browser) usage.
I’ll explain both cases.
✅ 1. Use Node.js modules in the build pipeline (e.g., PostCSS, Tailwind)
You typically:
- Install modules with
npm install tailwindcss postcss autoprefixer
- Create a
postcss.config.js
file - Reference them in Hugo using
resources.Get
andpostCSS
Example Hugo usage:
<link rel="stylesheet" href="">
✅ 2. Use frontend modules in the browser (like lodash
, axios
, etc.)
Option A: Use a CDN version
Simplest way — no bundler needed.
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
<script>
console.log(_.chunk([1,2,3,4], 2));
</script>
Option B: Bundle it using a tool like esbuild or Vite
If you want to use import
/require
from npm packages in your JS, you need to bundle them first.
Steps:
-
Install the module:
npm install lodash
-
Create your custom JS file (e.g.,
assets/js/app.js
):import _ from 'lodash'; console.log(_.chunk([1, 2, 3, 4], 2));
-
Bundle it using esbuild or Vite: Example with esbuild:
npx esbuild assets/js/app.js --bundle --outfile=static/js/bundle.js --minify
-
Link the bundled file in Hugo:
<script src="/js/bundle.js"></script>
Summary Table
Goal | Tools | What to Do |
---|---|---|
Use Tailwind, PostCSS | postcss , tailwindcss |
Use Hugo Pipes + PostCSS |
Use browser-side libraries like lodash |
esbuild , vite , or CDN |
Bundle and link in <script> |
Use Hugo and Node tools together | Hugo, Node, npm | Keep Hugo as static site engine, Node as asset pipeline |
How to use defer in javascript? Is it different from async?
defer
and async
are two different attributes used in the <script>
tag to control how and when JavaScript is loaded and executed in the browser — especially useful for performance tuning.
✅ Basic Syntax
<script src="script.js" defer></script>
<script src="script.js" async></script>
📊 defer vs async: The Key Differences
Feature | defer |
async |
---|---|---|
Download | Non-blocking | Non-blocking |
Execution order | Preserved (in order of appearance) | Not preserved (executes when ready) |
Execution time | After HTML is parsed | As soon as it’s downloaded |
DOM Ready Dependency | Executes after DOM is built | May execute before DOM is ready |
Best for | Scripts that rely on DOM (document.getElementById , etc.) |
Independent or analytics scripts |
✅ When to Use defer
Use defer
when:
- Your JS manipulates or depends on DOM elements
- You want to include multiple scripts in order (e.g., jQuery, then plugins)
<script src="/js/jquery.js" defer></script>
<script src="/js/app.js" defer></script>
🔐 Deferred scripts wait until the full HTML is parsed, then run in order.
✅ When to Use async
Use async
when:
- The script is independent (e.g., Google Analytics, ads)
- You don’t care when it runs or its order
<script src="https://www.googletagmanager.com/gtag/js" async></script>
⚡ Async scripts run as soon as they are downloaded — no guarantee about order.
❌ No defer
or async
If you omit both, the browser:
- Stops parsing HTML
- Downloads and executes the script immediately
- Then continues parsing the rest
This blocks page rendering — bad for performance.
🎯 Summary
Use Case | Attribute |
---|---|
DOM-dependent script | defer |
Independent/3rd-party script | async |
Critical inline or blocking script | Neither (but use sparingly) |
If I want to use typescript in place of javascript, in my hugo project, then what to do?
To use TypeScript in a Hugo project (which is static and doesn’t support TS natively), you’ll need a build tool like esbuild, Vite, or Webpack to compile your .ts
files into browser-compatible .js
.
✅ Minimal Setup Using esbuild
(Recommended for Hugo)
🔧 1. Install Node.js and esbuild
npm init -y
npm install --save-dev esbuild
📁 2. Create Your Project Structure
your-hugo-site/
├── assets/
│ └── ts/
│ └── main.ts <-- TypeScript source
├── static/
│ └── js/
│ └── (generated JS) <-- Bundled output here
├── package.json
├── build.js <-- esbuild config
└── ... (Hugo stuff)
🧱 3. Write Your TypeScript (assets/ts/main.ts
)
const message: string = "Hello from TypeScript!";
console.log(message);
⚙️ 4. Create build.js
(esbuild bundler script)
const esbuild = require("esbuild");
esbuild.build({
entryPoints: ["assets/ts/main.ts"],
bundle: true,
minify: true,
sourcemap: true,
outfile: "static/js/bundle.js",
target: ["es2020"],
}).catch(() => process.exit(1));
🚀 5. Add a Build Script in package.json
"scripts": {
"build": "node build.js"
}
Then run:
npm run build
This compiles TypeScript into a single static/js/bundle.js
.
🧩 6. Include in Hugo Template (e.g., in layouts/partials/scripts.html
)
<script src="/js/bundle.js" defer></script>
And include that partial in your baseof.html
or page template:
✅ Optional: Use Vite (for Hot Reloading + Dev Server)
If you’re building a more interactive frontend (e.g., React or Vue in Hugo), Vite is better than raw esbuild.
🧠 Recap
Task | Tool |
---|---|
Compile .ts → .js |
esbuild or Vite |
Reference output in HTML | <script src="/js/bundle.js" defer> |
Watch and rebuild | npm run build -- --watch or Vite dev server |
Can you help me understanding relationship between React, Hugo, Vue, Esbuild, Vite?
- How Hugo and React are connect? Both are different platforms, one for SSG and another for Dynamic.
- How come Vite is related to typescript, esbuild and react?
Here we are touching on some advanced but important architectural ideas when combining static site generators like Hugo with modern frontend tooling like React, TypeScript, and Vite.
Let’s break this down clearly:
✅ 1. How Hugo and React can work together
You’re right:
- Hugo is a static site generator (SSG) — it renders content at build time.
- React is a frontend library for dynamic content rendered at runtime (in the browser).
They serve different purposes. But they can be used together in a few common patterns:
🔹 Pattern A: Use React Components Inside Hugo Pages
You can write React components, bundle them using a tool like Vite, and embed them in your Hugo templates via a <div id="react-root"></div>
and <script src="/js/bundle.js"></script>
.
👉 Hugo delivers the page. 👉 React takes over specific parts of the page.
💡 Think of it like: “Hugo handles the static shell; React makes certain parts dynamic.”
🔹 Pattern B: Use Hugo for marketing pages, React for apps
Sometimes people keep the Hugo site and React app separate, then:
- Host React app under a subdirectory (e.g.,
/app
) - Or embed it in an iframe or section inside a Hugo page
✅ 2. How Vite is related to TypeScript, esbuild, and React
🔸 Vite is a frontend build tool, like Webpack — but much faster.
Here’s how it relates:
Technology | Role |
---|---|
TypeScript | Language — compiled to JavaScript |
esbuild | A fast bundler/compiler (used internally by Vite) |
React | A UI library |
Vite | A dev server + build system that uses esbuild under the hood |
🔹 Vite’s Job:
- Transpile and bundle TypeScript or JSX (React syntax)
- Serve your React/TS code in development with hot module reload (HMR)
- Bundle everything for production (using esbuild + Rollup)
🔹 Example Vite + React Setup
Install:
npm create vite@latest my-app -- --template react-ts
Run:
cd my-app
npm install
npm run dev
Then you can copy the compiled JS from dist/
to your Hugo static/js/
directory or mount it with symlinks.
🧠 Summary
Stack | Role |
---|---|
Hugo | Static content and templating |
React | Dynamic interactivity on specific pages or sections |
TypeScript | Safer JS development |
esbuild | Fast JS/TS bundler used by Vite |
Vite | Dev server + bundler (modern alternative to Webpack) |
👇 Real-world Example:
You have a Hugo site for a blog or docs. You add a feedback widget using React+TypeScript. Use Vite to bundle the React widget, and Hugo injects it like this:
<div id="feedback-widget"></div>
<script src="/js/widget.js" defer></script>
React mounts on that div
, providing dynamic interactivity inside an otherwise static page.
Boilerplate code using React component inside Hugo?
Can I mix Docsy and Reveal.js themes in Hugo?
You can use reveal.js
presentations alongside your Hugo site using the Docsy theme. They serve different purposes and can coexist smoothly with a bit of setup:
✅ What is reveal.js
?
reveal.js
is a JavaScript framework for building slide decks (HTML-based presentations). It’s independent of Hugo or Docsy but can be integrated as a standalone layout or content type within your Hugo site.
✅ Integration Approaches
🔹 Option 1: Static Integration (Recommended)
Use reveal.js by directly including its assets and creating a custom Hugo layout for presentations.
📁 1. Add reveal.js assets
Download or npm-install reveal.js, and copy its dist
folder to your Hugo project:
your-hugo-site/
└── static/
└── revealjs/
├── reveal.js
├── css/
├── js/
└── plugin/
Or link to CDN versions (e.g. via unpkg) to save size.
📄 2. Create a presentation page
In content/presentations/my-talk.md
:
title: "My Reveal.js Talk"
layout: "reveal"
<section>
<h2>Welcome</h2>
<p>This is a slide</p>
</section>
<section>
<h2>Another Slide</h2>
</section>
🧱 3. Create a custom layout
In layouts/_default/reveal.html
:
<!DOCTYPE html>
<html>
<head>
<title></title>
<link rel="stylesheet" href="/revealjs/dist/reveal.css">
<link rel="stylesheet" href="/revealjs/dist/theme/black.css">
</head>
<body>
<div class="reveal">
<div class="slides">
</div>
</div>
<script src="/revealjs/dist/reveal.js"></script>
<script>
Reveal.initialize();
</script>
</body>
</html>
Then navigate to /presentations/my-talk/
to view it!
🔹 Option 2: Use a Hugo Module for Reveal.js
Some Hugo themes/modules offer reveal.js support. You could import such a module alongside Docsy via config/_default/module.toml
, but it’s usually overkill unless you’re doing lots of slides.
🔹 Option 3: Use shortcodes
to embed Reveal sections
You could create shortcodes for slides and use them inside normal Docsy pages — helpful for interactive guides or embedded decks.
🧠 Can You Mix Docsy and Reveal.js?
Yes — Docsy handles your main site layout, navigation, etc. You:
- Use reveal.js in a dedicated section/layout
- Avoid letting Docsy style or interfere with presentation pages
- Add navigation back to your Docsy site in the presentation if needed
✅ Summary
Task | Tool |
---|---|
Site structure, docs, layout | Docsy (Hugo theme) |
Presentation slides | reveal.js (JS presentation framework) |
Integration method | Custom layout or CDN assets |
Can you give me Boilerplate for using Reveal.js inside Docsy without downlowing reavel.js
Hugo Docsy and Reaval.js Implementation Boiler Code
Can you help me customizing my docsy theme?
For my hugo website I am using docsy theme. What shortcode should I use for these? If they are not available in docsy from what I can copy them?
For my website I need following features
- Mermaid enabled
- Social sharing
- Accordion for some pages
- Giscuss comment
- Gallery
- Section Specific Taxonomy
- Card type grid for my articles. I am multiple sections and I don’t want to mix there taxonomy.
- Author bio with photograph at the end of article.
- Section specific card layouts with pagination
Docsy Customization Boilerplate Code
In html sometimes I notice “role” attribute in some tags, what is the use of that?
The role
attribute in HTML is used to define the semantic purpose of an element, primarily for accessibility. It helps screen readers and other assistive technologies understand the function or type of a given element—especially when that element doesn’t have a clear native semantic meaning.
🔍 Example Use Cases
✅ 1. Landmark Roles
<header role="banner">...</header>
<nav role="navigation">...</nav>
<main role="main">...</main>
<aside role="complementary">...</aside>
<footer role="contentinfo">...</footer>
These help screen readers jump between major sections of a page.
✅ 2. Widget Roles
<div role="button" tabindex="0">Click me</div>
Used when a non-button element (like div
or span
) behaves like a button. Also requires keyboard accessibility (like tabindex
and keydown
events).
✅ 3. Dialogs, Alerts, Tabs
<div role="dialog" aria-labelledby="dialog-title">...</div>
<div role="alert">Important update!</div>
<ul role="tablist">
<li role="tab">Tab 1</li>
<li role="tab">Tab 2</li>
</ul>
⚠️ Important Notes
- If you’re already using semantic HTML (
<button>
,<nav>
,<header>
, etc.), you usually don’t needrole
—those elements come with default roles. - Only use
role
when you’re using a non-semantic element or building custom components.
What is ARIA and what are Aria roles?
Great! Here’s a concise cheatsheet of ARIA roles, along with a brief explanation of ARIA itself.
🔤 What is ARIA?
ARIA stands for Accessible Rich Internet Applications. It is a set of attributes (role
, aria-*
) used to make web content and applications more accessible to people with disabilities, especially those using screen readers or other assistive technologies.
- ARIA is essential when you’re using custom UI components (like custom dropdowns, modals, tabs) that don’t have semantic HTML equivalents.
-
ARIA includes:
- Roles (e.g.,
role="button"
) - States (e.g.,
aria-checked="true"
) - Properties (e.g.,
aria-labelledby="id"
)
- Roles (e.g.,
🧭 ARIA Role Cheatsheet
🔹 1. Landmark Roles
Help users navigate page structure.
Role | Purpose |
---|---|
banner |
Identifies site-wide header |
navigation |
Marks a navigation menu |
main |
Marks the primary content area |
complementary |
Sidebar or supportive content |
contentinfo |
Footer or copyright info |
form |
Semantic grouping of a form |
search |
Identifies a search functionality |
🔹 2. Widget Roles
Define interactive components.
Role | Purpose |
---|---|
button |
Clickable button |
link |
Interactive link |
checkbox |
Checkbox (with aria-checked ) |
dialog |
Modal window |
alert |
Urgent message (no need to be focused) |
tooltip |
Small info bubble, usually on hover/focus |
tab |
A single tab in a tab list |
tablist |
Container for a group of tabs |
tabpanel |
Content area of a selected tab |
progressbar |
Visual progress indicator |
slider |
Range control like volume/brightness |
🔹 3. Structural Roles
Used to build component structure.
Role | Purpose |
---|---|
list |
Group of related items |
listitem |
Item in a list |
table |
A data table |
row |
A row in a table |
cell |
A data cell |
grid |
Grid-like tabular structure |
🏷️ Common ARIA Attributes
Attribute | Purpose |
---|---|
aria-label="..." |
Custom label for screen readers |
aria-labelledby="id" |
Reference another element as label |
aria-hidden="true" |
Hides element from assistive tech |
aria-expanded="true" |
Indicates dropdown/accordion state |
aria-checked="true" |
For custom checkboxes/radio buttons |
aria-disabled="true" |
Marks as disabled without removing it from tab order |
✅ Best Practices
- 🧠 Prefer semantic HTML over ARIA when possible (e.g., use
<button>
instead ofdiv role="button"
). - 🔄 Keep ARIA state attributes updated via JavaScript (e.g., toggle
aria-expanded
). - 🧪 Always test with a screen reader (like NVDA, VoiceOver).
You said “Autoprefixer PostCSS plugin to add vendor prefixes display: flex; → -webkit-box, -ms-flexbox, etc.” But why do we need to to this circus around css?
What is the difference between css, scss, sass?
🧾 1. CSS (Cascading Style Sheets)
- Standard stylesheet language used in all browsers.
- Syntax is plain and rigid.
-
Example:
body { font-family: Arial; color: black; }
🌀 2. SASS (Syntactically Awesome Stylesheets)
- A CSS preprocessor that adds powerful features to CSS.
- Original version of SASS uses indentation-based syntax (no
{}
, no;
). - Requires a compiler to convert it to CSS.
- File extension:
.sass
SASS Example:
$primary-color: blue
body
font-family: Arial
color: $primary-color
✳️ 3. SCSS (Sassy CSS)
- A newer, more popular syntax for SASS.
- Fully CSS-compatible syntax (uses
{}
,;
, etc.). - File extension:
.scss
- Most widely used today because it’s easier for developers already familiar with CSS.
SCSS Example:
$primary-color: blue;
body {
font-family: Arial;
color: $primary-color;
}
🔍 Key Differences
Feature | CSS | SASS | SCSS |
---|---|---|---|
File Extension | .css |
.sass |
.scss |
Syntax Style | CSS | Indentation | CSS-like |
Variables | ❌ | ✅ | ✅ |
Nesting | ❌ | ✅ | ✅ |
Mixins, Functions | ❌ | ✅ | ✅ |
Requires Compilation | ❌ | ✅ | ✅ |
⚙️ Usage in Projects
- To use SASS/SCSS in a Hugo project, you typically write SCSS in
assets/scss/
and process it using Hugo Pipes or external tools like PostCSS or Vite. - SCSS is generally preferred over .sass because of its familiar syntax and better community support.
What is Mixin and how it is different from function?
What are different related concepts like Mixin, Extend, Function, Control Directives etc.
🔁 What is a Mixin?
A mixin lets you define reusable blocks of CSS, optionally with parameters—similar to a function in programming.
✅ Use Case:
Instead of repeating vendor prefixes for transform
everywhere, you can use a mixin.
💡 SCSS Mixin Example:
@mixin transform($value) {
-webkit-transform: $value;
-ms-transform: $value;
transform: $value;
}
.box {
@include transform(rotate(45deg));
}
Output CSS:
.box {
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
📚 Other Related SCSS Features
1. Variables
Let you store values (colors, sizes, fonts) to reuse across stylesheets.
$primary-color: #3498db;
body {
color: $primary-color;
}
2. Nesting
Helps structure CSS hierarchically, matching your HTML structure.
nav {
ul {
li {
a {
color: white;
}
}
}
}
3. Functions
Like mixins but return values (used inside properties).
@function px-to-rem($px) {
@return $px / 16 * 1rem;
}
body {
font-size: px-to-rem(18);
}
4. Inheritance (@extend
)
Shares styles from one selector to another.
%button-base {
padding: 10px;
border-radius: 5px;
}
.btn {
@extend %button-base;
background: blue;
}
%button-base
is a placeholder selector (won’t be output unless extended).
5. Control Directives (If, For, Each)
Adds logic to stylesheets.
Example: Loop
@for $i from 1 through 3 {
.col-#{$i} {
width: #{100% / $i};
}
}
🧰 Summary Table
Feature | Description | Keyword |
---|---|---|
Variables | Reusable values | $variable |
Mixins | Reusable blocks of rules | @mixin , @include |
Functions | Return single computed values | @function |
Inheritance | Share styles between selectors | @extend |
Nesting | Organize selectors inside selectors | selector {} |
Logic | Add conditional or looping logic | @if , @for , @each |
What is lodash in node js?
Lodash is a popular JavaScript utility library that provides helpful functions for common programming tasks—especially when working with arrays, objects, strings, and functions.
🔧 Why Use Lodash?
Native JavaScript has improved over time (e.g. with map
, filter
, reduce
), but Lodash fills in the gaps with:
- More consistent cross-browser behavior
- More concise syntax
- More functional-style utilities
📦 Installation
npm install lodash
Then import it in your project:
const _ = require('lodash'); // CommonJS
// or
import _ from 'lodash'; // ES Module
💡 Common Lodash Functions
Category | Example | What It Does |
---|---|---|
Array | _.chunk([1,2,3,4], 2) |
Splits array into chunks |
Array | _.uniq([1,2,2,3]) |
Removes duplicates |
Object | _.get(obj, 'a.b.c') |
Safely access nested values |
Object | _.merge(obj1, obj2) |
Deep merge objects |
Collection | _.groupBy(users, 'age') |
Groups items by key |
Function | _.debounce(fn, 300) |
Rate-limit function calls |
String | _.camelCase('Hello world') |
Converts to helloWorld |
🧠 Lodash vs Native JavaScript
Many Lodash features are now natively available (e.g. Array.map
, Set
, Object.assign
, etc.). But Lodash still shines in:
- Deep manipulation of objects
- Functional programming chains
- Debouncing/throttling
- Safer operations on deeply nested data
✅ Example Use
const _ = require('lodash');
const users = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 25 },
{ name: 'Charlie', age: 30 }
];
const grouped = _.groupBy(users, 'age');
console.log(grouped);
/*
{
25: [{...}, {...}],
30: [{...}]
}
*/
🛑 When to Avoid It?
- If your project is very lightweight or performance-critical, and you’re using only one or two Lodash features, consider using native alternatives or smaller single-function libraries like
lodash.get
.
What is vite in node js
Vite is a modern frontend build tool and development server created by Evan You (the creator of Vue.js), and it is written in Node.js. It’s designed to be faster, simpler, and more efficient than older tools like Webpack.
⚡ What Is Vite?
Vite (pronounced “veet”) means “fast” in French.
Vite focuses on two main things:
- Lightning-fast development server using native ES Modules (no bundling during dev).
- Optimized build process using esbuild or Rollup for production.
🔧 Installation
You install it using npm or yarn:
npm create vite@latest
# or
yarn create vite
Then:
cd your-project
npm install
npm run dev
🧠 Why Vite Is Fast
Feature | Description |
---|---|
🚀 Dev Server | Uses native ES Modules + esbuild under the hood for instant startup |
📦 Build | Uses Rollup for highly optimized builds |
🔁 HMR (Hot Module Replacement) | Fast updates in browser without full reload |
⚙️ Plugin Ecosystem | Compatible with Rollup plugins and supports TypeScript, Vue, React, Svelte, etc. |
🧩 Frameworks Supported
Vite works with:
- React
- Vue 3
- Svelte
- Preact
- Lit
- Vanilla JavaScript / TypeScript
📁 Typical Vite Project Structure
my-app/
├── index.html
├── package.json
├── vite.config.js
├── public/
└── src/
├── main.js / main.tsx
└── App.vue / App.tsx
🧪 Example: Vite + React
npm create vite@latest my-app --template react
cd my-app
npm install
npm run dev
vite.config.js (optional)
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()]
})
✅ Benefits of Using Vite
- ⚡ Instant server start
- 🔁 Fast HMR
- ✅ Out-of-the-box support for TS, JSX, CSS modules
- 🌐 Uses modern browser features (ES Modules)
❓Vite vs Webpack
Feature | Vite | Webpack |
---|---|---|
Dev Startup | Instant (no bundle) | Slower |
Config Needed | Minimal | Often complex |
HMR | Faster | Slower |
Plugin System | Rollup-compatible | Webpack-only |
TypeScript | Native support | Needs loader |
📦 In Summary
Vite is a modern frontend tool built with Node.js, focused on providing a super-fast dev experience and optimized production builds, especially for frameworks like React, Vue, and Svelte.
What is difference between npm and npx?
✅ What is npm
?
npm
stands for Node Package Manager. It is used to:
- Install packages (
npm install
ornpm i
) - Manage dependencies in your project
- Run scripts defined in
package.json
- Publish or update packages to the npm registry
Examples:
npm install lodash # install lodash as dependency
npm install -g nodemon # install globally
npm run dev # run "dev" script from package.json
npm update # update installed packages
🚀 What is npx
?
npx
is a tool that comes with npm
(v5.2+). It is used to run Node.js CLI tools or packages directly without installing them globally.
Why use npx
?
- Avoid global installs
- Always run the latest version
- Useful for scaffolding tools, like
create-react-app
,vite
, etc.
Examples:
npx create-react-app my-app # run without installing globally
npx vite@latest # run latest version of vite
npx eslint . # run eslint without installing it globally
Think of
npx
as: “Download → Run → Delete (if not already installed locally)”
🧪 Difference Between npm
vs npx
Feature | npm |
npx |
---|---|---|
Use case | Install or manage packages | Run CLI tools directly |
Installs globally? | Yes (with -g ) |
No (runs and discards unless used locally) |
Typical usage | npm install <pkg> |
npx <pkg> |
Permanent install? | Yes | No (unless cached or used locally) |
🧰 Other Useful npm
Commands
Command | Purpose |
---|---|
npm init / npm init -y |
Create a package.json file |
npm ls |
List installed packages |
npm outdated |
Check outdated packages |
npm uninstall <pkg> |
Remove a package |
npm config list |
Show npm configuration |
npm cache clean --force |
Clean the npm cache |
npm audit |
Security audit of dependencies |
npm ci |
Clean install for CI/CD pipelines (faster, stricter than npm install ) |
🧠 Tip: Use npx
When…
- You want to try a package once
- You’re using project-local CLI tools
- You’re using a temporary version of a package
What is tailwind?
Tailwind CSS is a utility-first CSS framework used to build modern websites rapidly by composing utility classes directly in your HTML. Instead of writing custom CSS, you use predefined classes to style elements.
✅ What Makes Tailwind Special?
Unlike traditional CSS frameworks (like Bootstrap), which offer ready-made components, Tailwind gives you low-level utility classes like:
<div class="bg-blue-500 text-white font-bold p-4 rounded-lg">
Hello, Tailwind!
</div>
🚀 Key Features
Feature | Description |
---|---|
🎯 Utility-first | Style with tiny, single-purpose classes like text-xl , p-4 , bg-gray-200 |
⚙️ Customizable | Fully configurable via tailwind.config.js |
🪄 Responsive & State Variants | Built-in support for breakpoints, hover, focus, dark mode, etc. |
💨 Fast Prototyping | No need to leave your HTML to style components |
🧼 Built-in PurgeCSS | Removes unused CSS in production for ultra-small CSS files |
🛠 Example Comparison
Traditional CSS:
/* styles.css */
.btn {
background-color: blue;
color: white;
padding: 1rem;
border-radius: 0.5rem;
}
Tailwind:
<button class="bg-blue-500 text-white py-2 px-4 rounded">Click Me</button>
📦 How to Use Tailwind
You can use Tailwind in various ways:
- CDN (Quick test, no customization):
<link href="https://cdn.tailwindcss.com" rel="stylesheet">
- With Build Tools (recommended):
npm install -D tailwindcss
npx tailwindcss init
-
With Frameworks like:
- React (Vite, Next.js)
- Vue
- Hugo (via PostCSS)
- Laravel
🔧 Tailwind Workflow (With Build Tools)
- Install Tailwind and PostCSS
- Create
tailwind.config.js
- Set up
postcss.config.js
- Include Tailwind in your CSS:
@tailwind base;
@tailwind components;
@tailwind utilities;
- Build with:
npx tailwindcss -i ./src/input.css -o ./dist/output.css --watch
🌌 Tailwind Ecosystem
- Headless UI – Unstyled accessible UI components
- Tailwind UI – Commercial set of styled components
- DaisyUI – Theme-ready component library on top of Tailwind
- Heroicons – Icon set from the creators of Tailwind
💡 When to Use Tailwind
- You want full control over styling
- You’re tired of fighting against component libraries
- You value consistency and speed in building UI
- You want responsive design and dark mode support out of the box
Can you compare tailwind vs bootstrap?
🥊 Tailwind CSS vs Bootstrap: A Detailed Comparison
Feature | Tailwind CSS | Bootstrap |
---|---|---|
Approach | Utility-first | Component-based |
Styling Method | Compose your own design with utility classes in HTML | Use pre-built components and override if needed |
Customization | Highly customizable via tailwind.config.js |
Customizable via Sass variables and themes |
Design Freedom | Very high – no design imposed | Moderate – comes with a default “Bootstrap” look |
File Size | Small in production due to PurgeCSS | Larger because many unused styles are included |
Ease of Use | Steeper learning curve for beginners | Easier for quick prototyping with familiar components |
Responsiveness | Fully responsive with utility classes (md: , lg: , etc.) |
Built-in responsive grid and utilities |
JavaScript Components | No built-in JS (you can use Headless UI or your own) | Includes interactive components (dropdown, modal, etc.) |
Learning Curve | Requires learning class names and design thinking | Easier for those familiar with HTML/CSS |
Community & Ecosystem | Growing fast, popular among devs and designers | Established, widely used in enterprise and legacy apps |
Accessibility | Encourages accessible design with Headless UI | Built-in accessibility in components |
Use Case | Custom UI, modern sites, SPAs, Tailored design | Rapid UI prototyping, admin dashboards, traditional apps |
🔍 Example Comparison
Tailwind Button:
<button class="bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded">
Click me
</button>
Bootstrap Button:
<button class="btn btn-primary">
Click me
</button>
🎯 When to Use Which?
Use Tailwind if:
- You want a custom design without fighting pre-styled components.
- You like design systems and atomic CSS.
- You’re using modern JS frameworks like React, Vue, or Svelte.
Use Bootstrap if:
- You need to quickly build UI with ready-to-use components.
- You’re building internal tools or admin dashboards.
- You’re working on legacy projects or with backend-heavy stacks (like PHP, Django).
✅ Verdict
Criteria | Winner |
---|---|
Custom Design Flexibility | Tailwind |
Quick Prototyping | Bootstrap |
Performance in Production | Tailwind |
Pre-built Components | Bootstrap |
Developer Control | Tailwind |
Leave a comment