feat: Init with clean layout
This commit is contained in:
532
CUSTOMIZATION.md
Normal file
532
CUSTOMIZATION.md
Normal file
@@ -0,0 +1,532 @@
|
||||
# Hugo + PaperMod Customization Guide
|
||||
|
||||
This guide covers how to customize your Hugo portfolio site using the PaperMod theme.
|
||||
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Project Structure](#project-structure)
|
||||
2. [Development Workflow](#development-workflow)
|
||||
3. [Configuration (hugo.yaml)](#configuration-hugoyaml)
|
||||
4. [Adding Content](#adding-content)
|
||||
5. [Creating New Sections](#creating-new-sections)
|
||||
6. [Customizing Styles (CSS)](#customizing-styles-css)
|
||||
7. [Overriding Layouts](#overriding-layouts)
|
||||
8. [Common Customizations](#common-customizations)
|
||||
9. [Deployment](#deployment)
|
||||
|
||||
---
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
MyPortfolio/
|
||||
├── archetypes/ # Templates for new content
|
||||
├── assets/
|
||||
│ └── css/
|
||||
│ └── extended/
|
||||
│ └── custom.css # YOUR custom CSS (this gets merged)
|
||||
├── content/
|
||||
│ ├── posts/ # Long-form articles
|
||||
│ │ └── _index.md # Section config
|
||||
│ ├── notes/ # Short notes/TILs
|
||||
│ │ └── _index.md # Section config
|
||||
│ └── search.md # Search page
|
||||
├── layouts/
|
||||
│ ├── partials/ # Override theme partials
|
||||
│ │ └── footer.html # Custom footer
|
||||
│ └── notes/ # Section-specific layouts
|
||||
│ └── list.html # Custom notes list
|
||||
├── static/
|
||||
│ └── files/ # Static files (CV.pdf, images, etc.)
|
||||
├── themes/
|
||||
│ └── PaperMod/ # Theme (git submodule - DON'T edit)
|
||||
├── hugo.yaml # Main configuration
|
||||
└── .gitignore # Ignores public/, etc.
|
||||
```
|
||||
|
||||
### Key Principle: Never Edit the Theme Directly
|
||||
|
||||
The `themes/PaperMod/` folder is a git submodule. To customize:
|
||||
- **CSS**: Add to `assets/css/extended/custom.css`
|
||||
- **Layouts**: Copy the file from `themes/PaperMod/layouts/` to `layouts/` and modify
|
||||
- **Config**: Everything in `hugo.yaml`
|
||||
|
||||
---
|
||||
|
||||
## Development Workflow
|
||||
|
||||
### Local Development
|
||||
|
||||
```bash
|
||||
# Start dev server (watches for changes)
|
||||
hugo serve
|
||||
|
||||
# With drafts visible
|
||||
hugo serve -D
|
||||
|
||||
# Build for production (outputs to public/)
|
||||
hugo build --minify
|
||||
```
|
||||
|
||||
### Why `public/` is Gitignored
|
||||
|
||||
- `public/` is generated output - it's rebuilt fresh every time
|
||||
- Your CI/CD (GitHub Actions) builds it during deployment
|
||||
- Never commit build artifacts to git
|
||||
|
||||
### Git Workflow
|
||||
|
||||
```bash
|
||||
# After making changes
|
||||
git add .
|
||||
git commit -m "Add new post about X"
|
||||
git push origin master # Triggers deployment
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Configuration (hugo.yaml)
|
||||
|
||||
### Key Sections
|
||||
|
||||
#### Site Basics
|
||||
```yaml
|
||||
baseURL: "/" # Use "/" for relative URLs (works on localhost + prod)
|
||||
relativeURLs: true # Makes all URLs relative
|
||||
title: Saurav Dhakal
|
||||
languageCode: en-us
|
||||
theme: ["PaperMod"]
|
||||
```
|
||||
|
||||
#### Menu (Header Navigation)
|
||||
```yaml
|
||||
menu:
|
||||
main:
|
||||
- identifier: posts # Internal ID
|
||||
name: Posts # Display name
|
||||
url: /posts/ # URL path
|
||||
weight: 10 # Order (lower = first)
|
||||
- identifier: notes
|
||||
name: Notes
|
||||
url: /notes/
|
||||
weight: 20
|
||||
- identifier: tags
|
||||
name: Tags
|
||||
url: /tags/
|
||||
weight: 30
|
||||
- identifier: search
|
||||
name: Search
|
||||
url: /search/
|
||||
weight: 40
|
||||
```
|
||||
|
||||
#### Home Page Info
|
||||
```yaml
|
||||
params:
|
||||
homeInfoParams:
|
||||
Title: "Hi there 👋, I'm Saurav!"
|
||||
Content: >
|
||||
I'm a software engineer...
|
||||
```
|
||||
|
||||
#### Social Icons
|
||||
```yaml
|
||||
params:
|
||||
socialIcons:
|
||||
- name: github
|
||||
url: "https://github.com/yourusername"
|
||||
- name: linkedin
|
||||
url: "https://linkedin.com/in/yourusername"
|
||||
- name: x
|
||||
url: "https://x.com/yourusername"
|
||||
```
|
||||
|
||||
Available icons: github, linkedin, x, twitter, email, rss, youtube, instagram, facebook, stackoverflow, etc.
|
||||
|
||||
---
|
||||
|
||||
## Adding Content
|
||||
|
||||
### New Post
|
||||
|
||||
```bash
|
||||
hugo new posts/my-new-post.md
|
||||
```
|
||||
|
||||
Or manually create `content/posts/my-new-post.md`:
|
||||
|
||||
```markdown
|
||||
---
|
||||
title: "My New Post"
|
||||
date: 2025-08-20
|
||||
summary: "A brief description for the list view"
|
||||
tags: ["tag1", "tag2"]
|
||||
categories: ["Category"]
|
||||
draft: false
|
||||
ShowToc: true
|
||||
TocOpen: false
|
||||
---
|
||||
|
||||
Your content here...
|
||||
```
|
||||
|
||||
### New Note
|
||||
|
||||
Create `content/notes/my-note.md`:
|
||||
|
||||
```markdown
|
||||
---
|
||||
title: "Quick TIL"
|
||||
date: 2025-08-20
|
||||
summary: "Today I learned about X"
|
||||
tags: ["til"]
|
||||
---
|
||||
|
||||
Short content here...
|
||||
```
|
||||
|
||||
### Front Matter Options
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `title` | Post title |
|
||||
| `date` | Publication date (YYYY-MM-DD) |
|
||||
| `summary` | Short description for list views |
|
||||
| `tags` | Array of tags |
|
||||
| `categories` | Array of categories |
|
||||
| `draft` | If `true`, won't be published |
|
||||
| `ShowToc` | Show table of contents |
|
||||
| `TocOpen` | TOC expanded by default |
|
||||
| `ShowReadingTime` | Override global setting |
|
||||
| `ShowWordCount` | Override global setting |
|
||||
| `cover.image` | Cover image path |
|
||||
|
||||
---
|
||||
|
||||
## Creating New Sections
|
||||
|
||||
### Example: Adding a "Projects" Section
|
||||
|
||||
1. **Add to menu** in `hugo.yaml`:
|
||||
```yaml
|
||||
menu:
|
||||
main:
|
||||
# ... existing items
|
||||
- identifier: projects
|
||||
name: Projects
|
||||
url: /projects/
|
||||
weight: 25
|
||||
```
|
||||
|
||||
2. **Create content directory**:
|
||||
```bash
|
||||
mkdir -p content/projects
|
||||
```
|
||||
|
||||
3. **Create section index** `content/projects/_index.md`:
|
||||
```markdown
|
||||
---
|
||||
title: "Projects"
|
||||
description: "Things I've built"
|
||||
---
|
||||
```
|
||||
|
||||
4. **Add project pages** `content/projects/my-project.md`:
|
||||
```markdown
|
||||
---
|
||||
title: "My Cool Project"
|
||||
date: 2025-01-15
|
||||
summary: "A brief description"
|
||||
tags: ["golang", "cli"]
|
||||
---
|
||||
|
||||
Project description...
|
||||
```
|
||||
|
||||
5. **(Optional) Custom layout** - If you want projects to look different, create `layouts/projects/list.html`
|
||||
|
||||
---
|
||||
|
||||
## Customizing Styles (CSS)
|
||||
|
||||
### Where to Add CSS
|
||||
|
||||
**Only edit**: `assets/css/extended/custom.css`
|
||||
|
||||
PaperMod automatically includes this file. You don't need to import it anywhere.
|
||||
|
||||
### CSS Variables (Theme Colors)
|
||||
|
||||
PaperMod uses CSS variables. Override them in your custom.css:
|
||||
|
||||
```css
|
||||
:root {
|
||||
/* Light mode */
|
||||
--primary: #282828; /* Main text */
|
||||
--secondary: #3c3836; /* Secondary text */
|
||||
--tertiary: rgb(214, 214, 214); /* Borders, etc */
|
||||
--theme: rgb(255, 255, 255); /* Background */
|
||||
--entry: rgb(255, 255, 255); /* Card background */
|
||||
}
|
||||
|
||||
:root[data-theme="dark"] {
|
||||
/* Dark mode */
|
||||
--primary: #fbf1c7;
|
||||
--secondary: #ebdbb2;
|
||||
--theme: #181818;
|
||||
--entry: rgb(46, 46, 51);
|
||||
}
|
||||
```
|
||||
|
||||
### Common CSS Customizations
|
||||
|
||||
#### Change fonts
|
||||
```css
|
||||
@import url("https://fonts.googleapis.com/css2?family=Your+Font&display=swap");
|
||||
|
||||
body {
|
||||
font-family: "Your Font", sans-serif;
|
||||
}
|
||||
```
|
||||
|
||||
#### Style links
|
||||
```css
|
||||
main a {
|
||||
text-decoration: underline;
|
||||
text-decoration-color: var(--green);
|
||||
}
|
||||
|
||||
main a:hover {
|
||||
background-color: var(--green);
|
||||
color: white;
|
||||
}
|
||||
```
|
||||
|
||||
#### Customize post cards
|
||||
```css
|
||||
main .post-entry {
|
||||
border: 2px solid #383838;
|
||||
background-color: var(--entry);
|
||||
border-radius: 8px;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Overriding Layouts
|
||||
|
||||
### How Layout Override Works
|
||||
|
||||
Hugo looks for templates in this order:
|
||||
1. `layouts/` (your overrides)
|
||||
2. `themes/PaperMod/layouts/` (theme defaults)
|
||||
|
||||
### To Override a Template
|
||||
|
||||
1. Find the file in `themes/PaperMod/layouts/`
|
||||
2. Copy it to the same path in `layouts/`
|
||||
3. Modify your copy
|
||||
|
||||
### Common Files to Override
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `layouts/partials/header.html` | Site header/nav |
|
||||
| `layouts/partials/footer.html` | Site footer |
|
||||
| `layouts/partials/post_meta.html` | Post metadata (date, read time) |
|
||||
| `layouts/_default/list.html` | List pages (posts, tags) |
|
||||
| `layouts/_default/single.html` | Individual post/page |
|
||||
|
||||
### Example: Simpler Footer
|
||||
|
||||
Your `layouts/partials/footer.html` already overrides the theme's footer.
|
||||
|
||||
### Section-Specific Layouts
|
||||
|
||||
Create `layouts/SECTION_NAME/list.html` for a custom list layout for that section.
|
||||
|
||||
Example: `layouts/notes/list.html` - custom compact layout for notes.
|
||||
|
||||
---
|
||||
|
||||
## Common Customizations
|
||||
|
||||
### Disable Reading Time for a Section
|
||||
|
||||
In the section's `_index.md`:
|
||||
```markdown
|
||||
---
|
||||
title: "Notes"
|
||||
ShowReadingTime: false
|
||||
---
|
||||
```
|
||||
|
||||
Or per-post in front matter.
|
||||
|
||||
### Add a Static Page (About, Contact)
|
||||
|
||||
Create `content/about.md`:
|
||||
```markdown
|
||||
---
|
||||
title: "About"
|
||||
layout: "single"
|
||||
url: "/about/"
|
||||
---
|
||||
|
||||
About me content...
|
||||
```
|
||||
|
||||
Add to menu:
|
||||
```yaml
|
||||
menu:
|
||||
main:
|
||||
- identifier: about
|
||||
name: About
|
||||
url: /about/
|
||||
weight: 50
|
||||
```
|
||||
|
||||
### Add Favicon
|
||||
|
||||
1. Place favicon files in `static/`:
|
||||
- `static/favicon.ico`
|
||||
- `static/favicon-16x16.png`
|
||||
- `static/favicon-32x32.png`
|
||||
- `static/apple-touch-icon.png`
|
||||
|
||||
2. Update `hugo.yaml`:
|
||||
```yaml
|
||||
params:
|
||||
assets:
|
||||
favicon: "/favicon.ico"
|
||||
favicon16x16: "/favicon-16x16.png"
|
||||
favicon32x32: "/favicon-32x32.png"
|
||||
apple_touch_icon: "/apple-touch-icon.png"
|
||||
```
|
||||
|
||||
### Enable Comments (Disqus)
|
||||
|
||||
```yaml
|
||||
params:
|
||||
comments: true
|
||||
|
||||
disqusShortname: "your-disqus-shortname"
|
||||
```
|
||||
|
||||
### Add Google Analytics
|
||||
|
||||
Already configured in your `hugo.yaml`:
|
||||
```yaml
|
||||
googleAnalytics: "G-XXXXXXXXXX"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Deployment
|
||||
|
||||
### Current Setup (GitHub Actions → SSH/SCP)
|
||||
|
||||
Your `.github/workflows/deploy.yml`:
|
||||
1. Triggers on push to `master`
|
||||
2. Builds site with `hugo build --minify`
|
||||
3. Deploys `public/` via SCP to your server
|
||||
|
||||
### Required GitHub Secrets
|
||||
|
||||
Set these in your repo's Settings → Secrets:
|
||||
- `SSH_HOST` - Your server hostname/IP
|
||||
- `SSH_USER` - SSH username
|
||||
- `SSH_KEY` - Private SSH key
|
||||
- `SSH_PORT` - SSH port (usually 22)
|
||||
|
||||
### Alternative: GitHub Pages
|
||||
|
||||
If you want to use GitHub Pages instead:
|
||||
|
||||
1. Change workflow to use `peaceiris/actions-gh-pages`
|
||||
2. Set `baseURL` to `https://yourusername.github.io/repo-name/`
|
||||
|
||||
### Alternative: Netlify/Vercel
|
||||
|
||||
These platforms auto-detect Hugo and build for you:
|
||||
1. Connect your GitHub repo
|
||||
2. Set build command: `hugo --minify`
|
||||
3. Set publish directory: `public`
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### Useful Commands
|
||||
|
||||
```bash
|
||||
# Local dev
|
||||
hugo serve -D # Serve with drafts
|
||||
|
||||
# Create content
|
||||
hugo new posts/title.md # New post
|
||||
hugo new notes/title.md # New note
|
||||
|
||||
# Build
|
||||
hugo build --minify # Production build
|
||||
|
||||
# Debug
|
||||
hugo config # Show full config
|
||||
hugo list all # List all content
|
||||
```
|
||||
|
||||
### File Locations
|
||||
|
||||
| What | Where |
|
||||
|------|-------|
|
||||
| Config | `hugo.yaml` |
|
||||
| Custom CSS | `assets/css/extended/custom.css` |
|
||||
| Posts | `content/posts/` |
|
||||
| Notes | `content/notes/` |
|
||||
| Static files | `static/` |
|
||||
| Layout overrides | `layouts/` |
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Links Go to Production URL in Dev
|
||||
|
||||
Fixed by setting:
|
||||
```yaml
|
||||
baseURL: "/"
|
||||
relativeURLs: true
|
||||
```
|
||||
|
||||
### Changes Not Showing
|
||||
|
||||
1. Hard refresh browser (Ctrl+Shift+R)
|
||||
2. Clear `public/` folder: `rm -rf public/`
|
||||
3. Restart hugo serve
|
||||
|
||||
### Theme Not Loading
|
||||
|
||||
```bash
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
|
||||
### Search Not Working
|
||||
|
||||
Ensure `hugo.yaml` has:
|
||||
```yaml
|
||||
outputs:
|
||||
home:
|
||||
- HTML
|
||||
- RSS
|
||||
- JSON # Required for search
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Resources
|
||||
|
||||
- [Hugo Documentation](https://gohugo.io/documentation/)
|
||||
- [PaperMod Wiki](https://github.com/adityatelange/hugo-PaperMod/wiki)
|
||||
- [PaperMod Demo](https://adityatelange.github.io/hugo-PaperMod/)
|
||||
Reference in New Issue
Block a user