# Personal Page With Blog

Multi-page personal site (home, portfolio, blog, post) from view/*.html partials on PDRenderKit 1.2.0, with JS masonry and Markdown viewer.

## Overview

| Item | Value |
|---|---|
| Created | 2023-06-21 |
| Category | Blog Examples |
| HTML files | `index.html`, `portfolio.html`, `blog.html`, `blog-content.html`, `view/nav.html`, `view/header.html`, `view/portfolio.html`, `view/service.html`, `view/about.html`, `view/skill.html`, `view/client.html`, `view/contact.html`, `view/footer.html`, `view/blog-content.html` |
| Source | [target/20230621](https://github.com/pardnio/demo-web/tree/main/target/20230621) |

## Live Preview

<iframe src="/target/20230621/" title="Personal Page With Blog" loading="lazy" style="width:100%;height:640px;border:1px solid #e5e7eb;border-radius:8px"></iframe>

[Open the example in a new tab](/target/20230621/)

## Page Sections

| Section | Description |
|---|---|
| Nav (view/nav.html) | Sticky nav with brand link and :for links HOME / PORTFOLIO / BLOG; hamburger @click=tab toggles the mobile menu below 800px. |
| Header (view/header.html) | Headline, subheading and GitHub / LinkedIn buttons with reveal animation. |
| Portfolio (view/portfolio.html) | JS masonry of placeholder figures from the page's global ary (8 on index, 24 on portfolio.html) with auto-built ALL/TAG1/TAG2/TAG3 filter tabs. |
| Service (view/service.html) | 6 icon articles via :for over icon names with interpolated class fa-{{ e }}. |
| About (view/about.html) | Photo with decorative image/about.svg, bio and two 3-item timelines. |
| Skill (view/skill.html) | 8 circular pie indicators with shuffled :year values 1..8, animated when revealed. |
| Client (view/client.html) | 5 testimonial cards in a horizontal looping carousel with prev/next buttons. |
| Contact (view/contact.html) | :model form (name, email, message) with @click=send alert, beside an embedded Google Maps iframe. |
| Footer (view/footer.html) | Copyright and :for icon links (GitHub, LinkedIn, mail). |
| Blog list (blog.html) | Two-column layout: author card, 8 post links to blog-content.html, prev/next page links; sidebar with search, latest 4 posts, topics and tags; mobile floating bottom search bar. |
| Blog post (blog-content.html + view/blog-content.html) | Article header, details/summary table of contents, PDMarkdownKit viewer rendering the PDMarkdownKit README, prev/next post links, same sidebar. |

## Interactions

- js/index.js and js/blog.js create new PD({id: "body"}) with nav items; each view/*.html script creates its own PD instance and, in next(), registers its *.delay elements with the shared delay_observer.
- Reveal: IntersectionObserver removes .delay, sets done=1 after 700ms (wipe overlay ::after), removes .at after 1300ms; skill pies animate on [done="1"][year].
- updateShadow(): nav box-shadow and .float-bottom shadow scale with body scroll position (0..32px).
- view/portfolio.html: absolute-positioned masonry placing each item in the shortest column (1/2/3 columns at &lt;480 / 480 / 1024px), tag filter tabs set filter-key and updatePortfolio() re-lays out with opacity, debounced 300ms window.onresize relayout.
- view/client.html: clones the cards for an endless loop and animates scrollLeft with setInterval (10ms) on prev/next, jumping to the middle copy at either end.
- js/blog.js (module): fetches https://cdn.jsdelivr.net/npm/pdmarkdownkit@1.6.0/README.md and, on pages with section[name=blog-content], mounts a PDMarkdownKit viewer before section.page; also offsets the sticky sidebar top when taller than the viewport.
- In js/blog.js the tab event is an arrow function using this.$pre(), so the mobile menu toggle on blog pages has no element as this.

## Dependencies

| Name | Version | Source |
|---|---|---|
| Font Awesome Free | 6.5.2 | https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.5.2/css/all.min.css |
| PDRenderKit | 1.2.0 | https://cdn.jsdelivr.net/npm/pdrenderkit@1.2.0/dist/PDRenderKit.js |
| PDMarkdownKit (ES module, blog pages) | 1.6.0 | https://cdn.jsdelivr.net/npm/pdmarkdownkit@1.6.0/dist/PDMarkdownKit.module.js |
| Google Maps embed iframe | - | https://www.google.com/maps/embed?pb=... |
| Google Analytics (gtag.js) | - | https://www.googletagmanager.com/gtag/js?id=G-L5VYEZPVXX |
| js/index.js (index.html, portfolio.html) | - | ./js/index.js |
| js/blog.js (blog.html, blog-content.html) | - | ./js/blog.js (type=module) |

## Styling

| Item | Value |
|---|---|
| SCSS entry | `sass/index.scss` |
| Output CSS | `css/index.css` |
| Partials | `function/_hsbTohsl.scss`, `_init.scss`, `_nav.scss`, `_header.scss`, `_blog.scss`, `_portfolio.scss`, `_service.scss`, `_about.scss`, `_skill.scss`, `_client.scss`, `_contact.scss`, `_footer.scss`, `animation/_section-3.scss`, `animation/_pie.scss`, `animation/_bg-move.scss` |

function/_hsbTohsl defines hsb()/hsba() SCSS functions converting HSB to HSL; _init holds reset, breakpoint vars ($_800: 50rem etc.) and HSB-derived color scales (brand/success/notify/error/info/border). index.scss defines the global .at/.delay/[done] reveal with a gradient wipe ::after and a rotated a.hint watermark. _skill @imports animation/_pie and uses @for over [done][year] for pie rotation; _blog covers list/post/sidebar (sticky), details TOC and .float-bottom; _client handles [row] layouts. animation/_bg-move is present but not imported. Inline &lt;style&gt; sets --col-brand-5 #f1c50e and --gradient-col.

```bash
cd target/20230621
npx sass sass/index.scss css/index.css --no-source-map || exit 1
```

## Techniques

- PDRenderKit PD templating: :path partials, :for, {{ }} incl. inside attributes (:class="... fa-{{ e }}"), :model, @click, next() lifecycle hook.
- Custom SCSS @function for HSB to HSL color conversion and generated color scales.
- Shortest-column masonry with absolute positioning computed in JS; filter via opacity/left transitions.
- Reveal wipe effect: ::after with 300% three-band gradient whose background-position is animated via [done] attribute.
- details/summary TOC, position: sticky nav and sidebar, backdrop-filter, max-width 799.99px / min-width 480, 640, 800, 1024px breakpoints.

## External Assets

- https://cdn.jsdelivr.net/npm/pdmarkdownkit@1.6.0/README.md (fetched as blog post content)
- https://www.google.com/maps/embed?pb=... (contact map iframe)
- https://fakeimg.pl/1024/282828/eae0d0/?text=sample (placeholder images)
- https://pardn.io/image/head.png (favicon)
- https://pardn.io/web-template/image/20230621.jpg (og/twitter image)

## Related

- [Project Structure](/project-structure)
- [Styling Workflow](/styling-workflow)
- [Frameworks](/frameworks)
