diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index ccc1d2e..243d7f5 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,59 +1,7 @@ # GitHub Copilot Instructions -## Project Overview -This is a Jekyll-based static blog for solrevdev.com using the Hyde theme with custom modifications. +All agent guidance for this repository lives in [`AGENTS.md`](../AGENTS.md) at +the repository root. Read that file. -## Key Development Guidelines - -### Blog Posts -- Located in `_posts/` directory -- Use Jekyll front matter with these fields: - - `layout: post` - - `title: [Post Title]` - - `description: [SEO description]` - - `summary: [Brief summary]` - - `cover_image: [/images/filename.ext]` (optional) - - `tags: [array of tags]` - -### Cover Images -- Store in `/images/` directory -- Use `cover_image: /images/filename.ext` in front matter -- Supported formats: SVG (preferred), PNG, JPG - all handled gracefully -- Size handling: CSS automatically scales images responsively -- Recommended dimensions: 800x400px aspect ratio -- Keep file size under 50KB for performance -- Optional field - posts without cover images work perfectly - -### Local Development Image Issues -**Important**: During local development, images may not display properly due to URL resolution: - -**Solutions**: -1. **Use Jekyll server**: `bundle exec jekyll serve --host 127.0.0.1 --port 4000` -2. **Use localhost domain**: `http://localhost:4000` or `http://127.0.0.1:4000` -3. **Relative paths work**: with file:// protocol for testing - -**Don't use**: -- Absolute paths (`/images/...`) with file:// protocol - will fail -- localhost URLs without running Jekyll server - -### Styling -- Custom styles in `public/css/custom.scss` -- Uses SCSS with Jekyll compilation -- Responsive breakpoints: 768px (tablet), 480px (mobile) -- Cover images have hover effects and responsive sizing - -### File Structure -``` -├── _posts/ # Blog posts -├── _layouts/ # Jekyll layouts -├── _includes/ # Jekyll includes -├── public/css/ # SCSS stylesheets -├── images/ # Blog post images -├── claude.md # Claude development notes -└── .github/ # GitHub configuration -``` - -### Testing -- Test responsive design at 375px (mobile), 768px (tablet), 1200px+ (desktop) -- Cover images scale automatically across all device sizes -- Posts without cover images display normally \ No newline at end of file +It covers the post front matter, the drafting and publishing workflow, cover and +social images, SEO metadata, local development, and visual QA. diff --git a/AGENTS.md b/AGENTS.md index abcbadb..4cc9146 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,12 +1,77 @@ -# Repository Instructions +# AGENTS.md + +Repository-specific guidance for AI agents working on this Jekyll blog. + +## Project Overview + +This is the source for `solrevdev.com`, a Jekyll-based static blog using the +Hyde theme with custom styling. + +## Blog Posts + +Blog posts live in `_posts/` and use standard Jekyll front matter. New posts +should include: + +```yaml +--- +published: false +layout: post +title: Post Title +description: One concise SEO description. +summary: One concise home-page teaser. +cover_image: /images/post-cover.svg +image: /images/post-cover.png +tags: +- dotnet +- csharp +--- +``` + +Keep `published: false` while drafting unless the user explicitly asks to +publish the article. + +## Drafting Workflow + +- Before finalizing a draft, ask the user what publication date they want. +- Drafts live in `_posts/` with `published: false`. This repo has no `_drafts/` + folder, so keep the file where it is and flip the flag when it goes live. +- When publishing, rename the file to `_posts/YYYY-MM-DD-slug.md` and make sure + any `date:` front matter, if present, matches that filename date. +- Do not silently publish an article by removing `published: false`. +- Do not use a future date to hold a post back. `_config.yml` sets no `future` + key, so Jekyll defaults to `future: false` and the post stays invisible on + GitHub Pages until the date passes, with no error to explain why. Use + `published: false` with the intended date instead. +- If the user asks for a PR, keep the PR focused on the article and its related + assets unless they explicitly ask for wider site changes. -## Blog Post Cover Images and SEO Metadata +## Writing Style + +- Match the tone of recent posts: practical, first-person, direct, and focused + on what was built, why it exists, how it works, and what comes next. +- Prefer concrete implementation details over generic marketing copy. +- Use the existing section rhythm when it fits the topic, for example: + `Overview`, `The Problem`, `What I Built`, `Implementation Highlights`, + `Testing Strategy`, and `What's Next`. +- Keep code examples runnable or clearly illustrative. +- Avoid em dashes in new prose. Use commas, colons, parentheses, or separate + sentences. +- New posts should normally end with the established sign-off: + +```markdown +Success! 🎉 +``` -When creating or updating a blog post, use the same cover-image pattern as recent posts: +## Cover Images and Social Images + +New technical posts should normally have both a visible SVG cover and a PNG +social image. 1. Create a deterministic SVG cover in `/images/`. - Use an 800x400 canvas. - - Match the existing style: simple full-canvas background, restrained gradients, terminal or tool UI motifs, clear title text, and a short subtitle. + - Match the existing style: simple full-canvas background, restrained + gradients, terminal or tool UI motifs, clear title text, and a short + subtitle. - Keep the SVG local, lightweight, and hand-editable. - Avoid remote image hosts. @@ -30,32 +95,123 @@ When creating or updating a blog post, use the same cover-image pattern as recen image: /images/example-cover.png ``` -5. Make sure each post has useful SEO front matter: - - ```yaml - title: Clear post title with the main topic - description: One concise search-friendly sentence describing the post. - summary: Optional longer summary for homepage excerpts. - tags: - - dotnet - - csharp - ``` - -6. Verify the generated HTML includes the expected metadata: +5. Verify the generated HTML includes the expected metadata: - canonical URL - `meta name="description"` - `og:image` using the PNG file - `twitter:card` set to `summary_large_image` - the PNG image is 1200x630 -7. Build before finishing: +Both keys are needed, because two different consumers read them: - ```bash - bundle exec jekyll build - ``` +| Key | Value | Read by | Result | +| --- | --- | --- | --- | +| `cover_image` | the 800x400 SVG | `_layouts/post.html` and `_layouts/page.html` | the visible image at the top of the page | +| `image` | the 1200x630 PNG | the `jekyll-seo-tag` plugin, via `{% seo %}` in `_includes/head.html` | `og:image` and `twitter:image` | -## Writing Style +No layout in this repo reads `image`, and the plugin does not read `cover_image`. +Setting only `cover_image` emits no `og:image` at all and quietly downgrades +`twitter:card` from `summary_large_image` to `summary`, so the post loses its +large social preview with nothing in the build output to warn you. There is no +site-wide fallback image in `_config.yml`. + +Every post since August 2025 sets both, as do `about/index.md` and +`uses/index.md`. Posts before that set neither and are fine left alone. + +The post layout uses the page title as cover image alt text. + +`public/css/custom.scss` caps the visible cover at 400px tall on desktop, 250px +below 768px, and 200px below 480px. Keep the SVG under 50KB. + +## SEO Metadata + +- Every post should have an accurate `title`, `description`, `summary`, and + useful `tags`. +- Do not make SEO changes that are only keyword stuffing. Prefer accurate + titles, descriptions, tags, and useful cover/social metadata. +- Use a concise `summary:` so the home page does not leak large code blocks or + overly long paragraphs. + +## Styling + +- Custom styles live in `public/css/custom.scss`. +- The site uses SCSS through Jekyll compilation. +- Existing responsive breakpoints include 768px for tablet and 480px for mobile. +- Cover images have responsive sizing and hover effects; preserve that behavior + unless the user asks for a design change. + +## Listing Pages + +When creating or editing posts, verify that the article works in all three +public contexts: + +- Home page post listing: `index.html` uses `summary:` or `description:` before + falling back to body text. +- Archive listing: `archive/index.md` shows the post date and truncated title. +- Individual post page: `_layouts/post.html` renders `cover_image`, title, date, + and full content. + +## Local Development + +Run the Jekyll server for visual checks: + +```bash +bundle exec jekyll serve --host=localhost --livereload +``` + +A `published: false` post is skipped by that build. Preview one with +`--unpublished`. The `--drafts` flag renders a `_drafts/` folder instead, which +this repo does not have, so it will not show the post: + +```bash +bundle exec jekyll serve --unpublished --host=localhost --livereload +``` + +Add `--future` too if the post is dated later than today. + +Then inspect: + +- `http://localhost:4000/` +- `http://localhost:4000/archive/` +- the post URL + +During local development, images may fail if opened directly with `file://` and +absolute paths such as `/images/example.svg`. Use the Jekyll server for reliable +testing. + +Build before finishing: + +```bash +bundle exec jekyll build +``` + +## Visual QA + +- Test representative widths when changing post layout or cover-image CSS: + 375px mobile, 768px tablet, and 1200px or wider desktop. +- Confirm cover images scale without cropping important content. +- Confirm posts without cover images still render normally. +- Confirm the home page excerpt remains readable and compact. +- Confirm the archive title is not awkwardly truncated. + +Which browser tool to drive is a machine-level choice, not a repo one, so it +lives in the global agent instructions rather than here. Follow whatever order +those set out. This file only says what to look at. + +## Site Structure + +```text +_posts/ Blog posts, including unpublished ones +_layouts/ Jekyll layouts +_includes/ Jekyll includes +public/css/ SCSS stylesheets +images/ Blog post cover and social images +README.md Human maintainer workflow +AGENTS.md AI agent workflow, the single source +CLAUDE.md Pointer to AGENTS.md +.github/copilot-instructions.md Pointer to AGENTS.md +``` -- Avoid em dashes in new prose. Use commas, colons, parentheses, or separate sentences. -- Keep technical writing practical and direct. -- Do not make SEO changes that are only keyword stuffing. Prefer accurate titles, descriptions, tags, and useful cover/social metadata. +`AGENTS.md` is the only agent guidance in this repo. `CLAUDE.md` and +`.github/copilot-instructions.md` exist because those tools look for those +paths; both just point here. Add new guidance to this file, not to them. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..1a7528a --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,7 @@ +# Claude Development Notes + +All agent guidance for this repository lives in [`AGENTS.md`](AGENTS.md). Read +that file. + +It covers the post front matter, the drafting and publishing workflow, cover and +social images, SEO metadata, local development, and visual QA. diff --git a/README.md b/README.md index 6bd1617..c39cf3e 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,76 @@ Notes: - `` is optional; use it when you want the per‑post page to show a short intro before the rest. - Old posts don’t need to be edited. They’ll automatically use their first paragraph. +## Blog post publishing workflow + +New article drafts should normally start with `published: false` in the post +front matter so they can be reviewed safely on a branch or pull request. + +Recommended front matter for new posts: + +```yaml +--- +published: false +layout: post +title: My Post +description: A concise SEO description. +summary: A concise home-page teaser. +cover_image: /images/my-post-cover.svg +image: /images/my-post-cover.png +tags: +- dotnet +- csharp +--- +``` + +Set both image keys. `cover_image` is the 800x400 SVG that the post layout +shows at the top of the page. `image` is the 1200x630 PNG that `jekyll-seo-tag` +turns into `og:image` and `twitter:image`. Leaving `image` out drops the +`og:image` tag and downgrades `twitter:card` to `summary`, so the post gets no +large preview when shared. `AGENTS.md` has the `rsvg-convert` command that +generates the PNG from the SVG. + +Before publishing, decide the publication date and make the filename match it: + +```text +_posts/YYYY-MM-DD-post-slug.md +``` + +If a post has an explicit `date:` field in front matter, keep it aligned with +the filename date. When the article is ready to go live, remove +`published: false` or change it to `published: true`, then merge the pull +request. + +Do not use a future date to hold a post back. `_config.yml` sets no `future` +key, so Jekyll defaults to `future: false` and GitHub Pages will hide the post +until the date passes without reporting an error. Use `published: false` +instead. + +After merging, GitHub Pages normally rebuilds automatically. If a manual rebuild +is needed, use the GitHub CLI from an authenticated checkout of this repository: + +```bash +gh api --method POST repos/solrevdev/solrevdev.github.io/pages/builds +``` + +For visual checks, run the site locally and inspect the article in all of the +places readers will see it. A `published: false` post needs `--unpublished`; +`--drafts` only renders a `_drafts/` folder, which this repo does not use: + +```bash +bundle exec jekyll serve --unpublished --host=localhost --livereload +``` + +Then check: + +- `http://localhost:4000/` +- `http://localhost:4000/archive/` +- the individual post URL + +The home page uses `summary:` first, then `description:`, then the first real +paragraph. Keep `summary:` concise so the listing stays readable and does not +expose large code blocks. + ## SEO Improvements diff --git a/_config.yml b/_config.yml index bcbd779..d35e6b5 100644 --- a/_config.yml +++ b/_config.yml @@ -46,7 +46,37 @@ version: "2.1.0" github: [metadata] -exclude: ["Rakefile", "vendor", "claude.md", "CLAUDE.md", "warp.md", "WARP.md", "agent.md", "AGENT.md", "agents.md", "AGENTS.md"] +# Setting `exclude` replaces Jekyll's default list rather than adding to it, so +# the defaults are repeated here. Anything not excluded is copied to _site and +# served from solrevdev.com. `media/` stays: older posts link to images in it. +exclude: + # Jekyll defaults, restored + - .sass-cache + - .jekyll-cache + - gemfiles + - Gemfile + - Gemfile.lock + - node_modules + - vendor + # Repo documentation, not site content + - README.md + - readme.md + - LICENSE.md + - licence.md + - license.md + - claude.md + - CLAUDE.md + - warp.md + - WARP.md + - agent.md + - AGENT.md + - agents.md + - AGENTS.md + # Build and editor tooling + - Rakefile + - script + - frontmatter.json + - .github # Social Sharing facebook_app_id: "1213637668669023" diff --git a/claude.md b/claude.md deleted file mode 100644 index 5dfa204..0000000 --- a/claude.md +++ /dev/null @@ -1,52 +0,0 @@ -# Claude Development Notes - -## Blog Cover Images - -### Implementation -- Added `cover_image` front matter field to blog posts -- Updated `_layouts/post.html` to display cover images when present -- Added responsive CSS styles in `public/css/custom.scss` for proper display across devices - -### Image URL Behavior During Local Development - -**Key Finding**: When developing locally, images sometimes do not display properly due to path resolution issues. - -**Working Solutions**: -1. **Relative paths** (`./images/filename.svg`) - ✅ Works with file:// protocol -2. **File protocol** (`file:///full/path/to/image`) - ✅ Works for local testing -3. **Jekyll server** with localhost/127.0.0.1 - ✅ Works when Jekyll server is running - -**Non-working Solutions**: -1. **Absolute paths** (`/images/filename.svg`) - ❌ Fails with file:// protocol -2. **localhost URLs** without server - ❌ Connection refused when Jekyll isn't running -3. **127.0.0.1 URLs** without server - ❌ Connection refused when Jekyll isn't running - -### Development Workflow -For local development, either: -1. Use Jekyll server: `bundle exec jekyll serve --host 127.0.0.1 --port 4000` -2. Use relative paths in Jekyll templates with `{{ site.baseurl }}` prefix -3. Test with file:// protocol using relative paths for quick validation - -### CSS Implementation -- Responsive design with different max-heights for desktop (400px), tablet (250px), and mobile (200px) -- Hover effects with subtle scale transform -- Proper shadow and border-radius for visual appeal -- Mobile-specific margin adjustments for better display - -### Cover Image Guidelines -- **Supported formats**: SVG (preferred), PNG, JPG - all handled gracefully by CSS -- **Size handling**: CSS automatically scales images responsively: - - Desktop: max-height 400px - - Tablet: max-height 250px - - Mobile: max-height 200px -- **Recommended dimensions**: 800x400px aspect ratio for optimal display -- **File size**: Keep under 50KB for performance (SVG typically 2-5KB) -- **Alt text**: Automatically uses page title for accessibility -- **Storage**: Place images in `/images/` directory - -### Testing Results (Production Ready) -- ✅ Images scale gracefully across all device sizes -- ✅ Posts without cover images display normally -- ✅ Performance impact minimal (2.3KB SVG) -- ✅ All image formats (SVG, PNG, JPG) supported -- ✅ Responsive breakpoints working properly \ No newline at end of file