# Query Blog Index

> A dark product blog and changelog index where typing a query or picking a topic promotes the best matching post into a large lead slot, with the rest regrouping below.

Canonical: https://gsapvault.com/sections/query-blog-index-section
Live demo: https://gsapvault.com/demos/query-blog-index-section/index.html

| Property | Value |
|----------|-------|
| Type | section |
| Tier | paid |
| Price | Included only in the Vault |
| Difficulty | advanced |
| Plugins | Flip |
| Techniques | flip-layout, filter, clip-path, stagger, keyboard-navigation, progressive-enhancement, container-queries, responsive-section |
| Uses Lenis | No |

## Overview

Query Blog Index Section is the front page of a product blog or changelog: release notes, engineering write-ups, incident reviews and company news in one list, built so a visitor can find the latest or most relevant post and open it.

The newest post leads with a large photograph, the next two sit beneath it as cards, and everything older runs as a dense table of dates, titles, version tags and topics. A command-style filter bar sits above. Type a word or a version such as v4.1 and the index ranks itself: the best match takes the lead slot, its photograph opening from the top edge, the next two become cards and the rest glide into place. Matched words light up in the titles and every topic shows how many posts it holds for the current query.

The fictional Keelson CI example is dark, hairline-ruled and set in Geist with Geist Mono, with eight generated photographs of the team, their machines and their data centre. Every post is an ordinary list item with a link, date, topic, optional version and optional photo, so a buyer adds or removes posts by editing HTML.

## Features

- Command-style filter that ranks posts by title, version, topic, summary and author as you type
- Best match promoted into a large lead slot with a clip-path photo reveal; the next two become cards
- Unchanged posts glide to their new place with GSAP Flip; filtered-out posts fade away
- Topic buttons and counts generated from the markup, with live per-topic counts for the current query
- Matched words highlighted in titles and matching version tags filled with the accent
- Keyboard first: / focuses the filter, arrow keys walk the results, Enter opens the top result
- Photo-less posts such as patch releases get a typographic version plate in the lead and card slots
- Every post listed and linked with no JavaScript; tiers are pure CSS from visible order
- Container-aware layout for wide pages, narrow columns and phones
- Independent instances, unique IDs and exact teardown

## Use Cases

- Software products publishing release notes, engineering posts and incident reviews
- Studio or agency journals with a mix of case notes, news and long reads
- Independent publications that want readers to find a back-issue article quickly
- Documentation sites with a changelog and announcement feed

## Vibe-Code Ready Setup

This website section includes `START-HERE-AI.md`, a product-specific copy-paste setup prompt for Cursor, Claude Code, ChatGPT, GitHub Copilot, Windsurf, and other coding assistants. It tells the assistant to inspect the existing stack, integrate the supplied files, preserve the design, scope selectors, retain accessibility and responsive behaviour, add framework-appropriate GSAP cleanup, and report what it tested.

[How AI-assisted setup works](https://gsapvault.com/vibe-coding)

## How It Works

The section starts as one ordered list of posts, newest first. CSS reads visible order with :nth-child(of S): the first visible post is laid out as the lead, the next two as cards, the rest as table rows. With no JavaScript that is simply the newest three and the archive.

The script reads every post's title, topic, version, summary, author and date from the markup, builds the topic buttons with their counts and reveals the filter bar. Each change of query or topic scores the posts, reorders the list so the results come first in rank order and marks the rest as filtered out. Before that change it records the posts' positions with Flip.getState. Posts that keep their tier glide from the recorded positions with Flip.from; posts that change tier, such as a row promoted to the lead, stage in afresh, their photo frame opening with a clip-path while the image settles from a slight zoom and their lines rise in order.

Typing quickly interrupts nothing awkwardly: each update captures the current mid-flight positions, kills the previous Flip and speeds any unfinished reveals to their end, so the index always settles on the last query. Reduced motion applies every change instantly, and teardown restores the original markup, order and titles.

## Documentation

How this website section works and how it goes into a page. The reference you use once you own the files (worked examples, events, the programmatic API, the class list) ships with the download.

### Quick Start

Copy these into your project:

- the `<section class="kql">` element from `index.html`, between the `EXTRACT START` and `EXTRACT END` comments
- `assets/style.css`
- `assets/script.js`
- `assets/img/` (or your own photographs)

Load the fonts and styles, then GSAP, Flip and the section script after the markup:

_Code snippet omitted: it ships with the download._

Everything outside the `<section>` in `index.html` (the page background and body margin) is demo furniture. No build step is needed.

### Make it yours

#### Posts

Each post is one `<li class="kql-post" data-kql-post>` inside `<ol data-kql-list>`, newest first. To add a post, copy a whole `<li>` and edit it; to remove or reorder posts, delete or move whole `<li>` elements. Keep the list in date order: with an empty filter the first post is the lead and the next two are cards.

Inside each post:

| What | Where |
| --- | --- |
| Link and title | `.kql-post__title a` (`href` and text). Keep the title plain text; it is highlighted while filtering |
| Date | `<time datetime="YYYY-MM-DD">`, displayed text is yours to format |
| Topic | `.kql-post__topic`. Topic buttons and counts are built from these, in order of first appearance |
| Version (optional) | `.kql-post__ver`. Delete the span for posts without one |
| Summary | `.kql-post__dek`, shown in the lead and card slots |
| Author and read time | `.kql-post__by` and its inner `<span>` |
| Photo (optional) | `.kql-post__media` with its `<img>` |

The whole card is clickable through the title link. There is no count limit; with a single post the section shows it as the lead and the filter still works. With only one topic, no topic buttons are shown.

#### Photos

Each photo is an ordinary `<img>` inside `.kql-post__media`:

- **Files:** `assets/img/<name>.webp` at 1600 x 1000, with an 800 x 500 copy in `srcset`. Any landscape photo works; 16:10 or 3:2 at 1600px wide or more is ideal. The frame is 16:10 on wide screens and 4:3 on phones, and the image is cropped to fill it.
- **Replace:** change `src`, `srcset` (or delete `srcset`), `width`/`height` to your file's size, and `alt`.
- **Focal point:** add `style="--kql-focus: 50% 30%"` to the `<img>` to move the crop (it sets `object-position`).
- **No photo:** delete the whole `.kql-post__media` div. In the lead or card slot the post then shows a plate with its version number, or its date when it has no version.

Load the first post's photo eagerly (as in the demo) and give the rest `loading="lazy"`.

#### Heading, filter and footer

- Heading and intro: `.kql__title` (an `h2`; change the tag freely, the styles use the class) and `.kql__sub`.
- Feed link: `.kql__feed`. Older posts link: `.kql__older`. Both point at placeholder anchors you should replace.
- Filter label, placeholder, keyboard hints and the empty-state text live in `<template data-kql-controls>`. The script copies them into place, so they never show without JavaScript. The ruler text (Latest post, Best match for ...) is written by the script.
- The note in `.kql__foot` describes the demo content; delete it.

#### Brand variables

Set these on `.kql` (or a class you add to it):

| Variable | Default | Controls |
| --- | --- | --- |
| `--kql-ground` | `#0b0d10` | Section background |
| `--kql-surface`, `--kql-surface-2` | `#12151a`, `#181c22` | Filter bar, hovered rows, plates |
| `--kql-line`, `--kql-line-strong` | `#242931`, `#353b45` | Hairlines and borders |
| `--kql-text`, `--kql-muted` | `#eceef1`, `#949ba6` | Text colours |
| `--kql-accent` | `#5de4ff` | Prompt, focus, pressed topic, matches, version tags |
| `--kql-accent-ink` | `#04161b` | Text on a filled accent (matching version tag) |
| `--kql-font-sans`, `--kql-font-mono` | Geist, Geist Mono | Type roles |
| `--kql-width`, `--kql-gutter`, `--kql-space` | `1360px`, fluid, fluid | Content width, side padding, top and bottom space |
| `--kql-radius` | `6px` | Corners |

A light rebrand example:

_Code snippet omitted: it ships with the download._

Check the contrast of your accent against your ground; arbitrary colours are not automatically accessible.

### Behaviour and options

- `data-duration="0.5"` on `.kql` sets the base transition length in seconds.
- The script mounts every `[data-query-blog]` on the page. For content added later, or frameworks that re-render:

_Code snippet omitted: it ships with the download._

Ranking: every word typed must appear somewhere in the post. Title matches weigh most, then version, topic, summary, author and date; ties keep the newest first. A light stem lets "cache" find "caching".

### Accessibility and integration

- Tested with keyboard, touch, reduced motion (including switching it while the page is open), JavaScript disabled and GSAP blocked.
- Without JavaScript the filter bar never renders and every post is listed and linked, newest first. Without GSAP the filter works with instant changes.
- `/` focuses the filter of the section most in view unless the visitor is typing in a field. In the filter, Down moves to the first result, Enter opens the top result and Escape clears. In the list, Up and Down move between posts, Home and End jump, and Escape returns to the filter.
- Result counts are announced through a polite status once typing pauses.
- Topic buttons use `aria-pressed`. IDs are made unique per instance, so two copies can share a page.
- The layout follows the section's own width (container queries), so it works in narrow columns as well as full width. It does not pin, scroll-jack or install a smooth scroller.

### Dependencies and credits

- [GSAP](https://gsap.com) 3.15 core and Flip, loaded from jsDelivr. GSAP and its plugins are free under the GSAP standard licence.
- Geist and Geist Mono by Vercel, via Google Fonts, SIL Open Font License.
- The photographs are generated concept images made for this demo. Keelson, its people, posts and figures are fictional sample content; replace them with your own.

## What You Get

- `index.html`: working demo page
- `assets/script.js`: commented, readable source
- `assets/style.css`: effect styles
- `README.md`: full documentation with examples and framework integration notes
- `START-HERE-AI.md`: product-specific copy-paste prompt for AI-assisted setup
- `LICENSE.txt`: standard license terms
- Lifetime updates: re-download anytime from your library

## Get the Code

This website section is included only in the Vault, for existing and new owners. It is not sold individually. The standard licence covers unlimited personal and commercial projects; bundled assets retain their own licence requirements.

- [Get the Vault](https://gsapvault.com/pricing)
- [The Vault (£99 one-time, best value): every collection in the Vault library, plus future items added to those collections](https://gsapvault.com/effects)

---

From [GSAP Vault](https://gsapvault.com): production-ready GSAP animation effects. Full catalog for agents: https://gsapvault.com/llms-full.txt
