mirror of
https://github.com/chaoming/hugo-saasify-theme.git
synced 2025-04-20 07:11:52 +02:00
added blog design in the theme
This commit is contained in:
parent
bc1a3bdd9b
commit
aed855d55d
20 changed files with 708 additions and 26 deletions
|
@ -30,6 +30,10 @@
|
||||||
margin-bottom: 2rem;
|
margin-bottom: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cta-gradient {
|
||||||
|
background: linear-gradient(calc(var(--gradient-angle) * 1deg), var(--gradient-from), var(--gradient-to));
|
||||||
|
}
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
@apply inline-flex items-center justify-center px-6 py-3 font-medium transition duration-200 ease-in-out;
|
@apply inline-flex items-center justify-center px-6 py-3 font-medium transition duration-200 ease-in-out;
|
||||||
border-radius: 2rem;
|
border-radius: 2rem;
|
||||||
|
@ -67,4 +71,117 @@
|
||||||
.feature-grid {
|
.feature-grid {
|
||||||
@apply grid gap-8 md:grid-cols-2 lg:grid-cols-3;
|
@apply grid gap-8 md:grid-cols-2 lg:grid-cols-3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Blog and Syntax Highlighting Styles */
|
||||||
|
.highlight {
|
||||||
|
@apply text-sm font-mono text-gray-200;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight table {
|
||||||
|
@apply w-full border-separate border-spacing-0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight table td {
|
||||||
|
@apply p-0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight table td:first-child {
|
||||||
|
@apply pr-4 text-right select-none text-gray-500 border-r border-gray-700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight table td:last-child {
|
||||||
|
@apply pl-4 w-full;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight .k, .highlight .kd {
|
||||||
|
@apply text-purple-400 font-semibold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight .nf, .highlight .nx {
|
||||||
|
@apply text-blue-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight .s, .highlight .s1, .highlight .s2 {
|
||||||
|
@apply text-green-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight .mi, .highlight .mf {
|
||||||
|
@apply text-orange-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight .c, .highlight .c1, .highlight .cm {
|
||||||
|
@apply text-gray-500 italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight .o {
|
||||||
|
@apply text-yellow-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight .p {
|
||||||
|
@apply text-gray-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose {
|
||||||
|
@apply max-w-none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose h1, .prose h2, .prose h3, .prose h4 {
|
||||||
|
@apply font-heading font-bold text-gray-900;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose h1 {
|
||||||
|
@apply text-4xl mb-8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose h2 {
|
||||||
|
@apply text-3xl mt-12 mb-6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose h3 {
|
||||||
|
@apply text-2xl mt-8 mb-4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose p {
|
||||||
|
@apply text-gray-700 leading-relaxed mb-6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose a {
|
||||||
|
@apply text-primary-600 hover:text-primary-700 no-underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose ul, .prose ol {
|
||||||
|
@apply my-6 ml-6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose li {
|
||||||
|
@apply mb-2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose blockquote {
|
||||||
|
@apply border-l-4 border-gray-200 pl-4 italic text-gray-700 my-8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose img {
|
||||||
|
@apply rounded-lg shadow-lg my-8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose code:not(pre code) {
|
||||||
|
@apply bg-gray-100 text-gray-900 px-1.5 py-0.5 rounded text-sm font-mono;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-of-contents {
|
||||||
|
@apply bg-gray-50 p-6 rounded-lg my-8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-of-contents nav {
|
||||||
|
@apply space-y-2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-of-contents a {
|
||||||
|
@apply text-gray-700 hover:text-primary-600 no-underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-of-contents ul {
|
||||||
|
@apply list-none ml-4 space-y-2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
65
layouts/_default/list.html
Normal file
65
layouts/_default/list.html
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
{{ define "main" }}
|
||||||
|
<div class="container mx-auto px-4 py-12">
|
||||||
|
<div class="max-w-7xl mx-auto">
|
||||||
|
{{ if .IsHome }}
|
||||||
|
<h1 class="text-4xl font-bold mb-8">{{ .Site.Title }}</h1>
|
||||||
|
{{ else }}
|
||||||
|
<h1 class="text-4xl font-bold mb-8">{{ .Title }}</h1>
|
||||||
|
{{ with .Description }}
|
||||||
|
<div class="text-xl text-gray-600 mb-8">{{ . }}</div>
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||||
|
{{ $paginator := .Paginate .Pages }}
|
||||||
|
{{ range $paginator.Pages }}
|
||||||
|
{{ partial "post-card.html" . }}
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ $paginator := .Paginate .Pages }}
|
||||||
|
{{ if gt $paginator.TotalPages 1 }}
|
||||||
|
<nav class="mt-12 flex justify-between items-center">
|
||||||
|
{{ if $paginator.HasPrev }}
|
||||||
|
<a href="{{ $paginator.Prev.URL }}"
|
||||||
|
class="inline-flex items-center px-4 py-2 bg-primary-600 text-white rounded-lg hover:bg-primary-700 transition-colors duration-200">
|
||||||
|
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"></path>
|
||||||
|
</svg>
|
||||||
|
Previous
|
||||||
|
</a>
|
||||||
|
{{ else }}
|
||||||
|
<div></div>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
<div class="flex space-x-2">
|
||||||
|
{{ range $paginator.Pagers }}
|
||||||
|
{{ if eq . $paginator }}
|
||||||
|
<span class="px-4 py-2 bg-primary-600 text-white rounded-lg">
|
||||||
|
{{ .PageNumber }}
|
||||||
|
</span>
|
||||||
|
{{ else }}
|
||||||
|
<a href="{{ .URL }}"
|
||||||
|
class="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg hover:bg-gray-200 transition-colors duration-200">
|
||||||
|
{{ .PageNumber }}
|
||||||
|
</a>
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ if $paginator.HasNext }}
|
||||||
|
<a href="{{ $paginator.Next.URL }}"
|
||||||
|
class="inline-flex items-center px-4 py-2 bg-primary-600 text-white rounded-lg hover:bg-primary-700 transition-colors duration-200">
|
||||||
|
Next
|
||||||
|
<svg class="w-5 h-5 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3"></path>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
{{ else }}
|
||||||
|
<div></div>
|
||||||
|
{{ end }}
|
||||||
|
</nav>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
86
layouts/_default/single.html
Normal file
86
layouts/_default/single.html
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
{{ define "main" }}
|
||||||
|
<div class="container mx-auto px-4 py-12">
|
||||||
|
<!-- Two Column Layout for Content and Sidebar -->
|
||||||
|
<div class="flex flex-col lg:flex-row gap-8 mb-12">
|
||||||
|
<!-- Main Content -->
|
||||||
|
<article class="flex-1">
|
||||||
|
<header class="mb-8">
|
||||||
|
{{ with .Params.categories }}
|
||||||
|
<div class="mb-4">
|
||||||
|
{{ range . }}
|
||||||
|
<a href="{{ "/categories/" | relLangURL }}{{ . | urlize }}"
|
||||||
|
class="inline-block px-3 py-1 text-sm font-medium text-primary-600 bg-primary-50 rounded-full hover:bg-primary-100 mr-2">
|
||||||
|
{{ . }}
|
||||||
|
</a>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
<h1 class="text-4xl font-bold mb-4">{{ .Title }}</h1>
|
||||||
|
|
||||||
|
{{ partial "post-meta.html" . }}
|
||||||
|
</header>
|
||||||
|
|
||||||
|
{{ with .Params.featured_image }}
|
||||||
|
<div class="mb-8">
|
||||||
|
<img src="{{ . }}"
|
||||||
|
alt="{{ $.Title }}"
|
||||||
|
class="w-full h-auto rounded-lg"
|
||||||
|
loading="lazy">
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
<div class="prose prose-lg max-w-none">
|
||||||
|
{{ .Content }}
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<!-- Sidebar -->
|
||||||
|
<aside class="lg:w-80 xl:w-96">
|
||||||
|
{{ partial "sidebar.html" . }}
|
||||||
|
</aside>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Full-width Navigation Section -->
|
||||||
|
<nav class="border-t border-gray-200 mt-12 pt-8">
|
||||||
|
<div class="flex justify-between items-center">
|
||||||
|
{{ with .PrevInSection }}
|
||||||
|
<a href="{{ .RelPermalink }}"
|
||||||
|
class="group flex items-center">
|
||||||
|
<svg class="w-5 h-5 mr-2 text-gray-600 group-hover:text-primary-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"></path>
|
||||||
|
</svg>
|
||||||
|
<div>
|
||||||
|
<div class="text-sm text-gray-600">Previous Post</div>
|
||||||
|
<div class="font-medium group-hover:text-primary-600">{{ .Title }}</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
{{ else }}
|
||||||
|
<div></div>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ with .NextInSection }}
|
||||||
|
<a href="{{ .RelPermalink }}"
|
||||||
|
class="group flex items-center text-right">
|
||||||
|
<div>
|
||||||
|
<div class="text-sm text-gray-600">Next Post</div>
|
||||||
|
<div class="font-medium group-hover:text-primary-600">{{ .Title }}</div>
|
||||||
|
</div>
|
||||||
|
<svg class="w-5 h-5 ml-2 text-gray-600 group-hover:text-primary-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3"></path>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
{{ else }}
|
||||||
|
<div></div>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<!-- Full-width CTA Section -->
|
||||||
|
{{ if and .Site.Params.blog.cta.enable .Site.Params.cta.enable }}
|
||||||
|
<div class="mt-16">
|
||||||
|
{{ partial "components/cta.html" . }}
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
|
@ -1,6 +1,3 @@
|
||||||
{{ define "main" }}
|
{{ define "main" }}
|
||||||
<!-- Hero Section -->
|
{{ .Content }}
|
||||||
{{ if .Content }}
|
|
||||||
{{ .Content }}
|
|
||||||
{{ end }}
|
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
28
layouts/partials/components/cta.html
Normal file
28
layouts/partials/components/cta.html
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
{{ if .Site.Params.cta.enable }}
|
||||||
|
<section class="cta-section">
|
||||||
|
<div class="container">
|
||||||
|
{{ $angle := .Site.Params.cta.gradient_angle | default 45 }}
|
||||||
|
{{ $from := .Site.Params.cta.gradient_from }}
|
||||||
|
{{ $to := .Site.Params.cta.gradient_to }}
|
||||||
|
<div class="relative rounded-lg overflow-hidden bg-primary-600 cta-gradient"
|
||||||
|
style="--gradient-angle: {{ $angle }}; --gradient-from: {{ $from }}; --gradient-to: {{ $to }}">
|
||||||
|
<div class="relative text-center max-w-3xl mx-auto px-6 py-10">
|
||||||
|
<h2 class="text-3xl md:text-4xl font-bold text-white mb-6">{{ .Site.Params.cta.title }}</h2>
|
||||||
|
<p class="text-xl text-primary-100 mb-8">{{ .Site.Params.cta.description }}</p>
|
||||||
|
<div class="flex flex-col sm:flex-row justify-center gap-4">
|
||||||
|
{{ with .Site.Params.cta.primary_button }}
|
||||||
|
<a href="{{ .url }}" class="btn bg-white text-primary-600 hover:bg-gray-100">
|
||||||
|
{{ .text }}
|
||||||
|
</a>
|
||||||
|
{{ end }}
|
||||||
|
{{ with .Site.Params.cta.secondary_button }}
|
||||||
|
<a href="{{ .url }}" class="btn border-2 border-white text-white hover:bg-primary-700">
|
||||||
|
{{ .text }}
|
||||||
|
</a>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{{ end }}
|
33
layouts/partials/components/subscribe-form.html
Normal file
33
layouts/partials/components/subscribe-form.html
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
<div class="bg-primary-50 p-6 rounded-lg">
|
||||||
|
<h3 class="text-lg font-bold text-gray-900 mb-2">{{ .title | default "Subscribe to Newsletter" }}</h3>
|
||||||
|
<p class="text-sm text-gray-600 mb-4">{{ .description | default "Get the latest posts delivered right to your inbox." }}</p>
|
||||||
|
|
||||||
|
<form action="{{ .action | default "#" }}" method="POST" class="space-y-3">
|
||||||
|
{{ with .hidden }}
|
||||||
|
{{ range $name, $value := . }}
|
||||||
|
<input type="hidden" name="{{ $name }}" value="{{ $value }}">
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
name="{{ .emailName | default "email" }}"
|
||||||
|
placeholder="{{ .placeholder | default "Enter your email" }}"
|
||||||
|
required
|
||||||
|
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-primary-500"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="w-full px-4 py-2 bg-primary-600 text-white rounded-lg hover:bg-primary-700 transition-colors duration-200"
|
||||||
|
>
|
||||||
|
{{ .buttonText | default "Subscribe" }}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{{ with .disclaimer }}
|
||||||
|
<p class="text-xs text-gray-500 mt-2">{{ . }}</p>
|
||||||
|
{{ end }}
|
||||||
|
</form>
|
||||||
|
</div>
|
80
layouts/partials/post-card.html
Normal file
80
layouts/partials/post-card.html
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
<article class="bg-white rounded-lg shadow-md overflow-hidden hover:shadow-lg transition-shadow duration-300">
|
||||||
|
{{ with .Params.featured_image }}
|
||||||
|
<a href="{{ $.RelPermalink }}" class="block aspect-w-16 aspect-h-9 overflow-hidden">
|
||||||
|
<img
|
||||||
|
src="{{ . }}"
|
||||||
|
alt="{{ $.Title }}"
|
||||||
|
class="object-cover w-full h-full transform hover:scale-105 transition-transform duration-300"
|
||||||
|
loading="lazy"
|
||||||
|
>
|
||||||
|
</a>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
<div class="p-6">
|
||||||
|
<!-- Category -->
|
||||||
|
{{ with .Params.categories }}
|
||||||
|
<div class="mb-4">
|
||||||
|
{{ range first 1 . }}
|
||||||
|
<a href="{{ "/categories/" | relLangURL }}{{ . | urlize }}"
|
||||||
|
class="inline-block px-3 py-1 text-sm font-medium text-primary-600 bg-primary-50 rounded-full hover:bg-primary-100">
|
||||||
|
{{ . }}
|
||||||
|
</a>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
<!-- Title -->
|
||||||
|
<h2 class="text-2xl font-bold mb-3 hover:text-primary-600 transition-colors duration-200">
|
||||||
|
<a href="{{ .RelPermalink }}">{{ .Title }}</a>
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<!-- Description -->
|
||||||
|
<p class="text-gray-600 mb-4 line-clamp-2">
|
||||||
|
{{ with .Description }}
|
||||||
|
{{ . }}
|
||||||
|
{{ else }}
|
||||||
|
{{ .Summary | truncate 160 }}
|
||||||
|
{{ end }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- Author and Date in a cleaner layout -->
|
||||||
|
<div class="flex items-center justify-between text-sm text-gray-500 mb-4">
|
||||||
|
{{ with .Params.author }}
|
||||||
|
<div class="flex items-center">
|
||||||
|
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"></path>
|
||||||
|
</svg>
|
||||||
|
<span>{{ . }}</span>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
<div class="flex items-center">
|
||||||
|
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path>
|
||||||
|
</svg>
|
||||||
|
<time datetime="{{ .Date.Format "2006-01-02" }}">
|
||||||
|
{{ .Date.Format "Jan 2, 2006" }}
|
||||||
|
</time>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Read More link and Reading Time -->
|
||||||
|
<div class="flex justify-between items-center">
|
||||||
|
<a href="{{ .RelPermalink }}"
|
||||||
|
class="inline-flex items-center text-primary-600 hover:text-primary-700 font-medium">
|
||||||
|
Read More
|
||||||
|
<svg class="w-4 h-4 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3"></path>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<!-- Reading Time -->
|
||||||
|
<span class="text-sm text-gray-500 flex items-center">
|
||||||
|
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"></path>
|
||||||
|
</svg>
|
||||||
|
<span>{{ .ReadingTime }} min</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
45
layouts/partials/post-meta.html
Normal file
45
layouts/partials/post-meta.html
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
<div class="flex flex-col space-y-4">
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Author and Date -->
|
||||||
|
<div class="flex items-center justify-between text-sm text-gray-500">
|
||||||
|
{{ with .Params.author }}
|
||||||
|
<div class="flex items-center">
|
||||||
|
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"></path>
|
||||||
|
</svg>
|
||||||
|
<span>{{ . }}</span>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
<div class="flex items-center space-x-6">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"></path>
|
||||||
|
</svg>
|
||||||
|
<span>{{ .ReadingTime }} min read</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-center">
|
||||||
|
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path>
|
||||||
|
</svg>
|
||||||
|
<time datetime="{{ .Date.Format "2006-01-02" }}">
|
||||||
|
{{ .Date.Format "January 2, 2006" }}
|
||||||
|
</time>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Tags -->
|
||||||
|
{{ with .Params.tags }}
|
||||||
|
<div class="flex items-center flex-wrap gap-2">
|
||||||
|
{{ range . }}
|
||||||
|
<a href="{{ "/tags/" | relLangURL }}{{ . | urlize }}"
|
||||||
|
class="px-3 py-1 bg-gray-100 hover:bg-gray-200 rounded-full text-sm text-gray-700 transition-colors duration-200">
|
||||||
|
#{{ . }}
|
||||||
|
</a>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
86
layouts/partials/sidebar.html
Normal file
86
layouts/partials/sidebar.html
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
<div class="space-y-8">
|
||||||
|
<!-- Subscribe Form -->
|
||||||
|
{{ if .Site.Params.blog.sidebar.subscribe.enable }}
|
||||||
|
{{ $params := dict
|
||||||
|
"title" .Site.Params.blog.sidebar.subscribe.title
|
||||||
|
"description" .Site.Params.blog.sidebar.subscribe.description
|
||||||
|
"action" .Site.Params.blog.sidebar.subscribe.action
|
||||||
|
"emailName" .Site.Params.blog.sidebar.subscribe.emailName
|
||||||
|
"buttonText" .Site.Params.blog.sidebar.subscribe.buttonText
|
||||||
|
"placeholder" .Site.Params.blog.sidebar.subscribe.placeholder
|
||||||
|
"disclaimer" .Site.Params.blog.sidebar.subscribe.disclaimer
|
||||||
|
"hidden" .Site.Params.blog.sidebar.subscribe.hidden
|
||||||
|
}}
|
||||||
|
{{ partial "components/subscribe-form" $params }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
<!-- Recent Articles -->
|
||||||
|
{{ if .Site.Params.blog.sidebar.recent.enable }}
|
||||||
|
<div class="bg-white rounded-lg shadow-md p-6">
|
||||||
|
<h3 class="text-lg font-bold mb-4">{{ .Site.Params.blog.sidebar.recent.title | default "Recent Articles" }}</h3>
|
||||||
|
<div class="space-y-4">
|
||||||
|
{{ $recentCount := .Site.Params.blog.sidebar.recent.count | default 5 }}
|
||||||
|
{{ range first $recentCount (where .Site.RegularPages "Type" "blog") }}
|
||||||
|
<div class="group">
|
||||||
|
<a href="{{ .RelPermalink }}" class="block">
|
||||||
|
{{ with .Params.featured_image }}
|
||||||
|
<div class="aspect-w-16 aspect-h-9 mb-3 overflow-hidden rounded-lg">
|
||||||
|
<img
|
||||||
|
src="{{ . }}"
|
||||||
|
alt="{{ $.Title }}"
|
||||||
|
class="object-cover w-full h-full transform group-hover:scale-105 transition-transform duration-300"
|
||||||
|
loading="lazy"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
<h4 class="font-medium text-gray-900 group-hover:text-primary-600 transition-colors duration-200 line-clamp-2">
|
||||||
|
{{ .Title }}
|
||||||
|
</h4>
|
||||||
|
<div class="flex items-center text-sm text-gray-500 mt-2">
|
||||||
|
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path>
|
||||||
|
</svg>
|
||||||
|
<time datetime="{{ .Date.Format "2006-01-02" }}">
|
||||||
|
{{ .Date.Format "Jan 2, 2006" }}
|
||||||
|
</time>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
<!-- Categories -->
|
||||||
|
{{ if .Site.Params.blog.sidebar.categories.enable }}
|
||||||
|
<div class="bg-white rounded-lg shadow-md p-6">
|
||||||
|
<h3 class="text-lg font-bold mb-4">{{ .Site.Params.blog.sidebar.categories.title | default "Categories" }}</h3>
|
||||||
|
<div class="flex flex-wrap gap-2">
|
||||||
|
{{ range $name, $taxonomy := .Site.Taxonomies.categories }}
|
||||||
|
<a href="{{ "/categories/" | relLangURL }}{{ $name | urlize }}"
|
||||||
|
class="inline-block px-3 py-1 text-sm font-medium text-primary-600 bg-primary-50 rounded-full hover:bg-primary-100">
|
||||||
|
{{ $name }}
|
||||||
|
<span class="text-gray-500 ml-1">({{ $taxonomy.Count }})</span>
|
||||||
|
</a>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
<!-- Tags Cloud -->
|
||||||
|
{{ if .Site.Params.blog.sidebar.tags.enable }}
|
||||||
|
<div class="bg-white rounded-lg shadow-md p-6">
|
||||||
|
<h3 class="text-lg font-bold mb-4">{{ .Site.Params.blog.sidebar.tags.title | default "Popular Tags" }}</h3>
|
||||||
|
<div class="flex flex-wrap gap-2">
|
||||||
|
{{ $tagCount := .Site.Params.blog.sidebar.tags.count | default 20 }}
|
||||||
|
{{ range first $tagCount .Site.Taxonomies.tags.ByCount }}
|
||||||
|
<a href="{{ "/tags/" | relLangURL }}{{ .Name | urlize }}"
|
||||||
|
class="text-sm text-gray-600 hover:text-primary-600">
|
||||||
|
#{{ .Name }}
|
||||||
|
<span class="text-gray-500">({{ .Count }})</span>
|
||||||
|
</a>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
19
layouts/shortcodes/code.html
Normal file
19
layouts/shortcodes/code.html
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{{ $lang := .Get 0 }}
|
||||||
|
{{ $code := .Inner }}
|
||||||
|
{{ $filename := .Get 1 }}
|
||||||
|
|
||||||
|
<div class="not-prose my-8 overflow-hidden rounded-lg bg-gray-900 shadow-lg">
|
||||||
|
{{ with $filename }}
|
||||||
|
<div class="flex items-center justify-between px-4 py-2 bg-gray-800 border-b border-gray-700">
|
||||||
|
<div class="text-sm text-gray-200 font-mono">{{ . }}</div>
|
||||||
|
<div class="flex space-x-2">
|
||||||
|
<div class="w-3 h-3 rounded-full bg-red-500"></div>
|
||||||
|
<div class="w-3 h-3 rounded-full bg-yellow-500"></div>
|
||||||
|
<div class="w-3 h-3 rounded-full bg-green-500"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
<div class="p-4 overflow-x-auto">
|
||||||
|
{{ highlight $code $lang "linenos=table,linenostart=1,hl_lines=,lineanchors=line" }}
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -1,22 +1,17 @@
|
||||||
{{/* CTA Shortcode */}}
|
{{ $params := dict
|
||||||
<section class="cta-section">
|
"title" (.Get "title")
|
||||||
<div class="container">
|
"description" (.Get "description")
|
||||||
<div class="relative rounded-lg overflow-hidden bg-primary-600" {{ with .Get "gradient-from" }}style="background:linear-gradient({{ if $.Get "gradient-angle" }}{{ $.Get "gradient-angle" }}deg{{ else }}to right{{ end }},{{ . }},{{ $.Get "gradient-to" | default . }})"{{ end }} {{ with .Get "background-image" }}style="background-image:url('{{ . }}');background-size:cover;background-position:center"{{ end }}>
|
"primary_button" (dict
|
||||||
{{ with .Get "background-image" }}
|
"text" (.Get "primary_button_text")
|
||||||
<div class="absolute inset-0 bg-black/30"></div>
|
"url" (.Get "primary_button_url")
|
||||||
{{ end }}
|
)
|
||||||
<div class="relative text-center max-w-3xl mx-auto px-6 py-10">
|
"secondary_button" (dict
|
||||||
<h2 class="text-3xl md:text-4xl font-bold text-white mb-6">{{ .Get "title" | default "Ready to Transform Your User Experience?" }}</h2>
|
"text" (.Get "secondary_button_text")
|
||||||
<p class="text-xl text-primary-100 mb-8">{{ .Get "description" | default "Join thousands of companies already using our platform to drive growth." }}</p>
|
"url" (.Get "secondary_button_url")
|
||||||
<div class="flex flex-col sm:flex-row justify-center gap-4">
|
)
|
||||||
<a href="{{ .Get "primary_button_url" | default "#" }}" class="btn bg-white text-primary-600 hover:bg-gray-100">
|
"gradient_from" (.Get "gradient-from")
|
||||||
{{ .Get "primary_button_text" | default "Get Started Free" }}
|
"gradient_to" (.Get "gradient-to")
|
||||||
</a>
|
"gradient_angle" (.Get "gradient-angle")
|
||||||
<a href="{{ .Get "secondary_button_url" | default "#" }}" class="btn border-2 border-white text-white hover:bg-primary-700">
|
}}
|
||||||
{{ .Get "secondary_button_text" | default "Schedule Demo" }}
|
|
||||||
</a>
|
{{ partial "components/cta" (dict "Site" .Site "Params" (dict "cta" $params "enable" true)) }}
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
18
layouts/shortcodes/figure.html
Normal file
18
layouts/shortcodes/figure.html
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
{{ $src := .Get "src" }}
|
||||||
|
{{ $alt := .Get "alt" }}
|
||||||
|
{{ $caption := .Get "caption" }}
|
||||||
|
{{ $class := .Get "class" | default "w-full" }}
|
||||||
|
|
||||||
|
<figure class="my-8">
|
||||||
|
<img
|
||||||
|
src="{{ $src }}"
|
||||||
|
alt="{{ $alt }}"
|
||||||
|
class="{{ $class }} rounded-lg shadow-lg"
|
||||||
|
loading="lazy"
|
||||||
|
>
|
||||||
|
{{ with $caption }}
|
||||||
|
<figcaption class="mt-2 text-center text-sm text-gray-600">
|
||||||
|
{{ . | markdownify }}
|
||||||
|
</figcaption>
|
||||||
|
{{ end }}
|
||||||
|
</figure>
|
4
layouts/shortcodes/toc.html
Normal file
4
layouts/shortcodes/toc.html
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<div class="bg-gray-50 p-6 rounded-lg mb-8">
|
||||||
|
<h2 class="text-xl font-semibold mb-4">Table of Contents</h2>
|
||||||
|
{{ .Page.TableOfContents }}
|
||||||
|
</div>
|
70
layouts/taxonomy/list.html
Normal file
70
layouts/taxonomy/list.html
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
{{ define "main" }}
|
||||||
|
<div class="container mx-auto px-4 py-12">
|
||||||
|
<div class="max-w-4xl mx-auto">
|
||||||
|
<header class="mb-12">
|
||||||
|
<h1 class="text-4xl font-bold mb-4">
|
||||||
|
{{ .Data.Singular | title }}: {{ .Title }}
|
||||||
|
</h1>
|
||||||
|
<div class="text-xl text-gray-600">
|
||||||
|
{{ $count := len .Pages }}
|
||||||
|
{{ if eq $count 1 }}
|
||||||
|
1 post
|
||||||
|
{{ else }}
|
||||||
|
{{ $count }} posts
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="grid gap-8">
|
||||||
|
{{ $paginator := .Paginate .Pages }}
|
||||||
|
{{ range $paginator.Pages }}
|
||||||
|
{{ partial "post-card.html" . }}
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ $paginator := .Paginate .Pages }}
|
||||||
|
{{ if gt $paginator.TotalPages 1 }}
|
||||||
|
<nav class="mt-12 flex justify-between items-center">
|
||||||
|
{{ if $paginator.HasPrev }}
|
||||||
|
<a href="{{ $paginator.Prev.URL }}"
|
||||||
|
class="inline-flex items-center px-4 py-2 bg-primary-600 text-white rounded-lg hover:bg-primary-700 transition-colors duration-200">
|
||||||
|
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"></path>
|
||||||
|
</svg>
|
||||||
|
Previous
|
||||||
|
</a>
|
||||||
|
{{ else }}
|
||||||
|
<div></div>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
<div class="flex space-x-2">
|
||||||
|
{{ range $paginator.Pagers }}
|
||||||
|
{{ if eq . $paginator }}
|
||||||
|
<span class="px-4 py-2 bg-primary-600 text-white rounded-lg">
|
||||||
|
{{ .PageNumber }}
|
||||||
|
</span>
|
||||||
|
{{ else }}
|
||||||
|
<a href="{{ .URL }}"
|
||||||
|
class="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg hover:bg-gray-200 transition-colors duration-200">
|
||||||
|
{{ .PageNumber }}
|
||||||
|
</a>
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ if $paginator.HasNext }}
|
||||||
|
<a href="{{ $paginator.Next.URL }}"
|
||||||
|
class="inline-flex items-center px-4 py-2 bg-primary-600 text-white rounded-lg hover:bg-primary-700 transition-colors duration-200">
|
||||||
|
Next
|
||||||
|
<svg class="w-5 h-5 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3"></path>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
{{ else }}
|
||||||
|
<div></div>
|
||||||
|
{{ end }}
|
||||||
|
</nav>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
39
layouts/taxonomy/terms.html
Normal file
39
layouts/taxonomy/terms.html
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
{{ define "main" }}
|
||||||
|
<div class="container mx-auto px-4 py-12">
|
||||||
|
<div class="max-w-4xl mx-auto">
|
||||||
|
<header class="mb-12">
|
||||||
|
<h1 class="text-4xl font-bold mb-4">
|
||||||
|
{{ .Title }}
|
||||||
|
</h1>
|
||||||
|
<div class="text-xl text-gray-600">
|
||||||
|
Browse all {{ .Data.Plural }}
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
|
||||||
|
{{ range .Data.Terms.ByCount }}
|
||||||
|
<a href="{{ .Page.RelPermalink }}"
|
||||||
|
class="group p-6 bg-white rounded-lg shadow-md hover:shadow-lg transition-shadow duration-200">
|
||||||
|
<h2 class="text-xl font-semibold mb-2 group-hover:text-primary-600">
|
||||||
|
{{ .Page.Title }}
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray-600">
|
||||||
|
{{ .Count }}
|
||||||
|
{{ if eq .Count 1 }}
|
||||||
|
post
|
||||||
|
{{ else }}
|
||||||
|
posts
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ if not .Data.Terms }}
|
||||||
|
<div class="text-center py-12 text-gray-600">
|
||||||
|
No {{ .Data.Plural }} found
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
BIN
static/images/blog/blog-1.jpg
Normal file
BIN
static/images/blog/blog-1.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 76 KiB |
BIN
static/images/blog/blog-2.webp
Normal file
BIN
static/images/blog/blog-2.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 392 KiB |
BIN
static/images/blog/blog-3.webp
Normal file
BIN
static/images/blog/blog-3.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 74 KiB |
BIN
static/images/blog/blog-4.jpg
Normal file
BIN
static/images/blog/blog-4.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 419 KiB |
BIN
static/images/blog/blog-5.jpg
Normal file
BIN
static/images/blog/blog-5.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 279 KiB |
Loading…
Add table
Reference in a new issue