mirror of
https://github.com/mmahdium/portfolio.git
synced 2026-08-16 21:14:31 +03:30
add blog to project
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,241 @@
|
||||
# Requirements Document
|
||||
|
||||
## Introduction
|
||||
|
||||
This document specifies the requirements for implementing a fully-featured blog system in the Nuxt 4 portfolio application using Nuxt Content v3. The blog system will support bilingual content (English and Persian with RTL), markdown-based content management, SEO optimization, and seamless integration with the existing portfolio design system.
|
||||
|
||||
## Glossary
|
||||
|
||||
- **Blog System**: The complete blogging functionality including content management, rendering, listing, and navigation
|
||||
- **Nuxt Content**: The official Nuxt module (@nuxt/content) for file-based content management with markdown support
|
||||
- **Content Directory**: The file system location where markdown blog posts are stored (content/ folder)
|
||||
- **Blog Post**: A single article written in markdown format with frontmatter metadata
|
||||
- **Frontmatter**: YAML metadata at the top of markdown files containing post information (title, date, tags, etc.)
|
||||
- **Blog Listing Page**: The main blog index page displaying all published posts
|
||||
- **Blog Detail Page**: Individual post page rendering the full markdown content
|
||||
- **Content Query**: Nuxt Content's API for fetching and filtering markdown content
|
||||
- **MDC Syntax**: Markdown Components syntax for embedding Vue components in markdown
|
||||
- **SEO Metadata**: Meta tags, Open Graph, and structured data for search engine optimization
|
||||
- **Reading Time**: Calculated estimate of time required to read a blog post
|
||||
- **Tag System**: Categorization mechanism using tags/labels for blog posts
|
||||
- **Draft Mode**: Unpublished posts that are hidden from production but visible in development
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement 1: Nuxt Content Module Integration
|
||||
|
||||
**User Story:** As a developer, I want to integrate Nuxt Content v3 into the existing Nuxt 4 application, so that I can manage blog content using markdown files.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN the developer installs the @nuxt/content package, THE Blog System SHALL use version 3.x compatible with Nuxt 4
|
||||
2. WHEN the nuxt.config.ts is updated, THE Blog System SHALL register @nuxt/content in the modules array before other content-dependent modules
|
||||
3. THE Blog System SHALL create a content/ directory in the project root for storing markdown files
|
||||
4. THE Blog System SHALL configure Nuxt Content with Shiki syntax highlighter for code blocks
|
||||
5. THE Blog System SHALL enable markdown.mdc option to support Vue component embedding in markdown
|
||||
6. WHEN the development server starts, THE Blog System SHALL successfully load and parse all markdown files with hot-reload support
|
||||
|
||||
### Requirement 2: Content Directory Structure
|
||||
|
||||
**User Story:** As a content creator, I want a well-organized content directory structure, so that I can easily manage bilingual blog posts.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE Blog System SHALL create locale-based subdirectories (content/en/blog/ and content/fa/blog/)
|
||||
2. WHEN queryContent() is called with a locale parameter, THE Blog System SHALL fetch content from the corresponding locale directory
|
||||
3. THE Blog System SHALL support nested directories within blog folders for content organization (e.g., content/en/blog/tutorials/)
|
||||
4. THE Blog System SHALL recognize markdown files with .md extension as valid blog posts
|
||||
5. WHERE a blog post exists in one language but not another, THE Blog System SHALL display a fallback message with a link to the available language version
|
||||
6. THE Blog System SHALL use the file name (slug) as the URL path segment for blog posts
|
||||
|
||||
### Requirement 3: Blog Post Frontmatter Schema
|
||||
|
||||
**User Story:** As a content creator, I want a standardized frontmatter schema for blog posts, so that all posts have consistent metadata.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE Blog System SHALL require the following frontmatter fields: title, description, date, and tags
|
||||
2. THE Blog System SHALL support optional frontmatter fields: image, author, draft, updatedAt, and head (for custom SEO)
|
||||
3. THE Blog System SHALL define a TypeScript interface extending ParsedContent for type-safe frontmatter access
|
||||
4. THE Blog System SHALL parse date field as ISO 8601 date string (YYYY-MM-DD or full ISO format)
|
||||
5. THE Blog System SHALL accept tags as an array of strings for categorization
|
||||
6. WHERE draft is set to true, THE Blog System SHALL exclude the post from queryContent results in production using where({ draft: { $ne: true } })
|
||||
7. THE Blog System SHALL use the image field for Open Graph and Twitter Card meta tags
|
||||
|
||||
### Requirement 4: Blog Listing Page Implementation
|
||||
|
||||
**User Story:** As a visitor, I want to see a list of all published blog posts, so that I can browse available content.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN a visitor navigates to /blog or /fa/blog, THE Blog System SHALL use queryContent() to fetch all published posts for the current locale path
|
||||
2. THE Blog System SHALL sort blog posts by date field in descending order using .sort({ date: -1 })
|
||||
3. THE Blog System SHALL display post title, description, formatted date, reading time estimate, and tags for each post card
|
||||
4. WHEN a visitor clicks on a blog post card, THE Blog System SHALL navigate to the localized post detail page using the _path property
|
||||
5. WHERE no published posts exist for a locale, THE Blog System SHALL display an empty state message with i18n translation
|
||||
6. THE Blog System SHALL filter out draft posts using .where({ draft: { $ne: true } }) in production environment
|
||||
7. THE Blog System SHALL calculate reading time from the body.children word count assuming 200 words per minute
|
||||
8. THE Blog System SHALL use .only() to fetch only required fields (title, description, date, tags, _path, image) for performance
|
||||
|
||||
### Requirement 5: Blog Detail Page Implementation
|
||||
|
||||
**User Story:** As a visitor, I want to read the full content of a blog post, so that I can consume the article.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN a visitor navigates to /blog/[slug] or /fa/blog/[slug], THE Blog System SHALL use ContentDoc component or queryContent().where({ _path: path }).findOne() to fetch the post
|
||||
2. THE Blog System SHALL render markdown using ContentRenderer component with GitHub Flavored Markdown support
|
||||
3. THE Blog System SHALL apply Shiki syntax highlighting to code blocks with theme matching the site's color mode
|
||||
4. THE Blog System SHALL render post metadata (title, formatted date, reading time, tags) in a header section using Nuxt UI components
|
||||
5. WHERE the requested slug does not exist, THE Blog System SHALL throw a 404 error using createError({ statusCode: 404 })
|
||||
6. THE Blog System SHALL support MDC syntax (::component-name) for embedding Vue components within markdown
|
||||
7. THE Blog System SHALL apply Prose components styling from Nuxt UI for consistent typography (ProseH1, ProseP, ProseCode, etc.)
|
||||
8. THE Blog System SHALL auto-generate anchor links for all headings for easy section sharing
|
||||
|
||||
### Requirement 6: SEO and Meta Tags
|
||||
|
||||
**User Story:** As a content creator, I want proper SEO metadata for blog posts, so that they rank well in search engines.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE Blog System SHALL use useContentHead() composable to auto-generate meta tags from frontmatter
|
||||
2. THE Blog System SHALL use useSeoMeta() to set title in format "[Post Title] | Blog | [Site Name]"
|
||||
3. THE Blog System SHALL generate Open Graph tags (og:title, og:description, og:image, og:type, og:url) from post frontmatter
|
||||
4. WHERE an image field is specified in frontmatter, THE Blog System SHALL use it for og:image and twitter:image, otherwise use a default blog cover image
|
||||
5. THE Blog System SHALL set og:type to "article" and include article:published_time and article:tag properties
|
||||
6. THE Blog System SHALL generate Twitter Card meta tags with card type "summary_large_image"
|
||||
7. THE Blog System SHALL allow custom head overrides via the head field in frontmatter for advanced SEO control
|
||||
8. THE Blog System SHALL generate JSON-LD structured data for BlogPosting schema including author, datePublished, and headline
|
||||
|
||||
### Requirement 7: Tag Filtering System
|
||||
|
||||
**User Story:** As a visitor, I want to filter blog posts by tags, so that I can find content on specific topics.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE Blog System SHALL extract all unique tags from published posts using a computed property that aggregates tags arrays
|
||||
2. WHEN a visitor clicks on a tag, THE Blog System SHALL filter posts using queryContent().where({ tags: { $contains: selectedTag } })
|
||||
3. THE Blog System SHALL update the URL query parameter (?tag=value) using useRoute() and navigateTo() when a tag is selected
|
||||
4. WHEN a visitor clears the tag filter, THE Blog System SHALL remove the query parameter and display all posts
|
||||
5. THE Blog System SHALL highlight the active tag using Nuxt UI's UBadge or UButton component with active state styling
|
||||
6. THE Blog System SHALL read the tag query parameter on page load to maintain filter state on navigation or refresh
|
||||
|
||||
### Requirement 8: Responsive Design and Accessibility
|
||||
|
||||
**User Story:** As a visitor using any device, I want the blog to be fully responsive and accessible, so that I can read content comfortably.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE Blog System SHALL render blog listing and detail pages responsively across mobile, tablet, and desktop viewports
|
||||
2. THE Blog System SHALL maintain readability with appropriate font sizes and line heights for body text
|
||||
3. THE Blog System SHALL ensure sufficient color contrast ratios for text and backgrounds (WCAG AA compliance)
|
||||
4. THE Blog System SHALL support keyboard navigation for all interactive elements
|
||||
5. THE Blog System SHALL provide appropriate ARIA labels and semantic HTML for screen readers
|
||||
6. WHERE images are used in blog posts, THE Blog System SHALL require alt text for accessibility
|
||||
|
||||
### Requirement 9: RTL Support for Persian Content
|
||||
|
||||
**User Story:** As a Persian-speaking visitor, I want blog content to display correctly in RTL layout, so that I can read naturally.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN a visitor views Persian blog content, THE Blog System SHALL apply RTL text direction to all content
|
||||
2. THE Blog System SHALL mirror layout elements appropriately for RTL (navigation, spacing, alignment)
|
||||
3. THE Blog System SHALL maintain LTR direction for code blocks and technical content within RTL posts
|
||||
4. THE Blog System SHALL handle mixed LTR/RTL content gracefully (e.g., English words in Persian text)
|
||||
5. THE Blog System SHALL apply RTL-appropriate typography and spacing rules
|
||||
|
||||
### Requirement 10: Performance Optimization
|
||||
|
||||
**User Story:** As a visitor, I want blog pages to load quickly, so that I have a smooth browsing experience.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE Blog System SHALL use NuxtImg component for all images in markdown to enable automatic optimization
|
||||
2. THE Blog System SHALL configure @nuxt/image to generate responsive srcsets and modern formats (webp, avif)
|
||||
3. THE Blog System SHALL use .only() and .without() query modifiers to fetch minimal data for listing pages
|
||||
4. THE Blog System SHALL leverage Nuxt Content's built-in caching for content queries in production
|
||||
5. THE Blog System SHALL prerender all blog routes during build using nitro.prerender.routes configuration
|
||||
6. THE Blog System SHALL lazy-load blog components using defineAsyncComponent where appropriate
|
||||
7. THE Blog System SHALL achieve a Lighthouse performance score of 90+ for blog pages
|
||||
|
||||
### Requirement 11: Development Experience
|
||||
|
||||
**User Story:** As a developer, I want a smooth development experience when working with blog content, so that I can iterate quickly.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN a markdown file is modified, THE Blog System SHALL use Nuxt Content's HMR to hot-reload content without full page refresh
|
||||
2. THE Blog System SHALL include draft posts in queryContent results during development (process.dev check)
|
||||
3. WHERE a markdown parsing error occurs, THE Blog System SHALL display the error overlay with file path and line number
|
||||
4. THE Blog System SHALL define TypeScript interfaces for BlogPost extending ParsedContent for type-safe queries
|
||||
5. THE Blog System SHALL use Nuxt Content's built-in content:list server endpoint for debugging available content
|
||||
6. THE Blog System SHALL provide helpful console warnings when required frontmatter fields are missing
|
||||
|
||||
### Requirement 12: Table of Contents
|
||||
|
||||
**User Story:** As a visitor reading a long blog post, I want to see a table of contents, so that I can quickly navigate to specific sections.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE Blog System SHALL extract table of contents from the body.toc property provided by Nuxt Content
|
||||
2. WHERE a blog post has 3 or more headings, THE Blog System SHALL display a table of contents sidebar on desktop viewports
|
||||
3. THE Blog System SHALL render TOC links using the heading id and text from body.toc.links array
|
||||
4. WHEN a visitor clicks a TOC link, THE Blog System SHALL smooth-scroll to the corresponding heading
|
||||
5. THE Blog System SHALL highlight the active section in TOC based on scroll position using IntersectionObserver
|
||||
6. THE Blog System SHALL hide the TOC on mobile viewports and show it as a collapsible section instead
|
||||
7. THE Blog System SHALL support nested heading levels (h2, h3) in the TOC structure
|
||||
|
||||
### Requirement 13: Search Functionality
|
||||
|
||||
**User Story:** As a visitor, I want to search through blog posts, so that I can quickly find content on specific topics.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE Blog System SHALL provide a search input field on the blog listing page using UInput component
|
||||
2. WHEN a visitor types in the search field, THE Blog System SHALL filter posts using queryContent().where({ $or: [{ title: { $icontains: query } }, { description: { $icontains: query } }] })
|
||||
3. THE Blog System SHALL debounce search input by 300ms to avoid excessive queries
|
||||
4. THE Blog System SHALL display search results count and clear button when search is active
|
||||
5. THE Blog System SHALL highlight search terms in the results using text highlighting
|
||||
6. WHERE no results match the search query, THE Blog System SHALL display a "No posts found" message with suggestions
|
||||
7. THE Blog System SHALL combine search with tag filtering when both are active
|
||||
|
||||
### Requirement 14: RSS Feed Generation
|
||||
|
||||
**User Story:** As a visitor, I want to subscribe to the blog via RSS, so that I can receive updates on new posts.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE Blog System SHALL generate an RSS feed at /blog/rss.xml for English posts
|
||||
2. THE Blog System SHALL generate an RSS feed at /fa/blog/rss.xml for Persian posts
|
||||
3. THE Blog System SHALL use a Nitro server route to dynamically generate RSS XML from queryContent results
|
||||
4. THE Blog System SHALL include post title, description, link, pubDate, and guid in each RSS item
|
||||
5. THE Blog System SHALL set proper Content-Type header (application/rss+xml) for RSS endpoints
|
||||
6. THE Blog System SHALL include channel metadata (title, description, link, language) in the RSS feed
|
||||
7. THE Blog System SHALL add a link to the RSS feed in the blog listing page header for discoverability
|
||||
|
||||
### Requirement 15: Code Block Enhancements
|
||||
|
||||
**User Story:** As a visitor reading technical blog posts, I want enhanced code blocks with copy functionality, so that I can easily use code examples.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE Blog System SHALL display a "Copy" button on all code blocks using a custom ProseCode component
|
||||
2. WHEN a visitor clicks the copy button, THE Blog System SHALL copy the code to clipboard and show a success feedback
|
||||
3. THE Blog System SHALL display the programming language label on code blocks when specified in markdown
|
||||
4. THE Blog System SHALL support line highlighting using Nuxt Content's code highlighting syntax (```js{1,3-5})
|
||||
5. THE Blog System SHALL apply syntax highlighting theme that matches the current color mode (light/dark)
|
||||
6. THE Blog System SHALL support filename display for code blocks using custom metadata (```js [filename.js])
|
||||
|
||||
### Requirement 16: Navigation and Breadcrumbs
|
||||
|
||||
**User Story:** As a visitor, I want clear navigation between blog pages, so that I can easily move around the blog section.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE Blog System SHALL display breadcrumb navigation using UBreadcrumb component on blog detail pages showing Home > Blog > [Post Title]
|
||||
2. THE Blog System SHALL provide a "Back to Blog" link using localePath() to maintain locale context
|
||||
3. THE Blog System SHALL use useRoute() to detect blog routes and highlight the blog section in TopNav component
|
||||
4. WHERE previous/next posts exist chronologically, THE Blog System SHALL query adjacent posts using .sort() and .limit() and display navigation links
|
||||
5. THE Blog System SHALL use localePath() helper from @nuxtjs/i18n for all blog navigation links to maintain locale context
|
||||
6. THE Blog System SHALL implement keyboard navigation (arrow keys) for previous/next post navigation
|
||||
@@ -0,0 +1,315 @@
|
||||
# Implementation Plan
|
||||
|
||||
This implementation plan breaks down the blog system development into discrete, actionable coding tasks. Each task builds incrementally on previous work, with all code integrated and functional at each step.
|
||||
|
||||
## Task List
|
||||
|
||||
- [x] 1. Install and configure Nuxt Content module
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
- Install @nuxt/content package via pnpm
|
||||
- Add @nuxt/content to modules array in nuxt.config.ts (before other modules)
|
||||
- Configure content options: highlight themes (github-light/github-dark), markdown.mdc: true, toc depth
|
||||
- Add content-specific route rules for caching (/blog, /fa/blog with swr: 3600)
|
||||
- Verify installation by starting dev server and checking for content module initialization
|
||||
- _Requirements: 1.1, 1.2, 1.5, 1.6_
|
||||
|
||||
|
||||
|
||||
|
||||
- [ ] 2. Create content directory structure and sample posts
|
||||
- Create content/en/blog/ and content/fa/blog/ directories
|
||||
- Create TypeScript interface for BlogPost extending ParsedContent in app/types/blog.ts
|
||||
- Write 2 sample English blog posts with complete frontmatter (title, description, date, tags, image)
|
||||
- Write 2 sample Persian blog posts with RTL content
|
||||
|
||||
|
||||
|
||||
- Include code blocks, headings, lists, and images in sample posts for testing
|
||||
- Create one draft post to test draft filtering
|
||||
- _Requirements: 2.1, 2.3, 2.4, 3.1, 3.2, 3.5, 3.6_
|
||||
|
||||
- [ ] 3. Implement useBlog composable with utility functions
|
||||
- Create app/composables/useBlog.ts file
|
||||
- Implement calculateReadingTime function (200 words/min from body.children)
|
||||
- Implement formatDate function using Intl.DateTimeFormat with locale support
|
||||
|
||||
- Implement extractUniqueTags function to aggregate tags from posts array
|
||||
- Implement getBlogPath function returning locale-aware path
|
||||
- Implement filterPostsBySearch function for title/description/tags filtering
|
||||
- Implement filterPostsByTag function
|
||||
- Export all functions with proper TypeScript types
|
||||
- _Requirements: 4.7, 11.6_
|
||||
|
||||
- [x] 4. Update i18n translation files with blog keys
|
||||
|
||||
|
||||
- Add blog section to i18n/locales/en.json with all required keys (title, explore, empty, readMore, readingTime, publishedOn, backToBlog, previousPost, nextPost, tableOfContents, searchPlaceholder, filterByTag, allPosts, noResults, copyCode, codeCopied, subscribe)
|
||||
- Add corresponding Persian translations to i18n/locales/fa.json
|
||||
- Verify translations are loaded by checking in dev tools
|
||||
- _Requirements: 4.5, 8.1_
|
||||
|
||||
- [x] 5. Implement blog listing page
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
- [x] 5.1 Update app/pages/blog/index.vue with content fetching
|
||||
|
||||
|
||||
- Replace placeholder content with queryContent implementation
|
||||
- Use useAsyncData to fetch posts for current locale with .where({ draft: { $ne: true } })
|
||||
- Apply .sort({ date: -1 }) and .only() for required fields
|
||||
- Implement computed property for extracting unique tags using useBlog composable
|
||||
- Add reactive refs for searchQuery and selectedTag
|
||||
- Implement computed filteredPosts using filterPostsBySearch and filterPostsByTag
|
||||
- _Requirements: 4.1, 4.2, 4.6, 4.8, 7.1_
|
||||
|
||||
- [x] 5.2 Create BlogCard component
|
||||
|
||||
|
||||
- Create app/components/blog/BlogCard.vue
|
||||
- Accept post prop with BlogPost type
|
||||
- Use UCard as base component with hover effects
|
||||
- Display NuxtImg for cover image with lazy loading and fallback
|
||||
- Display title, description, formatted date, reading time, and tags
|
||||
- Use UBadge for tags display
|
||||
- Use localePath for navigation link
|
||||
- Apply responsive styling
|
||||
- _Requirements: 4.3, 10.1, 10.2_
|
||||
|
||||
- [x] 5.3 Create BlogSearch component
|
||||
|
||||
|
||||
- Create app/components/blog/BlogSearch.vue
|
||||
- Accept modelValue prop and emit update:modelValue
|
||||
- Use UInput with search icon and clear button
|
||||
- Implement debounce using useDebounceFn from VueUse (300ms)
|
||||
- Add i18n placeholder text
|
||||
- _Requirements: 13.2, 13.3_
|
||||
|
||||
- [x] 5.4 Create BlogTagFilter component
|
||||
|
||||
|
||||
- Create app/components/blog/BlogTagFilter.vue
|
||||
- Accept tags array and modelValue props
|
||||
- Display tags as UButton or UBadge with click handlers
|
||||
- Highlight active tag with primary color
|
||||
- Add "All posts" option to clear filter
|
||||
- Update URL query parameter using useRoute and navigateTo
|
||||
- Read query parameter on mount to restore filter state
|
||||
- Apply horizontal scroll on mobile
|
||||
- _Requirements: 7.2, 7.3, 7.4, 7.5, 7.6_
|
||||
|
||||
- [x] 5.5 Create BlogEmpty component and integrate all components
|
||||
|
||||
|
||||
- Create app/components/blog/BlogEmpty.vue with empty state message
|
||||
- Import and use BlogSearch, BlogTagFilter, BlogCard, BlogEmpty in index.vue
|
||||
- Implement grid layout for blog cards (responsive: 1 col mobile, 2 col tablet, 3 col desktop)
|
||||
- Add page header with title and description using i18n
|
||||
- Test search, filter, and empty state scenarios
|
||||
- _Requirements: 4.4, 4.5, 13.4, 13.6_
|
||||
|
||||
|
||||
- [x] 6. Implement blog detail page
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
- [x] 6.1 Update app/pages/blog/[...slug].vue with content fetching
|
||||
|
||||
|
||||
- Replace placeholder content with queryContent().findOne() implementation
|
||||
- Use useAsyncData with slug-based key
|
||||
- Fetch post using _path matching for current locale
|
||||
- Throw createError({ statusCode: 404 }) if post not found
|
||||
- Fetch adjacent posts for prev/next navigation using separate query
|
||||
- Calculate current post index in sorted posts array
|
||||
- _Requirements: 5.1, 5.5, 16.4_
|
||||
|
||||
- [x] 6.2 Implement SEO meta tags and structured data
|
||||
|
||||
|
||||
- Use useContentHead(post) for automatic meta generation
|
||||
- Use useSeoMeta for custom title, og tags, twitter cards
|
||||
- Set og:type to "article" with article:published_time and article:tag
|
||||
- Use post.image or default cover image for og:image
|
||||
- Add JSON-LD structured data using useHead with BlogPosting schema
|
||||
- Include author, datePublished, headline in structured data
|
||||
- _Requirements: 6.1, 6.2, 6.3, 6.4, 6.5, 6.6, 6.8_
|
||||
|
||||
|
||||
|
||||
- [ ] 6.3 Create BlogPost metadata component
|
||||
- Create app/components/blog/BlogPost.vue
|
||||
- Accept post prop with BlogPost type
|
||||
- Display post title as h1
|
||||
- Display formatted date using formatDate from useBlog
|
||||
- Display reading time using calculateReadingTime from useBlog
|
||||
- Display author if available
|
||||
- Display tags as UBadge components
|
||||
- Display cover image using NuxtImg if available
|
||||
- Use semantic HTML (article, header, time elements)
|
||||
|
||||
|
||||
- _Requirements: 5.4_
|
||||
|
||||
- [ ] 6.4 Implement ContentRenderer with Prose styling
|
||||
- Use ContentRenderer component to render post.body
|
||||
- Wrap in article element with proper semantic structure
|
||||
- Apply dir attribute based on locale (rtl for fa, ltr for en)
|
||||
- Add CSS to force LTR for code blocks in RTL context
|
||||
|
||||
|
||||
- Verify Shiki syntax highlighting is working
|
||||
- Test with sample posts containing various markdown elements
|
||||
- _Requirements: 5.2, 5.3, 5.7, 9.1, 9.2, 9.3_
|
||||
|
||||
- [ ] 6.5 Create BlogTableOfContents component
|
||||
- Create app/components/blog/BlogTableOfContents.vue
|
||||
- Accept toc prop from post.body.toc
|
||||
- Render nested heading structure from toc.links
|
||||
- Implement smooth scroll to heading on link click
|
||||
- Use IntersectionObserver to track active section
|
||||
|
||||
|
||||
- Highlight active section in TOC
|
||||
- Make sticky on desktop (position: sticky)
|
||||
- Make collapsible using UAccordion on mobile
|
||||
- Only show if post has 3+ headings
|
||||
- _Requirements: 12.1, 12.2, 12.3, 12.4, 12.5, 12.6, 12.7_
|
||||
|
||||
- [ ] 6.6 Create BlogNavigation component
|
||||
- Create app/components/blog/BlogNavigation.vue
|
||||
- Accept prev and next props (BlogPost | null)
|
||||
|
||||
|
||||
- Display previous post link with title and arrow icon
|
||||
- Display next post link with title and arrow icon
|
||||
- Use UButton with icon slots
|
||||
- Use localePath for navigation links
|
||||
- Implement keyboard navigation (@keydown for arrow keys)
|
||||
- Apply flexbox layout with space-between
|
||||
- _Requirements: 16.4, 16.5, 16.6_
|
||||
|
||||
- [ ] 6.7 Create breadcrumb navigation and integrate all components
|
||||
- Use UBreadcrumb component with links array (Home > Blog > Post Title)
|
||||
- Use localePath for breadcrumb links
|
||||
- Import and use BlogPost, ContentRenderer, BlogTableOfContents, BlogNavigation
|
||||
- Add "Back to Blog" link using localePath
|
||||
- Implement responsive layout (TOC sidebar on desktop, inline on mobile)
|
||||
- Test with both English and Persian posts
|
||||
- Test prev/next navigation
|
||||
- _Requirements: 16.1, 16.2, 16.3, 16.5_
|
||||
|
||||
- [ ] 7. Implement custom Prose components
|
||||
- [ ] 7.1 Create ProseCode component with copy functionality
|
||||
- Create app/components/content/ProseCode.vue
|
||||
- Accept code, language, filename, highlights props
|
||||
- Display language label if provided
|
||||
- Display filename if provided
|
||||
- Add copy button with icon
|
||||
- Implement copy to clipboard using navigator.clipboard API
|
||||
- Show success feedback (icon change or toast)
|
||||
- Apply syntax highlighting theme based on color mode
|
||||
- Support line highlighting from highlights prop
|
||||
- _Requirements: 15.1, 15.2, 15.3, 15.4, 15.5, 15.6_
|
||||
|
||||
- [ ] 7.2 Create custom MDC components
|
||||
- Create app/components/content/BlogCallout.vue for callout boxes
|
||||
- Accept title and type props (info, warning, success)
|
||||
- Use UCard with colored border based on type
|
||||
- Create app/components/content/Alert.vue for inline alerts
|
||||
- Test MDC syntax in sample blog posts (::blog-callout, ::alert)
|
||||
- _Requirements: 5.6_
|
||||
|
||||
- [ ]* 7.3 Customize Prose component styles
|
||||
- Update app.config.ts with prose customization
|
||||
- Define styles for ProseH1, ProseH2, ProseH3 (font sizes, spacing, colors)
|
||||
- Define styles for ProseP (line height, spacing, colors)
|
||||
- Define styles for ProseCode inline code (background, padding, border-radius)
|
||||
- Define styles for ProseA links (color, hover effects)
|
||||
- Define styles for ProseImg (responsive, rounded corners)
|
||||
- Test with sample posts to verify styling
|
||||
- _Requirements: 5.7, 8.2_
|
||||
|
||||
- [ ] 8. Implement RSS feed generation
|
||||
- Create server/routes/blog/rss.xml.ts server route
|
||||
- Use serverQueryContent to fetch published posts for current locale
|
||||
- Detect locale from URL path (/blog/rss.xml vs /fa/blog/rss.xml)
|
||||
- Generate RSS 2.0 XML with channel metadata
|
||||
- Include item elements for each post (title, link, guid, pubDate, description)
|
||||
- Implement escapeXml helper function for XML safety
|
||||
- Set Content-Type header to application/rss+xml
|
||||
- Add RSS link to blog listing page header
|
||||
- Test RSS feed in browser and RSS reader
|
||||
- _Requirements: 14.1, 14.2, 14.3, 14.4, 14.5, 14.6, 14.7_
|
||||
|
||||
- [ ] 9. Configure prerendering and route rules
|
||||
- Update nitro.prerender.routes in nuxt.config.ts to include /blog and /fa/blog
|
||||
- Add dynamic route generation for all blog posts using queryContent
|
||||
- Verify route rules for caching are applied (/blog/**, /fa/blog/** with swr: 3600)
|
||||
- Test static generation by running pnpm generate
|
||||
- Verify all blog routes are prerendered in .output/public
|
||||
- _Requirements: 10.5_
|
||||
|
||||
- [ ] 10. Add blog link to navigation
|
||||
- Update app/components/common/TopNav.vue to include blog link
|
||||
- Use localePath('/blog') for navigation
|
||||
- Highlight blog link when on blog routes using useRoute()
|
||||
- Add blog icon if desired
|
||||
- Test navigation in both locales
|
||||
- _Requirements: 16.3_
|
||||
|
||||
- [ ] 11. Create default blog cover image
|
||||
- Create or add a default cover image to public/img/blog/default-cover.jpg
|
||||
- Ensure image is optimized (WebP format, appropriate dimensions)
|
||||
- Use this image as fallback in BlogCard and SEO meta tags
|
||||
- _Requirements: 6.4_
|
||||
|
||||
- [ ]* 12. Performance optimization and testing
|
||||
- Run Lighthouse audit on blog listing and detail pages
|
||||
- Verify lazy loading of images below fold
|
||||
- Check code splitting in network tab (separate chunks for blog components)
|
||||
- Verify static generation of all routes
|
||||
- Test hot-reload in development mode
|
||||
- Measure and optimize Time to First Byte (TTFB)
|
||||
- Verify Core Web Vitals (LCP, FID, CLS)
|
||||
- _Requirements: 10.3, 10.4, 10.6, 10.7, 11.1_
|
||||
|
||||
- [ ]* 13. Accessibility testing and improvements
|
||||
- Test keyboard navigation (Tab, Enter, arrow keys)
|
||||
- Test with screen reader (NVDA or VoiceOver)
|
||||
- Verify color contrast ratios using browser dev tools
|
||||
- Ensure all interactive elements have focus indicators
|
||||
- Add ARIA labels where needed
|
||||
- Verify semantic HTML structure
|
||||
- Test with reduced motion preference
|
||||
- _Requirements: 8.3, 8.4, 8.5, 8.6_
|
||||
|
||||
- [ ]* 14. Cross-browser and responsive testing
|
||||
- Test on Chrome, Firefox, Safari, Edge
|
||||
- Test on mobile devices (iOS Safari, Chrome Android)
|
||||
- Test on tablet viewports
|
||||
- Verify RTL layout on Persian pages
|
||||
- Test search and filter functionality on all devices
|
||||
- Verify image optimization and lazy loading
|
||||
- Test code block copy functionality
|
||||
- _Requirements: 8.1, 9.1, 9.2, 9.4_
|
||||
|
||||
- [ ]* 15. Documentation and sample content
|
||||
- Create README.md in content/ directory with authoring guidelines
|
||||
- Document frontmatter schema and required fields
|
||||
- Provide markdown examples for common elements
|
||||
- Document MDC component usage
|
||||
- Add comments in code for complex logic
|
||||
- Update main README.md with blog feature description
|
||||
- _Requirements: 11.3, 11.4_
|
||||
|
||||
Reference in New Issue
Block a user