From a99d1db1cb7d373c2f47d7ea4c30c342a82a11a2 Mon Sep 17 00:00:00 2001 From: CaffeineFueled Date: Sun, 22 Mar 2026 20:30:05 +0100 Subject: [PATCH] ux: CHANGE change 'feeds' to 'sections' - BREAKING - short guide in release notes --- README.md | 24 +++--- config.py | 6 +- picopaper.py | 82 +++++++++---------- .../templates/{feeds.tmpl => sections.tmpl} | 6 +- 4 files changed, 59 insertions(+), 59 deletions(-) rename theme/default/templates/{feeds.tmpl => sections.tmpl} (57%) diff --git a/README.md b/README.md index 634e18b..db60989 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,8 @@ Show cases: - long- and short form content - pages - static files -- separate feeds (used for categories, tagging, etc) `/feed/{tag}` -- exclusion of feeds from main feed (drafts or system notes) +- separate sections (used for categories, tagging, etc) `/section/{tag}` +- exclusion of sections from main index (drafts or system notes) - HTML anchors for headers - list random posts at the bottom - optional RSS feeds @@ -47,33 +47,33 @@ Put markdown file into `items` dir. **Important naming convention**: 2025-10-05_short_quick-update_draft.md ``` -Format: `YYYY-MM-DD_type_slug[_feed].md` +Format: `YYYY-MM-DD_type_slug[_section].md` - `2025-10-03` - date of the article - `_long_` - type of content: `long`, `short`, or `page` - `building-a-static-site-generator` - slug/path for the URL -- `_draft` (optional) - feed tag for categorization +- `_draft` (optional) - section tag for categorization The first `#` header is the title of the article - no frontmatter needed. **Types of content**: -- `long` - only title with link to articles will be displayed in feed +- `long` - only title with link to articles will be displayed in the main index - `short` - title and all content will be displayed -- `page` - won't be displayed in feed at all +- `page` - won't be displayed in the main index at all -### Feeds +### Sections -Posts can be tagged with an optional feed category (e.g., `_python`, `_webdev`). Posts with feed tags: +Posts can be tagged with an optional section (e.g., `_python`, `_webdev`). Posts with section tags: - Appear on the main page (unless excluded in config) -- Have their own feed page at `/feed/{tag}/` +- Have their own section page at `/section/{tag}/` **Configuration in `config.py`:** ```python -# Exclude specific feeds from main page (they'll still have /feed/name/ pages) -EXCLUDE_FEEDS_FROM_MAIN = ['draft', 'private'] +# Exclude specific sections from main page (they'll still have /section/name/ pages) +EXCLUDE_SECTIONS_FROM_MAIN = ['draft', 'private'] ``` -This is useful for draft posts or topic-specific content you want separated from the main feed. +This is useful for draft posts or topic-specific content you want separated from the main index. --- diff --git a/config.py b/config.py index 66cb25c..0bf0d15 100644 --- a/config.py +++ b/config.py @@ -8,13 +8,13 @@ AUTHOR_NAME = "PicoPaper" AUTHOR_EMAIL = "hello@picopaper.com" # Optional THEME = "default" -# Exclude specific feeds from the main page (they'll still have their own /feed/name/ pages) -EXCLUDE_FEEDS_FROM_MAIN = ['draft','private'] # e.g., ['python', 'drafts'] +# Exclude specific sections from the main page (they'll still have their own /section/name/ pages) +EXCLUDE_SECTIONS_FROM_MAIN = ['draft','private'] # e.g., ['python', 'drafts'] # Navigation bar items - list of dictionaries with 'text' and 'url' keys NAVBAR_ITEMS = [ {'text': 'Home', 'url': '/'}, - {'text': 'Feeds', 'url': '/feed/'}, + {'text': 'Sections', 'url': '/section/'}, {'text': 'About', 'url': '/about/'}, {'text': 'RSS', 'url': '/rss.xml'} ] diff --git a/picopaper.py b/picopaper.py index bef764e..1448e80 100644 --- a/picopaper.py +++ b/picopaper.py @@ -6,7 +6,7 @@ from datetime import datetime from pathlib import Path from jinja2 import Environment, FileSystemLoader import markdown -from config import (BLOG_TITLE, BLOG_DESCRIPTION, THEME, EXCLUDE_FEEDS_FROM_MAIN, +from config import (BLOG_TITLE, BLOG_DESCRIPTION, THEME, EXCLUDE_SECTIONS_FROM_MAIN, NAVBAR_ITEMS, HIDE_LOGO, HIDE_TITLE, LOGO_PATH, ENABLE_RSS_FEED, RSS_FEED_PATH, BASE_URL, AUTHOR_NAME, AUTHOR_EMAIL, FEED_MAX_ITEMS) @@ -21,7 +21,7 @@ class SSGGGenerator: self.assets_dir = self.theme_dir / 'assets' self.blog_title = blog_title or BLOG_TITLE self.blog_description = blog_description or BLOG_DESCRIPTION - self.exclude_feeds = EXCLUDE_FEEDS_FROM_MAIN + self.exclude_sections = EXCLUDE_SECTIONS_FROM_MAIN self.navbar_items = NAVBAR_ITEMS self.hide_logo = HIDE_LOGO self.hide_title = HIDE_TITLE @@ -42,7 +42,7 @@ class SSGGGenerator: self.md = markdown.Markdown(extensions=['extra', 'toc']) def parse_filename(self, filename, subpath=''): - """Parse filename format: YYYY-MM-DD_type_name[_feed].md + """Parse filename format: YYYY-MM-DD_type_name[_section].md Args: filename: The markdown filename @@ -54,7 +54,7 @@ class SSGGGenerator: if not match: return None - date_str, post_type, name, feed = match.groups() + date_str, post_type, name, section = match.groups() date = datetime.strptime(date_str, '%Y-%m-%d') return { @@ -62,7 +62,7 @@ class SSGGGenerator: 'date_str': date.strftime('%Y-%m-%d'), 'type': post_type, 'name': name, - 'feed': feed, + 'section': section, 'filename': filename, 'subpath': subpath } @@ -140,7 +140,7 @@ class SSGGGenerator: 'content': content, 'slug': slug, 'url': url, - 'feed': parsed['feed'], + 'section': parsed['section'], 'source': str(relative_path), 'subpath': parsed['subpath'] } @@ -152,13 +152,13 @@ class SSGGGenerator: return posts - def generate_index(self, posts, feed_name=None, all_posts=None): - """Generate index.html with all posts (or feed-specific index)""" + def generate_index(self, posts, section_name=None, all_posts=None): + """Generate index.html with all posts (or section-specific index)""" template = self.env.get_template('index.tmpl') - if feed_name: - title = f"{feed_name} - {self.blog_title}" - output_path = self.output_dir / 'feed' / feed_name / 'index.html' + if section_name: + title = f"{section_name} - {self.blog_title}" + output_path = self.output_dir / 'section' / section_name / 'index.html' else: title = self.blog_title output_path = self.output_dir / 'index.html' @@ -183,28 +183,28 @@ class SSGGGenerator: print(f"✓ Generated {output_path}") - def generate_feeds_overview(self, feeds, all_posts=None): - """Generate /feed/index.html with list of all non-excluded feeds""" - template = self.env.get_template('feeds.tmpl') + def generate_sections_overview(self, sections, all_posts=None): + """Generate /section/index.html with list of all non-excluded sections""" + template = self.env.get_template('sections.tmpl') - # Prepare feed data with counts, excluding feeds in EXCLUDE_FEEDS_FROM_MAIN - feed_list = [] - for feed_name, posts in sorted(feeds.items()): - if feed_name not in self.exclude_feeds: - feed_list.append({ - 'name': feed_name, + # Prepare section data with counts, excluding sections in EXCLUDE_SECTIONS_FROM_MAIN + section_list = [] + for section_name, posts in sorted(sections.items()): + if section_name not in self.exclude_sections: + section_list.append({ + 'name': section_name, 'count': len(posts) }) - title = f"Feeds - {self.blog_title}" - output_path = self.output_dir / 'feed' / 'index.html' + title = f"Sections - {self.blog_title}" + output_path = self.output_dir / 'section' / 'index.html' html = template.render( title=title, blog_title=self.blog_title, blog_description=self.blog_description, navbar_items=self.navbar_items, - feeds=feed_list, + sections=section_list, all_posts=all_posts or [], hide_logo=self.hide_logo, hide_title=self.hide_title, @@ -397,27 +397,27 @@ class SSGGGenerator: all_posts = self.collect_posts() print(f"Found {len(all_posts)} posts") - # Filter out pages and excluded feeds from main feed - feed_posts = [p for p in all_posts + # Filter out pages and excluded sections from main index + main_posts = [p for p in all_posts if p['type'] != 'page' - and p['feed'] not in self.exclude_feeds] + and p['section'] not in self.exclude_sections] - # Generate main index with filtered feed posts - self.generate_index(feed_posts, all_posts=feed_posts) + # Generate main index with filtered posts + self.generate_index(main_posts, all_posts=main_posts) - # Group posts by feed (include all posts, not just those in main feed) - feeds = {} + # Group posts by section (include all posts, not just those in main index) + sections = {} for post in all_posts: - if post['feed'] and post['type'] != 'page': - feeds.setdefault(post['feed'], []).append(post) + if post['section'] and post['type'] != 'page': + sections.setdefault(post['section'], []).append(post) - # Generate feed-specific pages - for feed_name, posts in feeds.items(): - self.generate_index(posts, feed_name, all_posts=feed_posts) + # Generate section-specific pages + for section_name, posts in sections.items(): + self.generate_index(posts, section_name, all_posts=main_posts) - # Generate feeds overview page - if feeds: - self.generate_feeds_overview(feeds, all_posts=feed_posts) + # Generate sections overview page + if sections: + self.generate_sections_overview(sections, all_posts=main_posts) # Group posts by subdirectory subdirs = {} @@ -427,16 +427,16 @@ class SSGGGenerator: # Generate subdirectory index pages (e.g., /projects/) for subpath, subdir_posts in subdirs.items(): - self.generate_subdir_index(subpath, subdir_posts, all_posts=feed_posts) + self.generate_subdir_index(subpath, subdir_posts, all_posts=main_posts) # Generate individual pages for long posts, short posts, and pages for post in all_posts: if post['type'] in ['long', 'short', 'page']: - self.generate_post_page(post, all_posts=feed_posts) + self.generate_post_page(post, all_posts=main_posts) # Generate RSS feed if ENABLE_RSS_FEED: - self.generate_rss_feed(feed_posts) + self.generate_rss_feed(main_posts) # Copy assets self.copy_assets() diff --git a/theme/default/templates/feeds.tmpl b/theme/default/templates/sections.tmpl similarity index 57% rename from theme/default/templates/feeds.tmpl rename to theme/default/templates/sections.tmpl index c03aae7..046a356 100644 --- a/theme/default/templates/feeds.tmpl +++ b/theme/default/templates/sections.tmpl @@ -7,10 +7,10 @@ {% include 'header.tmpl' %}
-

Feeds

+

Sections