From 13e3b938c753c53e1e3f9e595d1abe298d4fe583 Mon Sep 17 00:00:00 2001 From: rexO77 Date: Sat, 8 Nov 2025 00:15:07 +0530 Subject: [PATCH 1/2] Welcome V2 --- ENHANCEMENTS.md | 420 +++++++++++++++++ QUICK-START.md | 133 ++++++ assets/css/style.css | 703 +++++++++++++++++++++++++++- assets/js/main.js | 2 +- assets/js/search.js | 146 ++++++ hugo.toml | 77 +++ hugo_stats.json | 51 +- layouts/_default/baseof.html | 19 + layouts/_default/index.json | 14 + layouts/_default/list.html | 69 ++- layouts/_default/single.html | 9 + layouts/partials/comments.html | 83 ++++ layouts/partials/newsletter.html | 99 ++++ layouts/partials/related-posts.html | 68 +++ readme.md | 372 ++++++++++----- 15 files changed, 2144 insertions(+), 121 deletions(-) create mode 100644 ENHANCEMENTS.md create mode 100644 QUICK-START.md create mode 100644 assets/js/search.js create mode 100644 layouts/_default/index.json create mode 100644 layouts/partials/comments.html create mode 100644 layouts/partials/newsletter.html create mode 100644 layouts/partials/related-posts.html diff --git a/ENHANCEMENTS.md b/ENHANCEMENTS.md new file mode 100644 index 0000000..f144fd7 --- /dev/null +++ b/ENHANCEMENTS.md @@ -0,0 +1,420 @@ +# Blog Enhancements - Implementation Guide + +This document outlines all the enhancements made to your Hugo blog and how to configure them. + +## ๐ŸŽ‰ What's Been Added + +All **5 Quick Win Enhancements** have been successfully implemented: + +1. โœ… **Enhanced Post Cards** - Beautiful, modern post listings with thumbnails and metadata +2. โœ… **Search Functionality** - Fast client-side search with keyboard shortcuts +3. โœ… **Comment System** - Giscus integration for community engagement +4. โœ… **Related Posts** - Smart content recommendations based on tags/categories +5. โœ… **Newsletter Integration** - Email subscription forms for audience building + +--- + +## 1๏ธโƒฃ Enhanced Post Cards + +### What Changed +- Homepage now displays rich post cards instead of simple list items +- Each card shows: + - Thumbnail image (auto-detected from post images) + - Category badges + - Post title + - Description/excerpt + - Publication date + - Reading time +- Responsive grid layout (1 column on mobile, 2 on tablet, 3 on desktop) +- Hover animations and smooth transitions + +### Files Modified +- `layouts/_default/list.html` - Updated post listing template +- `assets/css/style.css` - Added post card styles +- `assets/js/main.js` - Updated loading states + +### No Configuration Needed +This feature works automatically! Your posts will automatically display with enhanced cards. + +--- + +## 2๏ธโƒฃ Search Functionality + +### What Changed +- Beautiful modal search interface (opens with keyboard shortcut) +- Searches through post titles, descriptions, content, tags, and categories +- Keyboard shortcuts: `Cmd/Ctrl + K` to open, `Escape` to close +- Real-time search as you type +- Fuzzy search algorithm for better results +- Clean, distraction-free interface + +### Files Created +- `layouts/_default/index.json` - Search index generator +- `assets/js/search.js` - Search functionality + +### Files Modified +- `hugo.toml` - Added JSON output format +- `layouts/_default/baseof.html` - Added search UI and included search.js +- `assets/css/style.css` - Added search modal styles + +### Configuration +The search works automatically! Hugo will generate `/index.json` with all your posts. + +**Test it:** Press `โŒ˜K` (Mac) or `Ctrl+K` (Windows/Linux) to open search from anywhere on your site + +--- + +## 3๏ธโƒฃ Comment System (Giscus) + +### What Changed +- Added comment section at the bottom of each blog post +- Supports multiple providers: Giscus, Utterances, or Disqus +- Default: Giscus (GitHub Discussions) +- Theme syncs with your site's dark/light mode + +### Files Created +- `layouts/partials/comments.html` - Comments component + +### Files Modified +- `layouts/_default/single.html` - Added comments section +- `hugo.toml` - Added comments configuration +- `assets/css/style.css` - Added comments styles + +### Configuration Required โš ๏ธ + +To enable Giscus comments, follow these steps: + +1. **Create a GitHub repository for comments** (or use an existing one) + - Can be a dedicated repo like `blog-comments` or your blog repo itself + - Must be **public** + +2. **Enable GitHub Discussions** + - Go to your repo โ†’ Settings โ†’ Features + - Check "Discussions" + +3. **Install Giscus App** + - Visit https://giscus.app/ + - Scroll down to "Configuration" + - Enter your repo (e.g., `RexO77/blog-comments`) + - Choose settings (recommended defaults are fine) + - Copy the generated values + +4. **Update `hugo.toml`** + ```toml + [params.comments.giscus] + repo = "YourUsername/your-repo" # UPDATE THIS! + repoId = "R_xxxxxxxxxxxxx" # Get from giscus.app + category = "General" # Discussion category + categoryId = "DIC_xxxxxxxxxx" # Get from giscus.app + ``` + +5. **Disable if not ready** + ```toml + [params.comments] + enabled = false # Set to true when configured + ``` + +--- + +## 4๏ธโƒฃ Related Posts + +### What Changed +- "You Might Also Like" section appears on blog posts +- Shows up to 3 related posts +- Smart matching based on tags, categories, and date +- Beautiful card layout with images + +### Files Created +- `layouts/partials/related-posts.html` - Related posts component + +### Files Modified +- `layouts/_default/single.html` - Added related posts section +- `hugo.toml` - Added related content configuration +- `assets/css/style.css` - Added related posts styles + +### Configuration +The feature is already configured! Hugo's built-in related content engine will automatically find similar posts. + +You can adjust the algorithm in `hugo.toml`: +```toml +[related] + threshold = 80 # Minimum match score (0-100) + includeNewer = true # Include newer posts + [[related.indices]] + name = "tags" + weight = 100 # Tags are most important + [[related.indices]] + name = "categories" + weight = 80 # Categories are important + [[related.indices]] + name = "date" + weight = 10 # Date is least important +``` + +--- + +## 5๏ธโƒฃ Newsletter Integration + +### What Changed +- Beautiful newsletter signup section on blog posts +- Eye-catching gradient design with animations +- Supports multiple providers: Mailchimp, ConvertKit, Substack, or custom +- Responsive and mobile-friendly + +### Files Created +- `layouts/partials/newsletter.html` - Newsletter component + +### Files Modified +- `layouts/_default/single.html` - Added newsletter section +- `hugo.toml` - Added newsletter configuration +- `assets/css/style.css` - Added newsletter styles + +### Configuration Required โš ๏ธ + +Choose your newsletter provider and configure: + +#### Option A: Mailchimp (Recommended) + +1. **Create a Mailchimp audience** at mailchimp.com +2. **Get your signup form code** + - Audience โ†’ Signup forms โ†’ Embedded forms + - Copy the form action URL (looks like: `https://yoursite.us21.list-manage.com/subscribe/post?u=xxx&id=xxx`) +3. **Update `hugo.toml`** + ```toml + [params.newsletter] + enabled = true + provider = "mailchimp" + + [params.newsletter.mailchimp] + action = "YOUR_MAILCHIMP_FORM_ACTION_URL" + hiddenField = "b_YOUR_USER_ID_YOUR_LIST_ID" + ``` + +#### Option B: ConvertKit + +```toml +[params.newsletter] + enabled = true + provider = "convertkit" + +[params.newsletter.convertkit] + action = "https://app.convertkit.com/forms/YOUR_FORM_ID/subscriptions" + formId = "YOUR_FORM_ID" + uid = "YOUR_UID" +``` + +#### Option C: Substack + +```toml +[params.newsletter] + enabled = true + provider = "substack" + +[params.newsletter.substack] + url = "https://yoursubstack.substack.com" +``` + +#### Option D: Custom Backend + +If you want to handle subscriptions yourself: + +```toml +[params.newsletter] + enabled = true + provider = "custom" + +[params.newsletter.custom] + action = "/api/newsletter/subscribe" # Your API endpoint +``` + +#### Customize the Text + +```toml +[params.newsletter] + title = "๐Ÿ“ฌ Your Custom Title" + description = "Your custom description about the newsletter." +``` + +#### Disable if Not Ready + +```toml +[params.newsletter] + enabled = false # Set to true when configured +``` + +--- + +## ๐Ÿš€ Testing Your Changes + +### Build and Run Locally + +```bash +# Start the Hugo dev server +hugo server -D + +# Or if you have a dev script +./dev.sh +``` + +Visit `http://localhost:1313` to see all the new features! + +### What to Test + +1. **Homepage** - Check the new post cards layout +2. **Search** - Press `โŒ˜K` or click search icon, try searching for posts +3. **Open a blog post** and scroll down to see: + - Tags section + - Related Posts section + - Newsletter signup + - Social sharing buttons + - Post navigation + - Comments section (if configured) + +--- + +## ๐Ÿ“ Next Steps + +### 1. Configure Giscus Comments +- Follow the instructions in section 3๏ธโƒฃ above +- Update `hugo.toml` with your repo details + +### 2. Setup Newsletter +- Choose a provider (Mailchimp recommended for beginners) +- Follow the instructions in section 5๏ธโƒฃ above +- Update `hugo.toml` with your provider details + +### 3. Optional: Add Google Analytics +```toml +[params] + googleAnalytics = "G-XXXXXXXXXX" # Your GA4 ID +``` + +### 4. Deploy +Once everything looks good locally: + +```bash +# Build the site +hugo + +# Or if you have a build script +./build.sh + +# Then deploy (if using Vercel, it auto-deploys on push) +git add . +git commit -m "Add blog enhancements" +git push +``` + +--- + +## ๐ŸŽจ Customization + +### Change Colors + +Edit `assets/css/style.css`: + +```css +:root { + --accent-color-blue: #0099FF; /* Primary accent */ + --accent-color-yellow: #FFD700; /* Secondary accent */ +} +``` + +### Adjust Layout + +All responsive breakpoints are in `assets/css/style.css`: +- Mobile: `< 768px` +- Tablet: `768px - 1024px` +- Desktop: `> 1024px` + +### Modify Search Behavior + +Edit `assets/js/search.js` to adjust: +- Search delay (currently 200ms) +- Number of results +- Search algorithm + +--- + +## ๐Ÿ› Troubleshooting + +### Search Not Working +- Check if `/index.json` is generated (visit it in browser) +- Check browser console for JavaScript errors +- Make sure `hugo.toml` has the correct output configuration + +### Comments Not Showing +- Ensure `enabled = true` in `hugo.toml` +- Check if Giscus repo and category IDs are correct +- Make sure GitHub Discussions is enabled on your repo + +### Related Posts Not Showing +- You need at least 2 posts with similar tags/categories +- Lower the `threshold` in `hugo.toml` if no posts appear +- Check that posts have tags and categories in frontmatter + +### Newsletter Form Not Working +- Verify the action URL is correct +- Check browser console for errors +- Test with your provider's test mode first + +--- + +## ๐Ÿ“š File Structure + +``` +blog.nischalskanda.tech/ +โ”œโ”€โ”€ layouts/ +โ”‚ โ”œโ”€โ”€ _default/ +โ”‚ โ”‚ โ”œโ”€โ”€ baseof.html # Modified: Added search modal +โ”‚ โ”‚ โ”œโ”€โ”€ list.html # Modified: Enhanced post cards +โ”‚ โ”‚ โ”œโ”€โ”€ single.html # Modified: Added all new sections +โ”‚ โ”‚ โ””โ”€โ”€ index.json # NEW: Search index +โ”‚ โ””โ”€โ”€ partials/ +โ”‚ โ”œโ”€โ”€ comments.html # NEW: Comments component +โ”‚ โ”œโ”€โ”€ related-posts.html # NEW: Related posts component +โ”‚ โ””โ”€โ”€ newsletter.html # NEW: Newsletter component +โ”œโ”€โ”€ assets/ +โ”‚ โ”œโ”€โ”€ css/ +โ”‚ โ”‚ โ””โ”€โ”€ style.css # Modified: Added all new styles +โ”‚ โ””โ”€โ”€ js/ +โ”‚ โ”œโ”€โ”€ main.js # Modified: Updated for post cards +โ”‚ โ””โ”€โ”€ search.js # NEW: Search functionality +โ”œโ”€โ”€ hugo.toml # Modified: New configurations +โ””โ”€โ”€ ENHANCEMENTS.md # NEW: This file! +``` + +--- + +## ๐ŸŽฏ What You Get + +- **Better UX**: Visitors can easily browse and find content +- **Engagement**: Comments and newsletter build your community +- **Retention**: Related posts keep readers on your site longer +- **Professional**: Modern design that matches 2025 standards +- **Performance**: All features are optimized and lightweight + +--- + +## ๐Ÿ’ก Tips + +1. **Write good descriptions** for your posts - they appear in cards and search +2. **Use tags and categories** consistently for better related posts +3. **Add images** to your posts - they automatically show in cards +4. **Respond to comments** to build community engagement +5. **Promote your newsletter** in your posts to grow your list + +--- + +## ๐Ÿค Support + +If you encounter any issues: +1. Check the troubleshooting section above +2. Verify configuration in `hugo.toml` +3. Check browser console for errors +4. Review Hugo documentation at https://gohugo.io/ + +--- + +**Enjoy your enhanced blog! ๐Ÿš€** + diff --git a/QUICK-START.md b/QUICK-START.md new file mode 100644 index 0000000..e3da6e6 --- /dev/null +++ b/QUICK-START.md @@ -0,0 +1,133 @@ +# ๐Ÿš€ Quick Start Guide + +## All 5 Enhancements Are DONE! โœ… + +Your blog now has these awesome features: + +## โœ… What Works Right Now (No Configuration Needed) + +### 1. Enhanced Post Cards +- Beautiful grid layout on homepage +- Automatic image detection +- Category badges +- Reading time + +### 2. Search Functionality +- Press `โŒ˜K` (Mac) or `Ctrl+K` (Windows/Linux) to search +- Real-time search across all posts +- Works immediately! + +### 3. Related Posts +- Smart recommendations +- Shows similar content +- Already working! + +## โš™๏ธ What Needs Configuration (5 minutes each) + +### 4. Comments (Giscus) +**Status:** Template ready, needs your GitHub repo + +**Quick Setup:** +1. Go to https://giscus.app/ +2. Enter your repo name +3. Get the IDs +4. Update `hugo.toml` lines 60-63 +5. Change `enabled = true` on line 53 + +**OR disable for now:** +```toml +[params.comments] + enabled = false # Line 53 in hugo.toml +``` + +### 5. Newsletter +**Status:** Template ready, needs your email provider + +**Quick Setup (Mailchimp):** +1. Create Mailchimp account +2. Get form action URL +3. Update `hugo.toml` line 91 +4. Change `enabled = true` on line 84 + +**OR disable for now:** +```toml +[params.newsletter] + enabled = false # Line 84 in hugo.toml +``` + +--- + +## ๐Ÿงช Test It Now! + +```bash +hugo server -D +``` + +Then visit http://localhost:1313 and check: + +1. **Homepage** - See the new beautiful post cards +2. **Press โŒ˜K or Ctrl+K** - Try the search feature +3. **Open any post** - See related posts section +4. **Scroll down** - See newsletter and comments (if enabled) + +--- + +## ๐Ÿ“ Files Changed + +**New Files Created:** +- `layouts/_default/index.json` - Search index +- `layouts/partials/comments.html` - Comments component +- `layouts/partials/related-posts.html` - Related posts +- `layouts/partials/newsletter.html` - Newsletter form +- `assets/js/search.js` - Search functionality +- `ENHANCEMENTS.md` - Full documentation +- `QUICK-START.md` - This file + +**Files Modified:** +- `layouts/_default/list.html` - New post cards +- `layouts/_default/single.html` - Added new sections +- `layouts/_default/baseof.html` - Added search UI +- `assets/css/style.css` - All new styles +- `assets/js/main.js` - Updated animations +- `hugo.toml` - New configurations + +--- + +## ๐ŸŽฏ Ready to Deploy? + +1. **Test locally first** + ```bash + hugo server -D + ``` + +2. **Configure comments & newsletter** (optional) + - See `ENHANCEMENTS.md` for detailed steps + +3. **Build** + ```bash + hugo + ``` + +4. **Deploy** + ```bash + git add . + git commit -m "Add 5 major blog enhancements" + git push + ``` + +--- + +## ๐Ÿ’ก Pro Tips + +- **Search**: It indexes all your posts automatically! +- **Related Posts**: Add more tags to your posts for better matching +- **Post Cards**: Images from your posts auto-appear +- **Comments**: Can enable later without breaking anything +- **Newsletter**: Can enable later without breaking anything + +--- + +**Read `ENHANCEMENTS.md` for detailed configuration instructions!** + +Enjoy your upgraded blog! ๐ŸŽ‰ + diff --git a/assets/css/style.css b/assets/css/style.css index e405d28..5aee516 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -654,7 +654,7 @@ a { top: 0; left: 0; width: 100%; - height: 3px; + height: 4px; background: transparent; z-index: 9999; pointer-events: none; @@ -662,10 +662,56 @@ a { .reading-progress-fill { height: 100%; - background: linear-gradient(90deg, var(--accent-color-blue), var(--accent-color-yellow)); + background: linear-gradient(90deg, + #0099FF 0%, + #00B4FF 25%, + #FFB800 75%, + #FFD700 100% + ); width: 0%; - transition: width var(--transition-fast); - border-radius: 0 3px 3px 0; + transition: width 0.1s ease-out; + box-shadow: + 0 0 12px rgba(0, 153, 255, 0.6), + 0 0 24px rgba(0, 153, 255, 0.3), + 0 2px 8px rgba(0, 153, 255, 0.4); + border-radius: 0 4px 4px 0; +} + +/* Dark mode specific glow */ +[data-theme="dark"] .reading-progress-fill { + box-shadow: + 0 0 16px rgba(0, 180, 255, 0.8), + 0 0 32px rgba(0, 180, 255, 0.4), + 0 2px 12px rgba(0, 180, 255, 0.5); +} + +/* Light mode specific glow */ +[data-theme="light"] .reading-progress-fill, +:root:not([data-theme]) .reading-progress-fill { + box-shadow: + 0 0 10px rgba(0, 153, 255, 0.5), + 0 0 20px rgba(0, 153, 255, 0.25), + 0 2px 6px rgba(0, 0, 0, 0.15); +} + +/* System preference for light mode */ +@media (prefers-color-scheme: light) { + :root:not([data-theme]) .reading-progress-fill { + box-shadow: + 0 0 10px rgba(0, 153, 255, 0.5), + 0 0 20px rgba(0, 153, 255, 0.25), + 0 2px 6px rgba(0, 0, 0, 0.15); + } +} + +/* System preference for dark mode */ +@media (prefers-color-scheme: dark) { + :root:not([data-theme]) .reading-progress-fill { + box-shadow: + 0 0 16px rgba(0, 180, 255, 0.8), + 0 0 32px rgba(0, 180, 255, 0.4), + 0 2px 12px rgba(0, 180, 255, 0.5); + } } /* Focus styles for accessibility */ @@ -1137,3 +1183,652 @@ html, body { height: 300px; } } + +/* --- Enhanced Post Cards --- */ +.post-list { + display: grid; + grid-template-columns: 1fr; + gap: var(--space-2xl); + margin: var(--space-3xl) 0; +} + +@media (min-width: 768px) { + .post-list { + grid-template-columns: repeat(2, 1fr); + gap: var(--space-xl); + } +} + +@media (min-width: 1200px) { + .post-list { + grid-template-columns: repeat(3, 1fr); + } +} + +.post-card { + background: var(--surface-color); + border-radius: 12px; + overflow: hidden; + border: 1px solid var(--border-color); + transition: transform var(--transition-normal), box-shadow var(--transition-normal); + height: 100%; + display: flex; + flex-direction: column; +} + +.post-card:hover { + transform: translateY(-4px); + box-shadow: 0 12px 24px var(--shadow-color); +} + +.post-card-link { + text-decoration: none; + color: inherit; + display: flex; + flex-direction: column; + height: 100%; +} + +.post-card-image { + width: 100%; + height: 220px; + overflow: hidden; + background: var(--glass-bg); + position: relative; +} + +.post-card-image img { + width: 100%; + height: 100%; + object-fit: cover; + transition: transform 0.3s ease; +} + +.post-card:hover .post-card-image img { + transform: scale(1.05); +} + +.post-card-image-placeholder { + display: flex; + align-items: center; + justify-content: center; + background: linear-gradient(135deg, var(--accent-color-blue) 0%, var(--accent-color-yellow) 100%); + opacity: 0.1; +} + +.post-card-placeholder-content { + display: flex; + align-items: center; + justify-content: center; +} + +.post-card-placeholder-icon { + font-size: 4rem; + opacity: 0.3; +} + +.post-card-content { + padding: var(--space-lg); + display: flex; + flex-direction: column; + gap: var(--space-sm); + flex: 1; +} + +.post-card-categories { + display: flex; + gap: var(--space-xs); + flex-wrap: wrap; +} + +.post-card-category { + font-size: var(--text-xs); + font-family: var(--font-heading); + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.5px; + color: var(--accent-color-blue); + background: var(--glass-bg); + padding: 0.25rem 0.75rem; + border-radius: 20px; + border: 1px solid var(--accent-color-blue); +} + +.post-card-title { + font-family: var(--font-heading); + font-size: var(--text-xl); + font-weight: 700; + line-height: 1.3; + margin: 0; + color: var(--text-color); +} + +.post-card-link:hover .post-card-title { + color: var(--accent-color-blue); +} + +.post-card-description { + font-size: var(--text-base); + line-height: 1.6; + color: var(--text-color); + opacity: 0.8; + margin: 0; + flex: 1; +} + +.post-card-meta { + display: flex; + align-items: center; + gap: var(--space-xs); + font-size: var(--text-sm); + color: var(--text-color); + opacity: 0.6; + margin-top: auto; + padding-top: var(--space-sm); +} + +.post-card-date, +.post-card-reading-time { + font-family: var(--font-body); +} + +.post-card-separator { + opacity: 0.5; +} + +/* --- Search Functionality --- */ +.search-modal { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.8); + z-index: 9999; + display: flex; + align-items: flex-start; + justify-content: center; + padding-top: 10vh; + backdrop-filter: blur(8px); + animation: fadeIn 0.2s ease; +} + +@keyframes fadeIn { + from { opacity: 0; } + to { opacity: 1; } +} + +.search-modal-content { + background: var(--surface-color); + border-radius: 12px; + width: 90%; + max-width: 700px; + max-height: 80vh; + display: flex; + flex-direction: column; + border: 1px solid var(--border-color); + box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3); + animation: slideDown 0.3s ease; +} + +@keyframes slideDown { + from { + opacity: 0; + transform: translateY(-20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.search-header { + display: flex; + align-items: center; + gap: var(--space-sm); + padding: var(--space-lg); + border-bottom: 1px solid var(--border-color); +} + +.search-input { + flex: 1; + font-family: var(--font-body); + font-size: var(--text-lg); + padding: 0.75rem; + border: none; + background: transparent; + color: var(--text-color); + outline: none; +} + +.search-input::placeholder { + color: var(--text-color); + opacity: 0.5; +} + +.search-close { + background: none; + border: none; + color: var(--text-color); + cursor: pointer; + padding: 0.5rem; + display: flex; + align-items: center; + justify-content: center; + border-radius: 6px; + transition: all var(--transition-normal); +} + +.search-close:hover { + background: var(--glass-bg); + color: var(--accent-color-blue); +} + +.search-results { + overflow-y: auto; + padding: var(--space-sm); + max-height: calc(80vh - 100px); +} + +.search-result-item { + padding: var(--space-md); + border-radius: 8px; + margin-bottom: var(--space-sm); + transition: all var(--transition-normal); + cursor: pointer; + text-decoration: none; + color: inherit; + display: block; + border: 1px solid transparent; +} + +.search-result-item:hover { + background: var(--glass-bg); + border-color: var(--border-color); + transform: translateX(4px); +} + +.search-result-title { + font-family: var(--font-heading); + font-size: var(--text-lg); + font-weight: 700; + margin: 0 0 var(--space-xs) 0; + color: var(--text-color); +} + +.search-result-item:hover .search-result-title { + color: var(--accent-color-blue); +} + +.search-result-meta { + font-size: var(--text-sm); + color: var(--text-color); + opacity: 0.6; + margin-bottom: var(--space-xs); +} + +.search-result-description { + font-size: var(--text-base); + color: var(--text-color); + opacity: 0.8; + line-height: 1.5; + margin: 0; +} + +.search-result-tags { + display: flex; + gap: var(--space-xs); + flex-wrap: wrap; + margin-top: var(--space-sm); +} + +.search-result-tag { + font-size: var(--text-xs); + color: var(--accent-color-blue); + background: var(--glass-bg); + padding: 0.2rem 0.6rem; + border-radius: 12px; + border: 1px solid var(--accent-color-blue); +} + +.search-no-results { + text-align: center; + padding: var(--space-3xl); + color: var(--text-color); + opacity: 0.6; +} + +.search-no-results-icon { + font-size: 3rem; + margin-bottom: var(--space-md); +} + +/* --- Comments Section --- */ +.comments-section { + margin-top: var(--space-3xl); + width: 100%; + max-width: 100%; + overflow: hidden; +} + +.comments-title { + font-family: var(--font-heading); + font-size: var(--text-2xl); + font-weight: 700; + margin: 0 0 var(--space-lg) 0; + color: var(--text-color); +} + +/* Ensure Giscus is fully responsive */ +.giscus, .giscus-frame { + width: 100%; + max-width: 100%; +} + +.giscus iframe { + width: 100% !important; + max-width: 100% !important; +} + +/* Style comment container */ +.comments-section .giscus { + background: var(--surface-color); + border-radius: 8px; + padding: var(--space-md); + border: 1px solid var(--border-color); +} + +/* Mobile responsive adjustments */ +@media (max-width: 768px) { + .comments-section { + margin-top: var(--space-2xl); + } + + .comments-title { + font-size: var(--text-xl); + } + + .comments-section .giscus { + padding: var(--space-sm); + border-radius: 6px; + } +} + +/* --- Related Posts Section --- */ +.related-posts { + margin: var(--space-3xl) 0; +} + +.related-posts-title { + font-family: var(--font-heading); + font-size: var(--text-2xl); + font-weight: 700; + margin: 0 0 var(--space-lg) 0; + color: var(--text-color); +} + +.related-posts-grid { + display: grid; + grid-template-columns: 1fr; + gap: var(--space-lg); +} + +@media (min-width: 768px) { + .related-posts-grid { + grid-template-columns: repeat(2, 1fr); + } +} + +@media (min-width: 1024px) { + .related-posts-grid { + grid-template-columns: repeat(3, 1fr); + } +} + +.related-post-card { + background: var(--surface-color); + border-radius: 12px; + overflow: hidden; + border: 1px solid var(--border-color); + transition: transform var(--transition-normal), box-shadow var(--transition-normal); + height: 100%; + display: flex; + flex-direction: column; +} + +.related-post-card:hover { + transform: translateY(-4px); + box-shadow: 0 8px 16px var(--shadow-color); +} + +.related-post-link { + text-decoration: none; + color: inherit; + display: flex; + flex-direction: column; + height: 100%; +} + +.related-post-image { + width: 100%; + height: 180px; + overflow: hidden; + background: var(--glass-bg); + position: relative; +} + +.related-post-image img { + width: 100%; + height: 100%; + object-fit: cover; + transition: transform 0.3s ease; +} + +.related-post-card:hover .related-post-image img { + transform: scale(1.05); +} + +.related-post-image-placeholder { + display: flex; + align-items: center; + justify-content: center; + background: linear-gradient(135deg, var(--accent-color-blue) 0%, var(--accent-color-yellow) 100%); + opacity: 0.1; +} + +.related-post-placeholder-icon { + font-size: 3rem; + opacity: 0.3; +} + +.related-post-content { + padding: var(--space-md); + display: flex; + flex-direction: column; + gap: var(--space-xs); + flex: 1; +} + +.related-post-category { + font-size: var(--text-xs); + font-family: var(--font-heading); + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.5px; + color: var(--accent-color-blue); + background: var(--glass-bg); + padding: 0.25rem 0.75rem; + border-radius: 20px; + border: 1px solid var(--accent-color-blue); + display: inline-block; + width: fit-content; +} + +.related-post-title { + font-family: var(--font-heading); + font-size: var(--text-lg); + font-weight: 700; + line-height: 1.3; + margin: var(--space-xs) 0 0 0; + color: var(--text-color); + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.related-post-link:hover .related-post-title { + color: var(--accent-color-blue); +} + +.related-post-meta { + display: flex; + align-items: center; + gap: var(--space-xs); + font-size: var(--text-sm); + color: var(--text-color); + opacity: 0.6; + margin-top: auto; +} + +.related-post-separator { + opacity: 0.5; +} + +/* --- Newsletter Section --- */ +.newsletter-section { + margin: var(--space-3xl) 0; + background: var(--surface-color); + border: 1px solid var(--border-color); + border-radius: 12px; + padding: var(--space-2xl); + position: relative; + overflow: hidden; +} + +.newsletter-container { + text-align: center; + max-width: 600px; + margin: 0 auto; +} + +.newsletter-title { + font-family: var(--font-heading); + font-size: var(--text-2xl); + font-weight: 700; + margin: 0 0 var(--space-sm) 0; + color: var(--text-color); +} + +.newsletter-description { + font-size: var(--text-base); + line-height: 1.6; + color: var(--text-color); + opacity: 0.7; + margin: 0 0 var(--space-xl) 0; +} + +.newsletter-form { + margin-bottom: var(--space-sm); +} + +.newsletter-form-group { + display: flex; + gap: var(--space-sm); + max-width: 500px; + margin: 0 auto; +} + +@media (max-width: 600px) { + .newsletter-form-group { + flex-direction: column; + } +} + +.newsletter-input { + flex: 1; + padding: 0.875rem 1.125rem; + font-family: var(--font-body); + font-size: var(--text-base); + border: 1px solid var(--border-color); + background: var(--background-color); + color: var(--text-color); + border-radius: 8px; + outline: none; + transition: all var(--transition-normal); +} + +.newsletter-input:focus { + border-color: var(--accent-color-blue); + box-shadow: 0 0 0 3px rgba(0, 153, 255, 0.1); +} + +.newsletter-input::placeholder { + color: var(--text-color); + opacity: 0.5; +} + +.newsletter-button { + padding: 0.875rem 1.75rem; + font-family: var(--font-heading); + font-size: var(--text-base); + font-weight: 600; + background: var(--accent-color-blue); + color: #ffffff; + border: none; + border-radius: 8px; + cursor: pointer; + transition: all var(--transition-normal); + white-space: nowrap; +} + +.newsletter-button:hover { + background: #0088EE; + transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(0, 153, 255, 0.3); +} + +.newsletter-button:active { + transform: translateY(0); +} + +.newsletter-button:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.newsletter-privacy { + font-size: var(--text-sm); + color: var(--text-color); + opacity: 0.6; + margin: var(--space-md) 0 0 0; +} + +.newsletter-message { + margin-top: var(--space-md); + padding: var(--space-sm) var(--space-md); + border-radius: 6px; + font-size: var(--text-sm); +} + +.newsletter-message-success { + background: rgba(76, 175, 80, 0.1); + color: #4CAF50; + border: 1px solid rgba(76, 175, 80, 0.3); +} + +[data-theme="dark"] .newsletter-message-success { + background: rgba(76, 175, 80, 0.15); + color: #66BB6A; +} + +.newsletter-message-error { + background: rgba(244, 67, 54, 0.1); + color: #F44336; + border: 1px solid rgba(244, 67, 54, 0.3); +} + +[data-theme="dark"] .newsletter-message-error { + background: rgba(244, 67, 54, 0.15); + color: #EF5350; +} diff --git a/assets/js/main.js b/assets/js/main.js index 50367ac..1bad099 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -77,7 +77,7 @@ // Performance: Add loading states function initLoadingStates() { - const elements = document.querySelectorAll('.hero-headline, .post-item'); + const elements = document.querySelectorAll('.hero-headline, .post-item, .post-card'); // Use Intersection Observer for progressive loading const observer = new IntersectionObserver((entries) => { diff --git a/assets/js/search.js b/assets/js/search.js new file mode 100644 index 0000000..27f99b5 --- /dev/null +++ b/assets/js/search.js @@ -0,0 +1,146 @@ +// Simple client-side search functionality +(function() { + 'use strict'; + + let searchIndex = []; + let searchModal, searchInput, searchResults, searchClose; + + // Simple fuzzy search function + function fuzzySearch(query, text) { + if (!query || !text) return false; + + query = query.toLowerCase(); + text = text.toLowerCase(); + + // Direct match gets highest priority + if (text.includes(query)) return true; + + // Fuzzy match - all query chars appear in order + let queryIndex = 0; + for (let i = 0; i < text.length && queryIndex < query.length; i++) { + if (text[i] === query[queryIndex]) { + queryIndex++; + } + } + return queryIndex === query.length; + } + + // Search function + function performSearch(query) { + if (!query || query.length < 2) { + searchResults.innerHTML = '
๐Ÿ”

Start typing to search posts...

'; + return; + } + + const results = searchIndex.filter(post => { + return fuzzySearch(query, post.title) || + fuzzySearch(query, post.description) || + fuzzySearch(query, post.content) || + (post.tags && post.tags.some(tag => fuzzySearch(query, tag))) || + (post.categories && post.categories.some(cat => fuzzySearch(query, cat))); + }); + + if (results.length === 0) { + searchResults.innerHTML = '
๐Ÿ˜•

No posts found matching your search.

'; + return; + } + + searchResults.innerHTML = results.map(post => { + const tags = post.tags ? post.tags.slice(0, 3).map(tag => + `${tag}` + ).join('') : ''; + + return ` + +

${post.title}

+
${post.date}
+

${post.description || post.content}

+ ${tags ? `
${tags}
` : ''} +
+ `; + }).join(''); + } + + // Open search modal + function openSearch() { + searchModal.style.display = 'flex'; + document.body.style.overflow = 'hidden'; + setTimeout(() => searchInput.focus(), 100); + } + + // Close search modal + function closeSearch() { + searchModal.style.display = 'none'; + document.body.style.overflow = ''; + searchInput.value = ''; + searchResults.innerHTML = ''; + } + + // Load search index + function loadSearchIndex() { + fetch('/index.json') + .then(response => response.json()) + .then(data => { + searchIndex = data; + }) + .catch(error => { + console.error('Error loading search index:', error); + }); + } + + // Initialize search + function initSearch() { + searchModal = document.getElementById('search-modal'); + searchInput = document.getElementById('search-input'); + searchResults = document.getElementById('search-results'); + searchClose = document.getElementById('search-close'); + + if (!searchModal || !searchInput || !searchResults) return; + + // Load search index + loadSearchIndex(); + + // Event listeners + searchClose.addEventListener('click', closeSearch); + + // Close on background click + searchModal.addEventListener('click', (e) => { + if (e.target === searchModal) { + closeSearch(); + } + }); + + // Close on Escape key + document.addEventListener('keydown', (e) => { + if (e.key === 'Escape' && searchModal.style.display === 'flex') { + closeSearch(); + } + // Open with Cmd/Ctrl + K + if ((e.metaKey || e.ctrlKey) && e.key === 'k') { + e.preventDefault(); + openSearch(); + } + }); + + // Perform search as user types + let searchTimeout; + searchInput.addEventListener('input', (e) => { + clearTimeout(searchTimeout); + searchTimeout = setTimeout(() => { + performSearch(e.target.value); + }, 200); + }); + + // Show initial message + searchResults.innerHTML = '
๐Ÿ”

Start typing to search posts...

'; + } + + // Initialize when DOM is ready + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', initSearch); + } else { + initSearch(); + } + +})(); + diff --git a/hugo.toml b/hugo.toml index e577214..5ca2396 100644 --- a/hugo.toml +++ b/hugo.toml @@ -5,6 +5,11 @@ enableRobotsTXT = true enableGitInfo = true canonifyURLs = true +# Output formats for search +[outputs] + home = ["HTML", "RSS", "JSON"] + section = ["HTML", "RSS"] + # SEO and Performance [sitemap] changefreq = "weekly" @@ -43,6 +48,63 @@ canonifyURLs = true googleAnalytics = "" # Add your GA4 tracking ID vercelAnalytics = true # Enable Vercel Analytics + # Comments System Configuration + [params.comments] + enabled = false + system = "giscus" # Options: "giscus", "utterances", "disqus" + + # Giscus Configuration (GitHub Discussions) + # To set up: Visit https://giscus.app/ and follow the setup guide + # You'll need to enable Discussions on your GitHub repo + [params.comments.giscus] + repo = "RexO77/blogs" # Your GitHub repo + repoId = "R_kgDOPTHrAg" # From giscus.app + category = "Ideas" # Discussion category name + categoryId = "DIC_kwDOPTHrAs4CxjGf" # From giscus.app + mapping = "pathname" # How to map posts to discussions + strict = "0" + reactionsEnabled = "1" + emitMetadata = "0" + inputPosition = "bottom" + theme = "preferred_color_scheme" + lang = "en" + + # Alternative: Utterances (GitHub Issues) + [params.comments.utterances] + repo = "" # Your GitHub username/repo + issueTerm = "pathname" + theme = "github-light" + + # Alternative: Disqus + [params.comments.disqus] + shortname = "" # Your Disqus shortname + + # Newsletter Configuration + [params.newsletter] + enabled = true + title = "Stay in the Loop" + description = "Get weekly insights on AI, tech, and career advice. Join readers who stay ahead of the curve." + provider = "mailchimp" # Options: "mailchimp", "convertkit", "substack", "custom" + + # Mailchimp Configuration + [params.newsletter.mailchimp] + action = "https://tech.us21.list-manage.com/subscribe/post?u=YOUR_USER_ID&id=YOUR_LIST_ID" # UPDATE THIS! + hiddenField = "b_YOUR_USER_ID_YOUR_LIST_ID" # Anti-bot field name + + # ConvertKit Configuration + [params.newsletter.convertkit] + action = "https://app.convertkit.com/forms/YOUR_FORM_ID/subscriptions" # UPDATE THIS! + formId = "YOUR_FORM_ID" + uid = "YOUR_UID" + + # Substack Configuration + [params.newsletter.substack] + url = "https://yoursubstack.substack.com" # UPDATE THIS! + + # Custom Configuration (for your own backend) + [params.newsletter.custom] + action = "/api/newsletter/subscribe" # Your API endpoint + # Performance lazyLoading = true @@ -110,3 +172,18 @@ canonifyURLs = true category = "categories" tag = "tags" series = "series" + +# Related content configuration +[related] + threshold = 80 + includeNewer = true + toLower = true + [[related.indices]] + name = "tags" + weight = 100 + [[related.indices]] + name = "categories" + weight = 80 + [[related.indices]] + name = "date" + weight = 10 diff --git a/hugo_stats.json b/hugo_stats.json index 728285e..13a3f50 100644 --- a/hugo_stats.json +++ b/hugo_stats.json @@ -13,9 +13,11 @@ "em", "figcaption", "figure", + "form", "h1", "h2", "h3", + "h4", "head", "header", "hr", @@ -23,6 +25,7 @@ "img", "input", "li", + "line", "link", "main", "meta", @@ -38,6 +41,7 @@ "strong", "style", "sup", + "svg", "table", "tbody", "td", @@ -69,6 +73,15 @@ "is-active", "logo", "main-site-link", + "newsletter-button", + "newsletter-container", + "newsletter-description", + "newsletter-form", + "newsletter-form-group", + "newsletter-input", + "newsletter-privacy", + "newsletter-section", + "newsletter-title", "pager", "pager-next", "pager-number", @@ -76,12 +89,26 @@ "pager-prev", "pagination", "pagination-inner", + "post-card", + "post-card-categories", + "post-card-category", + "post-card-content", + "post-card-date", + "post-card-description", + "post-card-image", + "post-card-image-placeholder", + "post-card-link", + "post-card-meta", + "post-card-placeholder-content", + "post-card-placeholder-icon", + "post-card-reading-time", + "post-card-separator", + "post-card-title", "post-category-link", "post-content", "post-description", "post-divider", "post-header", - "post-item", "post-list", "post-meta", "post-meta-separator", @@ -98,7 +125,25 @@ "post-tags-list", "post-tags-title", "post-title", + "related-post-card", + "related-post-category", + "related-post-content", + "related-post-image", + "related-post-link", + "related-post-meta", + "related-post-reading-time", + "related-post-separator", + "related-post-title", + "related-posts", + "related-posts-grid", + "related-posts-title", "responsive-image", + "search-close", + "search-header", + "search-input", + "search-modal", + "search-modal-content", + "search-results", "site-header", "social-button", "social-button-linkedin", @@ -218,6 +263,10 @@ "references--field-notes", "saving-our-brains-before-theyre-toast", "scaling-experience-not-compute", + "search-close", + "search-input", + "search-modal", + "search-results", "so-how-the-heck-do-you-protect-yourself", "so-what", "so-what-the-hell-do-we-do", diff --git a/layouts/_default/baseof.html b/layouts/_default/baseof.html index 5cafc40..849964f 100644 --- a/layouts/_default/baseof.html +++ b/layouts/_default/baseof.html @@ -50,6 +50,22 @@ Main Site + + +
{{ block "main" . }}{{ end }} @@ -59,6 +75,9 @@ {{ $js := resources.Get "js/main.js" | resources.Minify | resources.Fingerprint }} + {{ $search := resources.Get "js/search.js" | resources.Minify | resources.Fingerprint }} + + {{ if .Site.Params.vercelAnalytics }} diff --git a/layouts/_default/index.json b/layouts/_default/index.json new file mode 100644 index 0000000..eab12ef --- /dev/null +++ b/layouts/_default/index.json @@ -0,0 +1,14 @@ +{{- $.Scratch.Add "index" slice -}} +{{- range where .Site.RegularPages "Section" "posts" -}} + {{- $.Scratch.Add "index" (dict + "title" .Title + "description" .Description + "content" (.Plain | truncate 500) + "permalink" .Permalink + "date" (.Date.Format "Jan 2, 2006") + "categories" .Params.categories + "tags" .Params.tags + ) -}} +{{- end -}} +{{- $.Scratch.Get "index" | jsonify -}} + diff --git a/layouts/_default/list.html b/layouts/_default/list.html index 427d85e..e73e076 100644 --- a/layouts/_default/list.html +++ b/layouts/_default/list.html @@ -13,9 +13,72 @@

{{ end }} {{ $p := .Paginate $pages }} {{ range $p.Pages }} -
-

{{ .Title }}

- +
+ + {{- $thumbnail := "" }} + {{- if .Params.thumbnail }} + {{- $thumbnail = .Params.thumbnail }} + {{- else }} + {{- /* Look for a file with "thumbnail" in the name first */ -}} + {{- range .Resources.ByType "image" }} + {{- if or (in .Name "thumbnail") (in .Name "Thumbnail") }} + {{- $thumbnail = .RelPermalink }} + {{- break }} + {{- end }} + {{- end }} + {{- /* If no thumbnail found, use the first image */ -}} + {{- if not $thumbnail }} + {{- $images := .Resources.ByType "image" }} + {{- if $images }} + {{- with index $images 0 }} + {{- $thumbnail = .RelPermalink }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + + {{- if $thumbnail }} +
+ {{- if .Params.thumbnail }} + {{ .Title }} + {{- else }} + {{ .Title }} + {{- end }} +
+ {{- else }} +
+
+ ๐Ÿ“ +
+
+ {{- end }} + +
+ {{- if .Params.categories }} +
+ {{- range first 2 .Params.categories }} + {{ . }} + {{- end }} +
+ {{- end }} + +

{{ .Title }}

+ + {{- if .Description }} +

{{ .Description | truncate 150 }}

+ {{- else }} +

{{ .Summary | truncate 150 }}

+ {{- end }} + +
+ + โ€ข + {{ .ReadingTime }} min read +
+
+
{{ end }} diff --git a/layouts/_default/single.html b/layouts/_default/single.html index ac52481..d2f596a 100644 --- a/layouts/_default/single.html +++ b/layouts/_default/single.html @@ -44,6 +44,12 @@ {{- end }} + + {{ partial "related-posts.html" . }} + + + {{ partial "newsletter.html" . }} + + + + {{ partial "comments.html" . }}
{{ end }} diff --git a/layouts/partials/comments.html b/layouts/partials/comments.html new file mode 100644 index 0000000..94ce09f --- /dev/null +++ b/layouts/partials/comments.html @@ -0,0 +1,83 @@ +{{- if .Site.Params.comments.enabled -}} +
+

Comments

+ + {{- if eq .Site.Params.comments.system "giscus" -}} + + + + + + {{- end -}} + + {{- if eq .Site.Params.comments.system "utterances" -}} + + + {{- end -}} + + {{- if eq .Site.Params.comments.system "disqus" -}} + +
+ + + {{- end -}} +
+{{- end -}} + diff --git a/layouts/partials/newsletter.html b/layouts/partials/newsletter.html new file mode 100644 index 0000000..a46679d --- /dev/null +++ b/layouts/partials/newsletter.html @@ -0,0 +1,99 @@ +{{- if .Site.Params.newsletter.enabled -}} + +{{- end -}} + diff --git a/layouts/partials/related-posts.html b/layouts/partials/related-posts.html new file mode 100644 index 0000000..529ebd8 --- /dev/null +++ b/layouts/partials/related-posts.html @@ -0,0 +1,68 @@ +{{- $related := .Site.RegularPages.Related . | first 3 -}} +{{- if $related -}} +
+ + +
+{{- end -}} + diff --git a/readme.md b/readme.md index 25d52bb..9befa9c 100644 --- a/readme.md +++ b/readme.md @@ -1,134 +1,282 @@ -# IDEA LAB โ€“ Hugo Blog +[bep]: https://github.com/bep +[bugs]: https://github.com/gohugoio/hugo/issues?q=is%3Aopen+is%3Aissue+label%3ABug +[contributing]: CONTRIBUTING.md +[create a proposal]: https://github.com/gohugoio/hugo/issues/new?labels=Proposal%2C+NeedsTriage&template=feature_request.md +[documentation repository]: https://github.com/gohugoio/hugoDocs +[documentation]: https://gohugo.io/documentation +[dragonfly bsd, freebsd, netbsd, and openbsd]: https://gohugo.io/installation/bsd +[features]: https://gohugo.io/about/features/ +[forum]: https://discourse.gohugo.io +[friends]: https://github.com/gohugoio/hugo/graphs/contributors +[go]: https://go.dev/ +[hugo modules]: https://gohugo.io/hugo-modules/ +[installation]: https://gohugo.io/installation +[issue queue]: https://github.com/gohugoio/hugo/issues +[linux]: https://gohugo.io/installation/linux +[macos]: https://gohugo.io/installation/macos +[prebuilt binary]: https://github.com/gohugoio/hugo/releases/latest +[requesting help]: https://discourse.gohugo.io/t/requesting-help/9132 +[spf13]: https://github.com/spf13 +[static site generator]: https://en.wikipedia.org/wiki/Static_site_generator +[support]: https://discourse.gohugo.io +[themes]: https://themes.gohugo.io/ +[website]: https://gohugo.io +[windows]: https://gohugo.io/installation/windows -A modern, minimal, and customizable blog built with [Hugo](https://gohugo.io/). This project is set up for rapid content publishing and easy design customization, inspired by clean, interactive web aesthetics. +Hugo -## Features -- **No external theme**: All templates and styles are custom, found in the `layouts` and `static` folders. -- **Modern, bold homepage**: Custom hero headline with interactive elements (CSS-based, easily swappable for 3D/SVG). -- **Pagination**: Configurable via `hugo.toml`. -- **Easy content management**: Write posts in Markdown under `content/posts/`. -- **Custom Fonts**: Uses Satoshi and Unbounded for a unique, modern look. +A fast and flexible static site generator built with love by [bep], [spf13], and [friends] in [Go]. -## Project Structure +--- -``` -blog.nischalskanda.tech/ -โ”œโ”€โ”€ archetypes/ -โ”‚ โ””โ”€โ”€ default.md # Archetype for new posts -โ”œโ”€โ”€ content/ -โ”‚ โ””โ”€โ”€ posts/ -โ”‚ โ””โ”€โ”€ my-first-post.md -โ”œโ”€โ”€ layouts/ -โ”‚ โ””โ”€โ”€ _default/ -โ”‚ โ”œโ”€โ”€ baseof.html # Main HTML skeleton -โ”‚ โ”œโ”€โ”€ list.html # Homepage/blog list template -โ”‚ โ””โ”€โ”€ single.html # Single post template -โ”œโ”€โ”€ assets/ -โ”‚ โ””โ”€โ”€ css/ -โ”‚ โ””โ”€โ”€ style.css # Custom CSS (processed via Hugo Pipes) -โ”œโ”€โ”€ hugo.toml # Main site configuration -โ””โ”€โ”€ ... (other Hugo folders) -``` +[![GoDoc](https://godoc.org/github.com/gohugoio/hugo?status.svg)](https://godoc.org/github.com/gohugoio/hugo) +[![Tests on Linux, MacOS and Windows](https://github.com/gohugoio/hugo/workflows/Test/badge.svg)](https://github.com/gohugoio/hugo/actions?query=workflow%3ATest) +[![Go Report Card](https://goreportcard.com/badge/github.com/gohugoio/hugo)](https://goreportcard.com/report/github.com/gohugoio/hugo) -## Quick Start +[Website] | [Installation] | [Documentation] | [Support] | [Contributing] | Mastodon -### 1. Prerequisites -- [Install Hugo](https://gohugo.io/getting-started/install/) (e.g. `brew install hugo` on macOS) +## Overview -### 2. Clone or Copy This Project -``` -git clone -cd blog.nischalskanda.tech +Hugo is a [static site generator] written in [Go], optimized for speed and designed for flexibility. With its advanced templating system and fast asset pipelines, Hugo renders a complete site in seconds, often less. + +Due to its flexible framework, multilingual support, and powerful taxonomy system, Hugo is widely used to create: + +- Corporate, government, nonprofit, education, news, event, and project sites +- Documentation sites +- Image portfolios +- Landing pages +- Business, professional, and personal blogs +- Resumes and CVs + +Use Hugo's embedded web server during development to instantly see changes to content, structure, behavior, and presentation. Then deploy the site to your host, or push changes to your Git provider for automated builds and deployment. + +Hugo's fast asset pipelines include: + +- Image processing – Convert, resize, crop, rotate, adjust colors, apply filters, overlay text and images, and extract EXIF data +- JavaScript bundling – Transpile TypeScript and JSX to JavaScript, bundle, tree shake, minify, create source maps, and perform SRI hashing. +- Sass processing – Transpile Sass to CSS, bundle, tree shake, minify, create source maps, perform SRI hashing, and integrate with PostCSS +- Tailwind CSS processing – Compile Tailwind CSS utility classes into standard CSS, bundle, tree shake, optimize, minify, perform SRI hashing, and integrate with PostCSS + +And with [Hugo Modules], you can share content, assets, data, translations, themes, templates, and configuration with other projects via public or private Git repositories. + +See the [features] section of the documentation for a comprehensive summary of Hugo's capabilities. + +## Sponsors + +

 

+

+ Linode +    + The complete IDE crafted for professional Go developers. +     + PinMe. +

+ +## Editions + +Hugo is available in three editions: standard, extended, and extended/deploy. While the standard edition provides core functionality, the extended and extended/deploy editions offer advanced features. + +Feature|extended edition|extended/deploy edition +:--|:-:|:-: +Encode to the WebP format when [processing images]. You can decode WebP images with any edition.|:heavy_check_mark:|:heavy_check_mark: +[Transpile Sass to CSS] using the embedded LibSass transpiler. You can use the [Dart Sass] transpiler with any edition.|:heavy_check_mark:|:heavy_check_mark: +Deploy your site directly to a Google Cloud Storage bucket, an AWS S3 bucket, or an Azure Storage container. See [details].|:x:|:heavy_check_mark: + +[dart sass]: https://gohugo.io/functions/css/sass/#dart-sass +[processing images]: https://gohugo.io/content-management/image-processing/ +[transpile sass to css]: https://gohugo.io/functions/css/sass/ +[details]: https://gohugo.io/hosting-and-deployment/hugo-deploy/ + +Unless your specific deployment needs require the extended/deploy edition, we recommend the extended edition. + +## Installation + +Install Hugo from a [prebuilt binary], package manager, or package repository. Please see the installation instructions for your operating system: + +- [macOS] +- [Linux] +- [Windows] +- [DragonFly BSD, FreeBSD, NetBSD, and OpenBSD] + +## Build from source + +Prerequisites to build Hugo from source: + +- Standard edition: Go 1.23.0 or later +- Extended edition: Go 1.23.0 or later, and GCC +- Extended/deploy edition: Go 1.23.0 or later, and GCC + +Build the standard edition: + +```text +go install github.com/gohugoio/hugo@latest ``` -### 3. Run the Development Server +Build the extended edition: -**Option 1: Use the development script (Recommended)** -```bash -./dev.sh +```text +CGO_ENABLED=1 go install -tags extended github.com/gohugoio/hugo@latest ``` -**Option 2: Manual command** -```bash -hugo server --buildDrafts --buildFuture --baseURL="http://localhost:1313" +Build the extended/deploy edition: + +```text +CGO_ENABLED=1 go install -tags extended,withdeploy github.com/gohugoio/hugo@latest ``` -Visit [http://localhost:1313](http://localhost:1313) in your browser. +## Star History -**Note:** The development script ensures all links point to localhost instead of the production URL for proper local development and navigation. +[![Star History Chart](https://api.star-history.com/svg?repos=gohugoio/hugo&type=Timeline)](https://star-history.com/#gohugoio/hugo&Timeline) -### 4. Add Your First Post -``` -hugo new posts/my-second-post.md -``` -Edit the new file in `content/posts/` and set `draft: false` to publish. +## Documentation -## Configuration +Hugo's [documentation] includes installation instructions, a quick start guide, conceptual explanations, reference information, and examples. -Edit `hugo.toml` to change site settings: -```toml -baseURL = "https://blog.nischalskanda.tech/" -languageCode = "en-us" -title = "IDEA LAB" +Please submit documentation issues and pull requests to the [documentation repository]. -[pagination] - pagerSize = 5 +## Support -[params] - description = "A space for ideas, design, and technology." -``` +Please **do not use the issue queue** for questions or troubleshooting. Unless you are certain that your issue is a software defect, use the [forum]. -## Customization -- **Homepage Headline**: Edit `layouts/_default/list.html` for the hero section. -- **Navigation**: Change links in `layouts/_default/baseof.html`. -- **Styles**: Tweak `assets/css/style.css` for colors, fonts, and layout. -- **Fonts**: Satoshi and Unbounded fonts are loaded in `baseof.html` and defined via `@font-face` in CSS. -- **Interactive Elements**: The `.interactive-o` and `.interactive-arrow` spans in the hero headline are styled with CSS. Replace with SVG or 3D embeds as desired. - -## Directory Details -- `archetypes/default.md`: Template for new posts (auto-filled front matter). -- `content/posts/`: Your blog posts in Markdown. -- `layouts/_default/`: Main HTML templates (base, list, single). -- `assets/css/style.css`: All custom styles. -- `hugo.toml`: Site config. - -## Deployment -1. Build the static site for production: - ```bash - ./build.sh - ``` - Or manually: - ```bash - hugo --cleanDestinationDir --minify - ``` - -2. (Optional) Verify URLs are correct: - ```bash - ./verify-urls.sh - ``` - -3. Deploy the `public/` directory to your static host (Netlify, Vercel, GitHub Pages, etc). - -**Important:** Always use the build script or manual `hugo` command for production builds. Never deploy files generated with the development server as they contain localhost URLs. - -## Development vs Production Workflow - -### For Local Development -- Use: `./dev.sh` or `hugo server --baseURL="http://localhost:1313"` -- Result: All links point to localhost for local testing -- Files: Development files in memory (not for deployment) - -### For Production Deployment -- Use: `./build.sh` or `hugo --cleanDestinationDir --minify` -- Result: All links point to production domain -- Files: Production-ready files in `./public/` directory - -## Troubleshooting -- If you see errors about `paginate` or themes, ensure your `hugo.toml` matches the config above and does **not** include a `theme` line. -- If you want to use a theme, set `theme = "your-theme-name"` and add it to the `themes/` directory. - -## License -MIT or your preferred license. +Hugoโ€™s [forum] is an active community of users and developers who answer questions, share knowledge, and provide examples. A quick search of over 20,000 topics will often answer your question. Please be sure to read about [requesting help] before asking your first question. ---- -Inspired by clean, interactive web design. Built with โค๏ธ using Hugo. +## Contributing + +You can contribute to the Hugo project by: + +- Answering questions on the [forum] +- Improving the [documentation] +- Monitoring the [issue queue] +- Creating or improving [themes] +- Squashing [bugs] + +Please submit documentation issues and pull requests to the [documentation repository]. + +If you have an idea for an enhancement or new feature, create a new topic on the [forum] in the "Feature" category. This will help you to: + +- Determine if the capability already exists +- Measure interest +- Refine the concept + +If there is sufficient interest, [create a proposal]. Do not submit a pull request until the project lead accepts the proposal. + +For a complete guide to contributing to Hugo, see the [Contribution Guide](CONTRIBUTING.md). + +## Dependencies + +Hugo stands on the shoulders of great open source libraries. Run `hugo env --logLevel info` to display a list of dependencies. + +
+See current dependencies + +```text +github.com/BurntSushi/locker="v0.0.0-20171006230638-a6e239ea1c69" +github.com/PuerkitoBio/goquery="v1.10.1" +github.com/alecthomas/chroma/v2="v2.15.0" +github.com/andybalholm/cascadia="v1.3.3" +github.com/armon/go-radix="v1.0.1-0.20221118154546-54df44f2176c" +github.com/bep/clocks="v0.5.0" +github.com/bep/debounce="v1.2.0" +github.com/bep/gitmap="v1.6.0" +github.com/bep/goat="v0.5.0" +github.com/bep/godartsass/v2="v2.3.2" +github.com/bep/golibsass="v1.2.0" +github.com/bep/gowebp="v0.3.0" +github.com/bep/imagemeta="v0.8.4" +github.com/bep/lazycache="v0.7.0" +github.com/bep/logg="v0.4.0" +github.com/bep/mclib="v1.20400.20402" +github.com/bep/overlayfs="v0.9.2" +github.com/bep/simplecobra="v0.5.0" +github.com/bep/tmc="v0.5.1" +github.com/cespare/xxhash/v2="v2.3.0" +github.com/clbanning/mxj/v2="v2.7.0" +github.com/cpuguy83/go-md2man/v2="v2.0.4" +github.com/disintegration/gift="v1.2.1" +github.com/dlclark/regexp2="v1.11.5" +github.com/dop251/goja="v0.0.0-20250125213203-5ef83b82af17" +github.com/evanw/esbuild="v0.24.2" +github.com/fatih/color="v1.18.0" +github.com/frankban/quicktest="v1.14.6" +github.com/fsnotify/fsnotify="v1.8.0" +github.com/getkin/kin-openapi="v0.129.0" +github.com/ghodss/yaml="v1.0.0" +github.com/go-openapi/jsonpointer="v0.21.0" +github.com/go-openapi/swag="v0.23.0" +github.com/go-sourcemap/sourcemap="v2.1.4+incompatible" +github.com/gobuffalo/flect="v1.0.3" +github.com/gobwas/glob="v0.2.3" +github.com/gohugoio/go-i18n/v2="v2.1.3-0.20230805085216-e63c13218d0e" +github.com/gohugoio/hashstructure="v0.5.0" +github.com/gohugoio/httpcache="v0.7.0" +github.com/gohugoio/hugo-goldmark-extensions/extras="v0.2.0" +github.com/gohugoio/hugo-goldmark-extensions/passthrough="v0.3.0" +github.com/gohugoio/locales="v0.14.0" +github.com/gohugoio/localescompressed="v1.0.1" +github.com/golang/freetype="v0.0.0-20170609003504-e2365dfdc4a0" +github.com/google/go-cmp="v0.6.0" +github.com/google/pprof="v0.0.0-20250208200701-d0013a598941" +github.com/gorilla/websocket="v1.5.3" +github.com/hairyhenderson/go-codeowners="v0.7.0" +github.com/hashicorp/golang-lru/v2="v2.0.7" +github.com/jdkato/prose="v1.2.1" +github.com/josharian/intern="v1.0.0" +github.com/kr/pretty="v0.3.1" +github.com/kr/text="v0.2.0" +github.com/kyokomi/emoji/v2="v2.2.13" +github.com/lucasb-eyer/go-colorful="v1.2.0" +github.com/mailru/easyjson="v0.7.7" +github.com/makeworld-the-better-one/dither/v2="v2.4.0" +github.com/marekm4/color-extractor="v1.2.1" +github.com/mattn/go-colorable="v0.1.13" +github.com/mattn/go-isatty="v0.0.20" +github.com/mattn/go-runewidth="v0.0.9" +github.com/mazznoer/csscolorparser="v0.1.5" +github.com/mitchellh/mapstructure="v1.5.1-0.20231216201459-8508981c8b6c" +github.com/mohae/deepcopy="v0.0.0-20170929034955-c48cc78d4826" +github.com/muesli/smartcrop="v0.3.0" +github.com/niklasfasching/go-org="v1.7.0" +github.com/oasdiff/yaml3="v0.0.0-20241210130736-a94c01f36349" +github.com/oasdiff/yaml="v0.0.0-20241210131133-6b86fb107d80" +github.com/olekukonko/tablewriter="v0.0.5" +github.com/pbnjay/memory="v0.0.0-20210728143218-7b4eea64cf58" +github.com/pelletier/go-toml/v2="v2.2.3" +github.com/perimeterx/marshmallow="v1.1.5" +github.com/pkg/browser="v0.0.0-20240102092130-5ac0b6a4141c" +github.com/pkg/errors="v0.9.1" +github.com/rivo/uniseg="v0.4.7" +github.com/rogpeppe/go-internal="v1.13.1" +github.com/russross/blackfriday/v2="v2.1.0" +github.com/sass/libsass="3.6.6" +github.com/spf13/afero="v1.11.0" +github.com/spf13/cast="v1.7.1" +github.com/spf13/cobra="v1.8.1" +github.com/spf13/fsync="v0.10.1" +github.com/spf13/pflag="v1.0.6" +github.com/tdewolff/minify/v2="v2.20.37" +github.com/tdewolff/parse/v2="v2.7.15" +github.com/tetratelabs/wazero="v1.8.2" +github.com/webmproject/libwebp="v1.3.2" +github.com/yuin/goldmark-emoji="v1.0.4" +github.com/yuin/goldmark="v1.7.8" +go.uber.org/automaxprocs="v1.5.3" +golang.org/x/crypto="v0.33.0" +golang.org/x/exp="v0.0.0-20250210185358-939b2ce775ac" +golang.org/x/image="v0.24.0" +golang.org/x/mod="v0.23.0" +golang.org/x/net="v0.35.0" +golang.org/x/sync="v0.11.0" +golang.org/x/sys="v0.30.0" +golang.org/x/text="v0.22.0" +golang.org/x/tools="v0.30.0" +golang.org/x/xerrors="v0.0.0-20240903120638-7835f813f4da" +gonum.org/v1/plot="v0.15.0" +google.golang.org/protobuf="v1.36.5" +gopkg.in/yaml.v2="v2.4.0" +gopkg.in/yaml.v3="v3.0.1" +oss.terrastruct.com/d2="v0.6.9" +oss.terrastruct.com/util-go="v0.0.0-20241005222610-44c011a04896" +rsc.io/qr="v0.2.0" +software.sslmate.com/src/go-pkcs12="v0.2.0" +``` +
From 87058add5de1aa128710c57260098a7dec515789 Mon Sep 17 00:00:00 2001 From: rexO77 Date: Sun, 9 Nov 2025 12:13:17 +0530 Subject: [PATCH 2/2] Word search --- assets/css/style.css | 18 ++++++ assets/js/search.js | 125 ++++++++++++++++++++---------------- build.sh | 5 ++ hugo.toml | 4 +- layouts/_default/index.json | 14 ---- 5 files changed, 93 insertions(+), 73 deletions(-) delete mode 100644 layouts/_default/index.json diff --git a/assets/css/style.css b/assets/css/style.css index 5aee516..9412c5e 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -1430,6 +1430,15 @@ html, body { max-height: calc(80vh - 100px); } +.search-result-count { + font-size: var(--text-sm); + color: var(--text-color); + opacity: 0.6; + padding: var(--space-sm) var(--space-md); + margin-bottom: var(--space-xs); + text-align: center; +} + .search-result-item { padding: var(--space-md); border-radius: 8px; @@ -1503,6 +1512,15 @@ html, body { margin-bottom: var(--space-md); } +/* Pagefind search term highlighting */ +.search-result-description mark { + background-color: var(--accent-color-blue); + color: var(--bg-color); + padding: 0.1em 0.2em; + border-radius: 3px; + font-weight: 500; +} + /* --- Comments Section --- */ .comments-section { margin-top: var(--space-3xl); diff --git a/assets/js/search.js b/assets/js/search.js index 27f99b5..c9a026a 100644 --- a/assets/js/search.js +++ b/assets/js/search.js @@ -1,64 +1,84 @@ -// Simple client-side search functionality +// Pagefind search integration (function() { 'use strict'; - let searchIndex = []; + let pagefind; + let pagefindLoaded = false; let searchModal, searchInput, searchResults, searchClose; - // Simple fuzzy search function - function fuzzySearch(query, text) { - if (!query || !text) return false; + // Lazy load Pagefind only when needed + async function ensurePagefind() { + if (pagefindLoaded) return; - query = query.toLowerCase(); - text = text.toLowerCase(); - - // Direct match gets highest priority - if (text.includes(query)) return true; - - // Fuzzy match - all query chars appear in order - let queryIndex = 0; - for (let i = 0; i < text.length && queryIndex < query.length; i++) { - if (text[i] === query[queryIndex]) { - queryIndex++; - } + try { + pagefind = await import('/pagefind/pagefind.js'); + pagefindLoaded = true; + } catch (error) { + console.error('Error loading Pagefind:', error); + throw error; } - return queryIndex === query.length; } - // Search function - function performSearch(query) { + // Perform search with Pagefind + async function performSearch(query) { if (!query || query.length < 2) { searchResults.innerHTML = '
๐Ÿ”

Start typing to search posts...

'; return; } - const results = searchIndex.filter(post => { - return fuzzySearch(query, post.title) || - fuzzySearch(query, post.description) || - fuzzySearch(query, post.content) || - (post.tags && post.tags.some(tag => fuzzySearch(query, tag))) || - (post.categories && post.categories.some(cat => fuzzySearch(query, cat))); - }); + // Show loading state immediately + searchResults.innerHTML = '
โณ

Searching...

'; - if (results.length === 0) { - searchResults.innerHTML = '
๐Ÿ˜•

No posts found matching your search.

'; - return; + try { + // Ensure Pagefind is loaded + await ensurePagefind(); + + const search = await pagefind.search(query); + + if (search.results.length === 0) { + searchResults.innerHTML = '
๐Ÿ˜•

No posts found matching your search.

'; + return; + } + + // Limit to first 10 results for speed + const limitedResults = search.results.slice(0, 10); + + // Load data for limited results + const results = await Promise.all( + limitedResults.map(r => r.data()) + ); + + displayResults(results, search.results.length); + } catch (error) { + console.error('Search error:', error); + searchResults.innerHTML = '
โš ๏ธ

Search error. Please try again.

'; } + } + + // Display search results + function displayResults(results, totalCount) { + const resultCount = totalCount > results.length + ? `
Showing ${results.length} of ${totalCount} results
` + : `
${results.length} result${results.length !== 1 ? 's' : ''}
`; - searchResults.innerHTML = results.map(post => { - const tags = post.tags ? post.tags.slice(0, 3).map(tag => - `${tag}` - ).join('') : ''; + const resultsHtml = results.map(result => { + // Extract tags from meta if available + const tags = result.meta.tags ? + result.meta.tags.slice(0, 3).map(tag => + `${tag}` + ).join('') : ''; return ` - -

${post.title}

-
${post.date}
-

${post.description || post.content}

+
+

${result.meta.title || 'Untitled'}

+
${result.meta.date || ''}
+

${result.excerpt}

${tags ? `
${tags}
` : ''}
`; }).join(''); + + searchResults.innerHTML = resultCount + resultsHtml; } // Open search modal @@ -66,6 +86,13 @@ searchModal.style.display = 'flex'; document.body.style.overflow = 'hidden'; setTimeout(() => searchInput.focus(), 100); + + // Preload Pagefind when modal opens (lazy load) + if (!pagefindLoaded) { + ensurePagefind().catch(err => + console.error('Failed to preload Pagefind:', err) + ); + } } // Close search modal @@ -73,19 +100,7 @@ searchModal.style.display = 'none'; document.body.style.overflow = ''; searchInput.value = ''; - searchResults.innerHTML = ''; - } - - // Load search index - function loadSearchIndex() { - fetch('/index.json') - .then(response => response.json()) - .then(data => { - searchIndex = data; - }) - .catch(error => { - console.error('Error loading search index:', error); - }); + searchResults.innerHTML = '
๐Ÿ”

Start typing to search posts...

'; } // Initialize search @@ -97,9 +112,6 @@ if (!searchModal || !searchInput || !searchResults) return; - // Load search index - loadSearchIndex(); - // Event listeners searchClose.addEventListener('click', closeSearch); @@ -122,13 +134,13 @@ } }); - // Perform search as user types + // Perform search as user types (reduced debounce for faster response) let searchTimeout; searchInput.addEventListener('input', (e) => { clearTimeout(searchTimeout); searchTimeout = setTimeout(() => { performSearch(e.target.value); - }, 200); + }, 150); }); // Show initial message @@ -143,4 +155,3 @@ } })(); - diff --git a/build.sh b/build.sh index 93137e9..9a05386 100755 --- a/build.sh +++ b/build.sh @@ -10,6 +10,11 @@ echo "" # Clean and build for production with explicit baseURL hugo --cleanDestinationDir --minify --baseURL="https://blog.nischalskanda.tech/" +# Build Pagefind search index +echo "" +echo "๐Ÿ” Building search index with Pagefind..." +npx --yes pagefind@latest --site public + echo "" echo "โœ… Production build complete!" echo "๐Ÿ“ Files are ready in ./public/ directory" diff --git a/hugo.toml b/hugo.toml index 5ca2396..443d8fe 100644 --- a/hugo.toml +++ b/hugo.toml @@ -5,9 +5,9 @@ enableRobotsTXT = true enableGitInfo = true canonifyURLs = true -# Output formats for search +# Output formats (JSON removed - Pagefind handles search indexing) [outputs] - home = ["HTML", "RSS", "JSON"] + home = ["HTML", "RSS"] section = ["HTML", "RSS"] # SEO and Performance diff --git a/layouts/_default/index.json b/layouts/_default/index.json deleted file mode 100644 index eab12ef..0000000 --- a/layouts/_default/index.json +++ /dev/null @@ -1,14 +0,0 @@ -{{- $.Scratch.Add "index" slice -}} -{{- range where .Site.RegularPages "Section" "posts" -}} - {{- $.Scratch.Add "index" (dict - "title" .Title - "description" .Description - "content" (.Plain | truncate 500) - "permalink" .Permalink - "date" (.Date.Format "Jan 2, 2006") - "categories" .Params.categories - "tags" .Params.tags - ) -}} -{{- end -}} -{{- $.Scratch.Get "index" | jsonify -}} -