This commit is contained in:
spleenftw committed 2026-05-29 12:15:08 +02:00
1 parent 3859c0c268
commit 04464d1fc1
19 files changed
+1379

No files matched your search

+67
View File
@@ -0,0 +1,67 @@
# Blowdit
A clean, minimal theme for [Bludit](https://www.bludit.com) inspired by the
[Blowfish](https://blowfish.page/) Hugo theme.
![Bludit](https://img.shields.io/badge/Bludit-3.9+-informational) ![License](https://img.shields.io/badge/license-MIT-green)
## Features
- 🌗 **Light / dark mode toggle** — remembers the visitor's choice and falls back to the OS preference.
- 🧱 **Monochrome design** — restrained grayscale palette with crisp typography (Inter).
- 👤 **Profile hero** — circular avatar, site title, slogan and social links on the homepage.
- 📚 **Right sidebar** — drop any Bludit sidebar plugin into it (categories, tags, search…).
- ⏱️ **Reading time & dates** shown on the post list and single posts.
- 🔗 **Social icons** in the navbar and hero, using SVG files in `img/` (GitHub, Mastodon, Bluesky, LinkedIn, and more).
- 🏷️ **Tags & categories** rendered as pill badges.
- 📱 Fully responsive, no flash of the wrong theme on load.
## Installation
1. Download or clone this repository into your Bludit `bl-themes` directory:
```
bl-themes/blowdit/
```
2. In the Bludit admin panel go to **Settings → Themes** and activate **Blowdit**.
3. Add your assets to `blowdit/img/`:
- The social-network SVG icons (`github.svg`, `mastodon.svg`, …) named after each
Bludit social-network key.
- Your avatar as `spleenftw.jpeg` — used for the homepage profile hero **and** the favicon.
To use a different filename, change it in [php/head.php](php/head.php) (favicon) and
[php/home.php](php/home.php) (`$profileImage`).
## Layout
```
blowdit/
├── index.php Main template
├── metadata.json Theme metadata
├── css/
│ └── style.css Light & dark styles (CSS custom properties)
├── php/
│ ├── head.php <head>, fonts, favicon, anti-FOUC theme script
│ ├── navbar.php Navbar, social SVG icons, theme toggle
│ ├── home.php Profile hero + post listing
│ ├── page.php Single page / post
│ ├── sidebar.php Sidebar plugin container
│ └── footer.php Footer
├── img/ Social SVG icons + avatar (spleenftw.jpeg)
└── languages/ Translations
```
## Dark mode
The colour scheme is driven by CSS custom properties. Light mode lives in
`:root`; dark mode overrides them under `[data-theme="dark"]`. The attribute is
set on `<html>` before paint (in `php/head.php`) to avoid a flash, and the
toggle button in the navbar persists the choice to `localStorage`.
To tweak the palette, edit the variables at the top of
[css/style.css](css/style.css).
## License
[MIT](LICENSE)
+821
View File
@@ -0,0 +1,821 @@
/* ========================================
BLOWDIT — a Bludit theme inspired by Blowfish
Monochrome palette with light & dark modes
======================================== */
/* ----------------------------------------
THEME TOKENS — Light Mode (default)
---------------------------------------- */
:root {
color-scheme: light;
/* Accent (monochrome: near-black in light mode) */
--accent: #1f1f1f;
--accent-hover: #000000;
--accent-contrast: #ffffff;
/* Surfaces */
--bg-body: #ffffff;
--bg-surface: #ffffff;
--bg-subtle: #f5f5f5;
--bg-hover: #f0f0f0;
/* Text */
--text-primary: #1f1f1f;
--text-secondary: #595959;
--text-muted: #8c8c8c;
/* Borders */
--border-color: #e5e5e5;
--border-subtle: #ededed;
/* Chrome (navbar / footer) — fixed dark in both modes */
--chrome-bg: #1f1f1f;
--chrome-text: rgba(255, 255, 255, 0.92);
--chrome-text-hover: #ffffff;
/* Shadows */
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.04);
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08);
--shadow-lg: 0 12px 28px rgba(0, 0, 0, 0.12);
/* Code */
--code-bg: #f5f5f5;
--code-text: #1f1f1f;
/* Spacing scale */
--space-xs: 0.5rem;
--space-sm: 1rem;
--space-md: 1.5rem;
--space-lg: 2rem;
--space-xl: 3rem;
/* Radii */
--radius-sm: 8px;
--radius-md: 12px;
--radius-lg: 18px;
/* Typography */
--font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
--font-size-base: 1.05rem;
--font-size-sm: 0.875rem;
--font-size-xs: 0.78rem;
--line-height-base: 1.7;
}
/* ----------------------------------------
THEME TOKENS — Dark Mode
---------------------------------------- */
[data-theme="dark"] {
color-scheme: dark;
--accent: #e5e5e5;
--accent-hover: #ffffff;
--accent-contrast: #171717;
--bg-body: #171717;
--bg-surface: #1f1f1f;
--bg-subtle: #262626;
--bg-hover: #2e2e2e;
--text-primary: #ededed;
--text-secondary: #b0b0b0;
--text-muted: #808080;
--border-color: #333333;
--border-subtle: #2a2a2a;
--chrome-bg: #0f0f0f;
--chrome-text: rgba(255, 255, 255, 0.88);
--chrome-text-hover: #ffffff;
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.4);
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.45);
--shadow-lg: 0 12px 28px rgba(0, 0, 0, 0.5);
--code-bg: #262626;
--code-text: #ededed;
}
/* ========================================
BASE
======================================== */
html {
position: relative;
min-height: 100%;
scroll-behavior: smooth;
}
body {
font-family: var(--font-sans);
padding-top: 56px;
margin-bottom: 64px;
background-color: var(--bg-body);
color: var(--text-primary);
font-size: var(--font-size-base);
line-height: var(--line-height-base);
transition: background-color 0.25s ease, color 0.25s ease;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
}
img {
max-width: 100%;
height: auto;
}
::selection {
background: var(--accent);
color: var(--accent-contrast);
}
/* ========================================
LINKS
======================================== */
a {
color: var(--text-primary);
text-decoration: none;
transition: color 0.2s ease;
}
a:hover {
color: var(--text-secondary);
text-decoration: none;
}
a:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
border-radius: 2px;
}
/* ========================================
TYPOGRAPHY
======================================== */
h1, h2, h3, h4, h5, h6 {
color: var(--text-primary);
font-weight: 700;
line-height: 1.25;
letter-spacing: -0.02em;
}
h1.title {
font-size: 2.4rem;
margin-bottom: var(--space-md);
}
h2.title {
font-size: 1.85rem;
margin-bottom: var(--space-sm);
}
.content {
margin-top: var(--space-md);
}
.content h2 { font-size: 1.6rem; margin-top: var(--space-xl); }
.content h3 { font-size: 1.3rem; margin-top: var(--space-lg); }
.content p,
.content ul,
.content ol {
margin-bottom: var(--space-md);
}
.content img {
border-radius: var(--radius-md);
margin: var(--space-md) 0;
}
hr {
border: none;
border-top: 1px solid var(--border-color);
margin: var(--space-xl) 0;
}
/* ========================================
FORMS
======================================== */
input,
textarea,
select,
.form-control {
background-color: var(--bg-surface);
color: var(--text-primary);
border: 1px solid var(--border-color);
border-radius: var(--radius-sm);
}
.form-control:focus {
background-color: var(--bg-surface);
color: var(--text-primary);
border-color: var(--accent);
box-shadow: 0 0 0 3px rgba(127, 127, 127, 0.18);
}
/* ========================================
CODE
======================================== */
pre,
code {
background: var(--code-bg);
color: var(--code-text);
border-radius: var(--radius-sm);
font-family: "JetBrains Mono", "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
transition: background-color 0.25s ease, color 0.25s ease;
}
pre {
border: 1px solid var(--border-color);
border-left: 3px solid var(--accent);
padding: var(--space-md);
overflow-x: auto;
}
code {
display: inline-block;
padding: 0.15em 0.45em;
font-size: 0.875em;
}
pre code {
padding: 0;
background: transparent;
border: none;
}
/* ========================================
TABLES
======================================== */
table {
empty-cells: show;
border: 1px solid var(--border-color);
width: 100%;
font-size: 0.95em;
margin-bottom: var(--space-md);
border-radius: var(--radius-sm);
overflow: hidden;
border-collapse: collapse;
}
thead {
background: var(--bg-subtle);
color: var(--text-primary);
text-align: left;
}
tbody tr {
transition: background-color 0.2s ease;
}
tbody tr:hover {
background-color: var(--bg-hover);
}
th, td {
padding: 0.75em 1em;
border-bottom: 1px solid var(--border-color);
}
/* ========================================
BLOCKQUOTES
======================================== */
blockquote {
padding: var(--space-md) var(--space-lg);
margin: 0 0 var(--space-lg) 0;
border-left: 4px solid var(--accent);
background-color: var(--bg-subtle);
border-radius: var(--radius-sm);
color: var(--text-secondary);
font-style: italic;
}
/* ========================================
NAVBAR
======================================== */
.navbar-modern {
background: var(--chrome-bg) !important;
box-shadow: var(--shadow-sm);
padding-top: 0.5rem;
padding-bottom: 0.5rem;
min-height: 56px;
transition: background-color 0.25s ease;
}
.navbar-brand {
font-weight: 700;
font-size: 1.1rem;
letter-spacing: -0.01em;
}
.navbar-brand .text-white {
color: #ffffff !important;
}
.navbar .nav-link {
font-size: 0.85rem;
font-weight: 500;
color: var(--chrome-text) !important;
padding: 0.4rem 0.85rem !important;
border-radius: var(--radius-sm);
transition: background-color 0.2s ease, color 0.2s ease;
}
.navbar .nav-link:hover {
background-color: rgba(255, 255, 255, 0.12);
color: var(--chrome-text-hover) !important;
}
.navbar .nav-link.active {
background-color: rgba(255, 255, 255, 0.18);
color: var(--chrome-text-hover) !important;
}
.navbar .nav-link .bi {
font-size: 1.15rem;
margin-right: 0;
vertical-align: -0.05em;
}
/* Social SVG icons (img/<network>.svg) — rendered white on the dark navbar */
img.nav-svg-icon {
width: 1.2rem;
height: 1.2rem;
filter: brightness(0) invert(1);
opacity: 0.85;
transition: opacity 0.2s ease, transform 0.2s ease;
}
.nav-link:hover img.nav-svg-icon {
opacity: 1;
transform: translateY(-1px);
}
/* Theme toggle button */
.theme-toggle {
background: transparent;
border: 1px solid rgba(255, 255, 255, 0.2);
color: var(--chrome-text) !important;
border-radius: var(--radius-sm);
width: 38px;
height: 38px;
display: inline-flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: background-color 0.2s ease, border-color 0.2s ease;
}
.theme-toggle:hover {
background-color: rgba(255, 255, 255, 0.12);
border-color: rgba(255, 255, 255, 0.4);
color: #ffffff !important;
}
.theme-toggle .bi {
font-size: 1.1rem;
margin-right: 0;
}
/* ========================================
PROFILE HERO (Blowfish-style homepage)
======================================== */
.profile {
padding: var(--space-xl) 0 var(--space-lg);
margin-bottom: var(--space-lg);
border-bottom: 1px solid var(--border-color);
}
.profile-avatar {
width: 150px;
height: 150px;
border-radius: 50%;
object-fit: cover;
border: 4px solid var(--bg-surface);
box-shadow: var(--shadow-md);
margin-bottom: var(--space-md);
}
.profile-name {
font-size: 2.1rem;
margin-bottom: var(--space-xs);
}
.profile-bio {
color: var(--text-secondary);
font-size: 1.1rem;
margin-bottom: var(--space-md);
}
.profile-social {
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: var(--space-md);
}
.profile-social a {
display: inline-flex;
}
.profile-social-icon {
width: 1.4rem;
height: 1.4rem;
opacity: 0.6;
transition: opacity 0.2s ease, transform 0.2s ease;
}
.profile-social a:hover .profile-social-icon {
opacity: 1;
transform: translateY(-2px);
}
/* Dark mode: invert the dark SVG glyphs to light */
[data-theme="dark"] .profile-social-icon {
filter: brightness(0) invert(1);
opacity: 0.7;
}
[data-theme="dark"] .profile-social a:hover .profile-social-icon {
opacity: 1;
}
@media (max-width: 767.98px) {
.profile-avatar { width: 120px; height: 120px; }
.profile-name { font-size: 1.7rem; }
}
/* ========================================
POST CARDS (home listing)
======================================== */
.card-modern {
background: transparent;
border: none;
border-bottom: 1px solid var(--border-color);
padding-bottom: var(--space-xl);
margin-bottom: var(--space-xl);
}
.card-modern:last-child {
border-bottom: none;
}
.card-modern .card-img-top {
border-radius: var(--radius-md);
}
.card-modern .card-body {
padding: 0;
margin-top: var(--space-md);
}
.card-modern .title {
color: var(--text-primary);
transition: color 0.2s ease;
}
.card-modern a:hover .title {
color: var(--text-secondary);
}
.cover-image-wrapper {
position: relative;
overflow: hidden;
border-radius: var(--radius-md);
margin-bottom: var(--space-md);
}
.cover-image-wrapper .card-img-top {
transition: transform 0.4s ease;
}
.card-modern:hover .cover-image-wrapper .card-img-top {
transform: scale(1.03);
}
/* ========================================
METADATA (date, reading time)
======================================== */
.metadata {
color: var(--text-muted);
font-size: var(--font-size-sm);
display: flex;
flex-wrap: wrap;
gap: var(--space-md);
align-items: center;
}
.metadata i {
color: var(--text-muted);
margin-right: 0.35rem;
}
/* ========================================
BUTTONS
======================================== */
.btn-primary-gradient {
background: var(--accent);
border: none;
color: var(--accent-contrast);
padding: 0.6rem 1.3rem;
border-radius: var(--radius-sm);
font-weight: 600;
font-size: var(--font-size-sm);
transition: background-color 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease;
box-shadow: var(--shadow-sm);
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
.btn-primary-gradient:hover {
background: var(--accent-hover);
color: var(--accent-contrast);
transform: translateY(-2px);
box-shadow: var(--shadow-md);
text-decoration: none;
}
.btn-primary-gradient .bi {
margin-right: 0;
transition: transform 0.2s ease;
}
.btn-primary-gradient:hover .bi {
transform: translateX(3px);
}
/* ========================================
TAXONOMY (tags & categories)
======================================== */
.post-taxonomy {
display: flex;
flex-wrap: wrap;
gap: 0.4rem;
align-items: center;
}
.taxonomy-badge {
display: inline-flex;
align-items: center;
padding: 0.3rem 0.8rem;
border-radius: 999px;
font-size: var(--font-size-xs);
font-weight: 500;
border: 1px solid var(--border-color);
color: var(--text-secondary);
background: transparent;
transition: all 0.2s ease;
}
.taxonomy-badge .bi {
margin-right: 0.35rem;
font-size: 0.85em;
}
.taxonomy-badge:hover {
background: var(--accent);
color: var(--accent-contrast);
border-color: var(--accent);
}
/* ========================================
PAGINATION
======================================== */
.pagination .page-link {
background: var(--bg-surface);
border: 1px solid var(--border-color);
color: var(--text-primary);
padding: 0.55rem 1.1rem;
border-radius: var(--radius-sm);
font-weight: 500;
transition: all 0.2s ease;
}
.pagination .page-link:hover {
background: var(--accent);
color: var(--accent-contrast);
border-color: var(--accent);
transform: translateY(-2px);
}
.pagination .page-item.disabled .page-link {
background: var(--bg-subtle);
color: var(--text-muted);
border-color: var(--border-color);
}
/* ========================================
SIDEBAR + PLUGINS
======================================== */
.sidebar-container {
margin-top: var(--space-xl);
background: var(--bg-surface);
border: 1px solid var(--border-color);
border-radius: var(--radius-lg);
padding: var(--space-lg);
font-size: 0.9rem;
position: sticky;
top: 72px;
}
/* Compact profile card inside the sidebar (article view) */
.sidebar-profile {
padding-bottom: var(--space-lg);
margin-bottom: var(--space-lg);
border-bottom: 1px solid var(--border-subtle);
}
.sidebar-profile-avatar {
width: 84px;
height: 84px;
border-radius: 50%;
object-fit: cover;
border: 3px solid var(--bg-surface);
box-shadow: var(--shadow-sm);
margin-bottom: var(--space-sm);
transition: transform 0.2s ease;
}
.sidebar-profile-avatar:hover {
transform: translateY(-2px);
}
.sidebar-profile-name {
font-weight: 700;
font-size: 1rem;
color: var(--text-primary);
}
.sidebar-profile-bio {
color: var(--text-secondary);
font-size: var(--font-size-sm);
margin: 0.35rem 0 0;
}
.plugin {
padding-bottom: var(--space-lg);
margin-bottom: var(--space-lg);
border-bottom: 1px solid var(--border-subtle);
}
.plugin:last-child {
border-bottom: none;
margin-bottom: 0;
padding-bottom: 0;
}
.plugin-label {
font-size: var(--font-size-xs);
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--text-muted);
margin-bottom: var(--space-md);
}
.plugin ul {
list-style: none;
padding: 0;
margin: 0;
}
.plugin ul li {
padding: 0.3rem 0;
}
.plugin ul li a {
color: var(--text-secondary);
display: block;
transition: color 0.2s ease;
}
.plugin ul li a:hover {
color: var(--text-primary);
}
/* Tags & categories in sidebar — badge style */
.plugin.plugin-tags ul,
.plugin.plugin-categories ul {
display: flex;
flex-wrap: wrap;
gap: 0.4rem;
}
.plugin.plugin-tags li,
.plugin.plugin-categories li {
padding: 0;
}
.plugin.plugin-tags li a,
.plugin.plugin-categories li a {
background: var(--bg-subtle);
color: var(--text-secondary);
padding: 0.3rem 0.8rem;
border-radius: 999px;
font-size: var(--font-size-xs);
font-weight: 500;
display: inline-block;
transition: all 0.2s ease;
}
.plugin.plugin-tags li a:hover,
.plugin.plugin-categories li a:hover {
background: var(--accent);
color: var(--accent-contrast);
}
/* Search plugin */
.plugin.plugin-search .form-control {
border: 1px solid var(--border-color);
border-radius: var(--radius-sm);
padding: 0.6rem 0.9rem;
background: var(--bg-body);
color: var(--text-primary);
}
.plugin.plugin-search .form-control:focus {
border-color: var(--accent);
box-shadow: 0 0 0 3px rgba(127, 127, 127, 0.18);
outline: none;
}
.plugin.plugin-search button {
background: var(--accent);
border: none;
color: var(--accent-contrast);
padding: 0.55rem 1.2rem;
border-radius: var(--radius-sm);
font-weight: 600;
transition: background-color 0.2s ease, transform 0.2s ease;
margin-top: var(--space-sm);
}
.plugin.plugin-search button:hover {
background: var(--accent-hover);
transform: translateY(-2px);
}
/* ========================================
FOOTER
======================================== */
footer.footer-modern {
position: absolute;
bottom: 0;
width: 100%;
min-height: 64px;
line-height: 1.6;
background: var(--chrome-bg);
color: var(--chrome-text);
padding: 1rem 0;
font-size: var(--font-size-xs);
transition: background-color 0.25s ease;
}
footer.footer-modern a {
color: var(--chrome-text);
transition: color 0.2s ease;
}
footer.footer-modern a:hover {
color: var(--chrome-text-hover);
}
.mini-logo {
height: 22px;
vertical-align: middle;
filter: brightness(0) invert(1);
}
/* ========================================
ICON SPACING
======================================== */
.bi {
margin-right: 0.4rem;
}
/* ========================================
RESPONSIVE
======================================== */
@media (max-width: 767.98px) {
h1.title { font-size: 1.9rem; }
h2.title { font-size: 1.5rem; }
body { font-size: 1rem; }
.sidebar-container {
position: static;
margin-top: var(--space-lg);
}
.btn-primary-gradient {
width: 100%;
justify-content: center;
}
.navbar-nav .theme-toggle {
width: 100%;
margin-top: 0.5rem;
height: 42px;
}
}
+101
View File
@@ -0,0 +1,101 @@
<!DOCTYPE html>
<html lang="<?php echo Theme::lang() ?>">
<head>
<?php include(THEME_DIR_PHP.'head.php'); ?>
</head>
<body>
<!-- Load Bludit Plugins: Site Body Begin -->
<?php Theme::plugins('siteBodyBegin'); ?>
<!-- Navbar -->
<?php include(THEME_DIR_PHP.'navbar.php'); ?>
<!-- Content -->
<div class="container">
<div class="row">
<!-- Blog Posts -->
<div class="col-md-8">
<?php
// Bludit content are pages.
// Ordered by date, these pages behave like posts.
//
// $WHERE_AM_I detects where the visitor is:
// "page" -> viewing a single page/post
// "home" -> viewing the front page
if ($WHERE_AM_I == 'page') {
include(THEME_DIR_PHP.'page.php');
} else {
include(THEME_DIR_PHP.'home.php');
}
?>
</div>
<!-- Right Sidebar -->
<div class="col-md-3 offset-md-1">
<?php include(THEME_DIR_PHP.'sidebar.php'); ?>
</div>
</div>
</div>
<!-- Footer -->
<?php include(THEME_DIR_PHP.'footer.php'); ?>
<!-- Javascript -->
<?php
// Include Jquery file from Bludit Core
echo Theme::jquery();
// Include javascript Bootstrap file from Bludit Core
echo Theme::jsBootstrap();
?>
<!-- Light / Dark theme toggle -->
<script>
(function () {
var STORAGE_KEY = 'blowdit-theme';
var root = document.documentElement;
var btn = document.getElementById('theme-toggle');
function syncIcon(theme) {
if (!btn) return;
var icon = btn.querySelector('i');
if (!icon) return;
icon.className = (theme === 'dark') ? 'bi bi-sun' : 'bi bi-moon-stars';
}
function apply(theme) {
root.setAttribute('data-theme', theme);
try { localStorage.setItem(STORAGE_KEY, theme); } catch (e) {}
syncIcon(theme);
}
// Reflect the theme set by the inline head script.
syncIcon(root.getAttribute('data-theme') || 'light');
if (btn) {
btn.addEventListener('click', function () {
var current = root.getAttribute('data-theme') || 'light';
apply(current === 'dark' ? 'light' : 'dark');
});
}
// Follow the OS preference unless the visitor chose explicitly.
if (window.matchMedia) {
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function (e) {
try {
if (localStorage.getItem(STORAGE_KEY)) return;
} catch (err) {}
apply(e.matches ? 'dark' : 'light');
});
}
})();
</script>
<!-- Load Bludit Plugins: Site Body End -->
<?php Theme::plugins('siteBodyEnd'); ?>
</body>
</html>
+8
View File
@@ -0,0 +1,8 @@
{
"theme-data":
{
"name": "Blowdit",
"description": "Ein Bludit-Theme, inspiriert vom Blowfish-Hugo-Theme. Rechte Seitenleiste, Lesezeit, Umschalter für hellen/dunklen Modus und eine Navigationsleiste mit Social-Media-Icons und statischen Seiten."
},
"Toggle theme": "Design wechseln"
}
+8
View File
@@ -0,0 +1,8 @@
{
"theme-data":
{
"name": "Blowdit",
"description": "Ein Bludit-Theme, inspiriert vom Blowfish-Hugo-Theme. Rechte Seitenleiste, Lesezeit, Umschalter für hellen/dunklen Modus und eine Navigationsleiste mit Social-Media-Icons und statischen Seiten."
},
"Toggle theme": "Design wechseln"
}
+8
View File
@@ -0,0 +1,8 @@
{
"theme-data":
{
"name": "Blowdit",
"description": "A Bludit theme inspired by the Blowfish Hugo theme. Right sidebar, reading time, a light/dark mode toggle and a navbar with social icons and static pages."
},
"Toggle theme": "Toggle theme"
}
+8
View File
@@ -0,0 +1,8 @@
{
"theme-data":
{
"name": "Blowdit",
"description": "Un tema para Bludit inspirado en el tema Blowfish de Hugo. Barra lateral derecha, tiempo de lectura, conmutador de modo claro/oscuro y barra de navegación con iconos sociales y páginas estáticas."
},
"Toggle theme": "Cambiar tema"
}
+8
View File
@@ -0,0 +1,8 @@
{
"theme-data":
{
"name": "Blowdit",
"description": "یک قالب بلودیت با الهام از قالب Blowfish هوگو. نوار کناری راست، زمان مطالعه، کلید تغییر حالت روشن/تاریک و نوار ناوبری به همراه آیکون‌های شبکه‌های اجتماعی و صفحات ایستا."
},
"Toggle theme": "تغییر پوسته"
}
+8
View File
@@ -0,0 +1,8 @@
{
"theme-data":
{
"name": "Blowdit",
"description": "Un tema per Bludit ispirato al tema Blowfish di Hugo. Barra laterale a destra, tempo di lettura, interruttore per la modalità chiara/scura e barra di navigazione con icone social e pagine statiche."
},
"Toggle theme": "Cambia tema"
}
+8
View File
@@ -0,0 +1,8 @@
{
"theme-data":
{
"name": "Blowdit",
"description": "Hugo の Blowfish テーマにインスパイアされた Bludit テーマ。右サイドバー、読了時間、ライト/ダークモードの切り替え、ソーシャルアイコンと固定ページを備えたナビゲーションバーを搭載しています。"
},
"Toggle theme": "テーマを切り替え"
}
+8
View File
@@ -0,0 +1,8 @@
{
"theme-data":
{
"name": "Blowdit",
"description": "Een Bludit-thema geïnspireerd op het Blowfish-thema voor Hugo. Zijbalk rechts, leestijd, schakelaar voor lichte/donkere modus en een navigatiebalk met sociale iconen en statische pagina's."
},
"Toggle theme": "Thema wisselen"
}
+8
View File
@@ -0,0 +1,8 @@
{
"theme-data":
{
"name": "Blowdit",
"description": "Тема для Bludit, вдохновлённая темой Blowfish для Hugo. Боковая панель справа, время чтения, переключатель светлой/тёмной темы и панель навигации со значками соцсетей и статическими страницами."
},
"Toggle theme": "Переключить тему"
}
+8
View File
@@ -0,0 +1,8 @@
{
"theme-data":
{
"name": "Blowdit",
"description": "Hugo'nun Blowfish temasından esinlenen bir Bludit teması. Sağ kenar çubuğu, okuma süresi, açık/koyu mod düğmesi ve sosyal simgeler ile sabit sayfalar içeren bir gezinme çubuğu."
},
"Toggle theme": "Temayı değiştir"
}
+20
View File
@@ -0,0 +1,20 @@
<footer class="footer footer-modern">
<div class="container">
<div class="row align-items-center">
<?php if (defined('BLUDIT_PRO')): ?>
<div class="col-12 text-center">
<p class="m-0 text-uppercase"><?php echo $site->footer(); ?></p>
</div>
<?php else: ?>
<div class="col-md-6 text-center text-md-left mb-2 mb-md-0">
<p class="m-0 text-uppercase"><?php echo $site->footer(); ?></p>
</div>
<div class="col-md-6 text-center text-md-right">
<p class="m-0">
Powered by <a href="https://www.bludit.com" target="_blank" rel="noopener"><strong>BLUDIT</strong></a>
</p>
</div>
<?php endif; ?>
</div>
</div>
</footer>
+43
View File
@@ -0,0 +1,43 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="Bludit">
<!-- Set the colour theme as early as possible to avoid a flash -->
<script>
(function () {
try {
var stored = localStorage.getItem('blowdit-theme');
var prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
var theme = stored || (prefersDark ? 'dark' : 'light');
document.documentElement.setAttribute('data-theme', theme);
} catch (e) {
document.documentElement.setAttribute('data-theme', 'light');
}
})();
</script>
<!-- Dynamic title tag -->
<?php echo Theme::metaTags('title'); ?>
<!-- Dynamic description tag -->
<?php echo Theme::metaTags('description'); ?>
<!-- Include Favicon -->
<?php echo Theme::favicon('img/spleenftw.jpeg'); ?>
<!-- Inter typeface (Blowfish-like typography) -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<!-- Include Bootstrap CSS file bootstrap.css -->
<?php echo Theme::cssBootstrap(); ?>
<!-- Include CSS Bootstrap ICONS file from Bludit Core -->
<?php echo Theme::cssBootstrapIcons(); ?>
<!-- Include CSS Styles from this theme -->
<?php echo Theme::css('css/style.css'); ?>
<!-- Load Bludit Plugins: Site head -->
<?php Theme::plugins('siteHead'); ?>
+129
View File
@@ -0,0 +1,129 @@
<?php
// ---- Profile hero (Blowfish-style) -------------------------------------
// Shown only on the blog front page (first paginated page).
// Drop your avatar at img/spleenftw.jpeg (change the filename below to reuse).
$profileImage = DOMAIN_THEME . 'img/spleenftw.jpeg';
$showProfile = ($WHERE_AM_I === 'home' && Paginator::currentPage() == 1);
?>
<?php if ($showProfile) : ?>
<header class="profile text-center">
<img class="profile-avatar" src="<?php echo $profileImage; ?>" alt="<?php echo $site->title(); ?>" />
<h1 class="profile-name"><?php echo $site->title(); ?></h1>
<?php if ($site->slogan()) : ?>
<p class="profile-bio"><?php echo $site->slogan(); ?></p>
<?php elseif ($site->description()) : ?>
<p class="profile-bio"><?php echo $site->description(); ?></p>
<?php endif ?>
<?php $networks = Theme::socialNetworks(); ?>
<?php if (!empty($networks)) : ?>
<div class="profile-social">
<?php foreach ($networks as $key => $label) : ?>
<a href="<?php echo $site->{$key}(); ?>" target="_blank" rel="noopener" title="<?php echo $label ?>">
<img class="profile-social-icon" src="<?php echo DOMAIN_THEME . 'img/' . $key . '.svg' ?>" alt="<?php echo $label ?>" />
</a>
<?php endforeach ?>
</div>
<?php endif ?>
</header>
<?php endif ?>
<?php if (empty($content)) : ?>
<div class="mt-5">
<?php $language->p('No pages found') ?>
</div>
<?php endif ?>
<?php foreach ($content as $page) : ?>
<!-- Post -->
<article class="card card-modern my-5">
<!-- Load Bludit Plugins: Page Begin -->
<?php Theme::plugins('pageBegin'); ?>
<!-- Cover image -->
<?php if ($page->coverImage()) : ?>
<a href="<?php echo $page->permalink(); ?>" class="cover-image-wrapper d-block">
<img class="card-img-top" alt="<?php echo $page->title(); ?>" src="<?php echo $page->coverImage(); ?>" />
</a>
<?php endif ?>
<div class="card-body">
<!-- Title -->
<a href="<?php echo $page->permalink(); ?>">
<h2 class="title"><?php echo $page->title(); ?></h2>
</a>
<!-- Creation date and reading time -->
<div class="metadata mb-4">
<span><i class="bi bi-calendar3"></i><?php echo $page->date(); ?></span>
<span><i class="bi bi-clock-history"></i><?php echo $L->get('Reading time') . ': ' . $page->readingTime(); ?></span>
</div>
<!-- Breaked content -->
<?php echo $page->contentBreak(); ?>
<!-- "Read more" button -->
<?php if ($page->readMore()) : ?>
<a class="btn-primary-gradient mt-3" href="<?php echo $page->permalink(); ?>">
<?php echo $L->get('Read more'); ?>
<i class="bi bi-arrow-right"></i>
</a>
<?php endif ?>
<!-- Tags and Category -->
<?php $tagsList = $page->tags(true); $categoryKey = $page->categoryKey(); ?>
<?php if (!empty($tagsList) || $categoryKey) : ?>
<div class="post-taxonomy mt-4">
<?php if ($categoryKey) : ?>
<a class="taxonomy-badge" href="<?php echo $page->categoryPermalink(); ?>">
<i class="bi bi-folder2"></i><?php echo $page->category(); ?>
</a>
<?php endif ?>
<?php foreach ($tagsList as $tagKey => $tagName) : ?>
<a class="taxonomy-badge" href="<?php echo DOMAIN_TAGS . $tagKey; ?>"><i class="bi bi-tag"></i><?php echo $tagName; ?></a>
<?php endforeach ?>
</div>
<?php endif ?>
</div>
<!-- Load Bludit Plugins: Page End -->
<?php Theme::plugins('pageEnd'); ?>
</article>
<?php endforeach ?>
<!-- Pagination -->
<?php if (Paginator::numberOfPages() > 1) : ?>
<nav class="paginator mt-5">
<ul class="pagination flex-wrap justify-content-center">
<!-- Previous button -->
<?php if (Paginator::showPrev()) : ?>
<li class="page-item mr-2">
<a class="page-link" href="<?php echo Paginator::previousPageUrl() ?>" tabindex="-1">
<i class="bi bi-chevron-left"></i> <?php echo $L->get('Previous'); ?>
</a>
</li>
<?php endif; ?>
<!-- Home button -->
<li class="page-item mx-2 <?php if (Paginator::currentPage() == 1) echo 'disabled' ?>">
<a class="page-link" href="<?php echo Theme::siteUrl() ?>">
<i class="bi bi-house-door"></i> Home
</a>
</li>
<!-- Next button -->
<?php if (Paginator::showNext()) : ?>
<li class="page-item ml-2">
<a class="page-link" href="<?php echo Paginator::nextPageUrl() ?>">
<?php echo $L->get('Next'); ?> <i class="bi bi-chevron-right"></i>
</a>
</li>
<?php endif; ?>
</ul>
</nav>
<?php endif ?>
+46
View File
@@ -0,0 +1,46 @@
<nav class="navbar navbar-expand-md navbar-dark fixed-top navbar-modern">
<div class="container">
<a class="navbar-brand" href="<?php echo Theme::siteUrl() ?>">
<span class="text-white"><?php echo $site->title() ?></span>
</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ml-auto align-items-md-center">
<!-- Blog link (when homepage is set to a static page) -->
<?php if ($site->homepage()): ?>
<li class="nav-item">
<a class="nav-link<?php echo ($WHERE_AM_I === 'blog') ? ' active' : '' ?>" href="<?php echo DOMAIN_BASE . ltrim($url->filters('blog'), '/') ?>"><?php echo $L->get('Blog') ?></a>
</li>
<?php endif; ?>
<!-- Static pages -->
<?php foreach ($staticContent as $staticPage) : ?>
<li class="nav-item">
<a class="nav-link<?php echo ($url->slug() == $staticPage->slug()) ? ' active' : '' ?>" href="<?php echo $staticPage->permalink() ?>"><?php echo $staticPage->title() ?></a>
</li>
<?php endforeach ?>
<!-- Social Networks (SVG icons live in img/<network>.svg) -->
<?php foreach (Theme::socialNetworks() as $key => $label) : ?>
<li class="nav-item">
<a class="nav-link" href="<?php echo $site->{$key}(); ?>" target="_blank" rel="noopener" title="<?php echo $label ?>">
<img class="d-none d-md-block nav-svg-icon" src="<?php echo DOMAIN_THEME . 'img/' . $key . '.svg' ?>" alt="<?php echo $label ?>" />
<span class="d-inline d-md-none"><?php echo $label; ?></span>
</a>
</li>
<?php endforeach; ?>
<!-- Light / Dark mode toggle -->
<li class="nav-item ml-md-2 mt-2 mt-md-0">
<button type="button" id="theme-toggle" class="theme-toggle" aria-label="<?php echo $L->get('Toggle theme') ?>" title="<?php echo $L->get('Toggle theme') ?>">
<i class="bi bi-moon-stars" aria-hidden="true"></i>
</button>
</li>
</ul>
</div>
</div>
</nav>
+51
View File
@@ -0,0 +1,51 @@
<!-- Post -->
<article class="card card-modern my-5">
<!-- Load Bludit Plugins: Page Begin -->
<?php Theme::plugins('pageBegin'); ?>
<!-- Cover image -->
<?php if ($page->coverImage()): ?>
<div class="cover-image-wrapper">
<img class="card-img-top" alt="<?php echo $page->title(); ?>" src="<?php echo $page->coverImage(); ?>"/>
</div>
<?php endif ?>
<div class="card-body">
<!-- Title -->
<h1 class="title"><?php echo $page->title(); ?></h1>
<?php if (!$page->isStatic() && !$url->notFound()): ?>
<!-- Creation date and reading time -->
<div class="metadata mb-4">
<span><i class="bi bi-calendar3"></i><?php echo $page->date(); ?></span>
<span><i class="bi bi-clock-history"></i><?php echo $L->get('Reading time') . ': ' . $page->readingTime() ?></span>
</div>
<?php endif ?>
<!-- Full content -->
<div class="content">
<?php echo $page->content(); ?>
</div>
<!-- Tags and Category -->
<?php $tagsList = $page->tags(true); $categoryKey = $page->categoryKey(); ?>
<?php if (!empty($tagsList) || $categoryKey) : ?>
<div class="post-taxonomy mt-4">
<?php if ($categoryKey) : ?>
<a class="taxonomy-badge" href="<?php echo $page->categoryPermalink(); ?>">
<i class="bi bi-folder2"></i><?php echo $page->category(); ?>
</a>
<?php endif ?>
<?php foreach ($tagsList as $tagKey => $tagName) : ?>
<a class="taxonomy-badge" href="<?php echo DOMAIN_TAGS . $tagKey; ?>"><i class="bi bi-tag"></i><?php echo $tagName; ?></a>
<?php endforeach ?>
</div>
<?php endif ?>
</div>
<!-- Load Bludit Plugins: Page End -->
<?php Theme::plugins('pageEnd'); ?>
</article>
+21
View File
@@ -0,0 +1,21 @@
<aside class="sidebar-container">
<?php
// Compact profile card — shown only while reading an article
// (a single, non-static page), not on the homepage or static pages.
$isArticle = ($WHERE_AM_I === 'page' && isset($page) && !$page->isStatic() && !$url->notFound());
?>
<?php if ($isArticle) : ?>
<div class="sidebar-profile text-center">
<a href="<?php echo Theme::siteUrl() ?>">
<img class="sidebar-profile-avatar" src="<?php echo DOMAIN_THEME . 'img/spleenftw.jpeg' ?>" alt="<?php echo $site->title() ?>" />
</a>
<div class="sidebar-profile-name"><?php echo $site->title() ?></div>
<?php if ($site->slogan()) : ?>
<p class="sidebar-profile-bio"><?php echo $site->slogan() ?></p>
<?php endif ?>
</div>
<?php endif ?>
<?php Theme::plugins('siteSidebar') ?>
</aside>