### Description
#### Backend
- String and interger can be pass as `id` to `GET` `/post/{id}`
- For the posts existed, the default `semantic_id` for them will be `_id`. (e.g. `_1`, `_2`)
- Semantic ID should follow the rules:
1. It shouldn't be an integer
1. It should match the pattern: `^[0-9a-zA-Z_\-]+$`
<br>
|Semantic ID|Result|Note|
|-|-|-|
|12|X|against with `i`|
|-3|X|against with `i`|
|3.14|X|against with `ii`|
|hello world|X|against with `ii`|
|*EMPTY*|X|against with `ii`|
|12_34-56|O||
#### Frontend
- The href of post preview card becomes the semantic ID.
### Package Changes
```toml
regex = "1.12.1"
```
### Screenshots

### Reference
Resolves#125.
### Checklist
- [x] A milestone is set
- [x] The related issuse has been linked to this branch
Reviewed-on: #134
Co-authored-by: SquidSpirit <squid@squidspirit.com>
Co-committed-by: SquidSpirit <squid@squidspirit.com>
### Description
This PR updates the application to handle posts that may not have a publication date (e.g., drafts) by making the `published_time` field optional across the entire post feature stack.
This ensures that draft posts can be processed and rendered without causing errors, and prevents search engine metadata from being generated for content that is not yet published.
#### Key Changes:
* **DTO & Schema (`postInfoResponseDto.ts`):**
* The Zod schema for `PostInfoResponseSchema` has been updated to mark `published_time` as `.nullable()`.
* The `PostInfoResponseDto` class now correctly handles a `null` value from the API, mapping it to `Date | null`.
* **Domain Entity (`postInfo.ts`):**
* The core `PostInfo` entity's `publishedTime` property is now typed as `Date | null` to reflect the business logic that a post may be unpublished.
* **View Model (`postInfoViewModel.ts`):**
* Updated `publishedTime` to be `Date | null`.
* Added a new `isPublished` boolean getter for convenient conditional logic in the UI.
* The `formattedPublishedTime` getter now returns `string | null`.
* Dehydration and rehydration logic (`dehydrate`/`rehydrate`) has been updated to correctly handle the nullable `publishedTime`.
* **UI Component (`PostContentPage.svelte`):**
* The component now uses the new `isPublished` flag to conditionally render the `<StructuredData>` component for SEO. This ensures that structured data is only included for posts that have been officially published.
### Package Changes
_No response_
### Screenshots
_No response_
### Reference
Resolves#118
### Checklist
- [x] A milestone is set
- [x] The related issuse has been linked to this branch
Reviewed-on: #121
Co-authored-by: SquidSpirit <squid@squidspirit.com>
Co-committed-by: SquidSpirit <squid@squidspirit.com>
### Description
#### Overview
This PR improves the website's SEO by:
1. Moving title and meta description tags from app.html to individual page components
2. Adding dynamic meta descriptions based on page content
3. Implementing structured data for blog posts using JSON-LD
4. Optimizing meta descriptions for better search engine visibility
#### Changes
- **app.html**: Removed static title and meta description tags
- **HomePage.svelte**: Added descriptive title parameter to generateTitle function
- **Terminal.svelte**: Dynamically generates meta description from terminal lines
- **PostContentPage.svelte**: Added meta description and structured data for blog posts
- **PostOverallPage.svelte**: Added descriptive meta description for blog listing page
- **StructuredData.svelte**: Created new component to generate JSON-LD structured data for blog posts
#### Benefits
- Improved SEO through better metadata management
- Enhanced search engine visibility with structured data
- More accurate and dynamic meta descriptions
- Better control over page-specific metadata
> [!NOTE]
> Since sitemap auto generating is a little more complex, it will be solved in #117 in the future.
### Package Changes
_No response_
### Screenshots
_No response_
### Reference
Resolves#48
### Checklist
- [x] A milestone is set
- [x] The related issuse has been linked to this branch
Reviewed-on: #116
Co-authored-by: SquidSpirit <squid@squidspirit.com>
Co-committed-by: SquidSpirit <squid@squidspirit.com>
### Description
- Enhance typography and color consistency in PostPreview and PostContentPage
- Add tailwind configuration for custom typography styles
### Package Changes
_No response_
### Screenshots
_No response_
### Reference
Resolves#87
### Checklist
- [x] A milestone is set
- [x] The related issuse has been linked to this branch
Reviewed-on: #88
Co-authored-by: SquidSpirit <squid@squidspirit.com>
Co-committed-by: SquidSpirit <squid@squidspirit.com>
### Description
- Use `generateTitle` to combine app name and page title.
### Package Changes
_No response_
### Screenshots
|Home|Post Overall|Post Content|
|-|-|-|
||||
### Reference
Resolves#73
### Checklist
- [x] A milestone is set
- [x] The related issuse has been linked to this branch
Reviewed-on: #77
Co-authored-by: SquidSpirit <squid@squidspirit.com>
Co-committed-by: SquidSpirit <squid@squidspirit.com>
### Description
- Implement the content page
- Parse markdown formant content to html by `markdown-it`
- Use `sanitize-html` to prevent from XSS attack
- Style the html with `tailwindcss-typography`
- Fix the issue when backend parse the password to url
- Fix and make the post info list from backend always sorted by id
### Package Changes
### Rust
```toml
percent-encoding = "2.3.1"
```
### Node
```json
{
"@types/markdown-it": "^14.1.2",
"@types/sanitize-html": "^2.16.0",
"markdown-it": "^14.1.0",
"sanitize-html": "^2.17.0"
}
```
### Screenshots
|Desktop|Mobile|
|-|-|
|||
### Reference
Resolves#45
### Checklist
- [x] A milestone is set
- [x] The related issuse has been linked to this branch
Reviewed-on: #67
Co-authored-by: SquidSpirit <squid@squidspirit.com>
Co-committed-by: SquidSpirit <squid@squidspirit.com>