Blog Content Authoring (en/tr)
This repo generates content via static export. List pages are driven by JSON index files, while the post detail page is driven by the Markdown file. Therefore, when adding a new post you must update Markdown + post index JSON + thumbnail + (if needed) topics index JSON together.
File/Folder Map
- •Posts (Markdown):
content/posts/<locale>/<slug>.md(<locale>:enortr) - •Post list index:
public/data/posts.<locale>.json - •Topic list:
public/data/topics.<locale>.json - •Thumbnails:
public/images/*.webp(referenced as/images/<file>.webpin Markdown/JSON)
Non-Negotiable Rules (Summary)
- •Slug/ID: kebab-case (
my-new-post). Use the same slug for bothenandtr. - •Post index JSON is the source of truth: list pages / RSS / sitemap use
public/data/posts.<locale>.json. Markdown is read for the detail page content + frontmatter metadata. - •Sorting: post index JSON should be kept in date DESC order (newest first).
- •Images: keep post images under
/images/and preferwebpfor consistency/performance. - •Thumbnail:
1200x630(OG size),webp, underpublic/images/(recommended name:<slug>-thumbnail.webp). - •Topic consistency: topic
ids must exist in topic index JSON in both locales;nameis translated per locale;colormust be one of the allowed values. - •Icon standards: tab icons use the
[icon=...]format and must be from the allowed set; step headings must use the standardized emoji + label format (see below).
2024+ Editorial Rule Set (Mandatory)
Use this rule set to keep every article at a modern, professional developer-blog quality bar (Vercel/Cloudflare/Stripe/GitHub Engineering style patterns).
A) Structural contract (all posts)
- •
titleis specific and searchable;summaryclearly states outcome and stays concise. - •After frontmatter, include a short opening paragraph (2-4 sentences) that frames problem + value.
- •First main section is always
## 🌟 ...and explains either:- •what the reader will learn, or
- •why this approach matters.
- •
## 📋 Prerequisites/## 📋 Gereksinimlermust exist and be explicit. - •Implementation is step-based (
## 🛠️/🧪/▶️ Step NorAdım N) with sequential numbering. - •Each
##section must contain real content (no empty headings). - •End with a single
## 🏁 Conclusion/## 🏁 Sonuç:- •one concise synthesis paragraph,
- •one practical next step for production hardening.
B) Readability & prose quality
- •No visual spacer hacks in markdown (remove
<span style="display:block; height:1rem;"></span>). - •No language-mixing in headings (
Adım ...: Add Dependenciesis invalid). - •Keep heading hierarchy clean: main sections
##, subsections###, avoid deeper nesting. - •Keep prose direct and concrete; prefer short paragraphs and scannable bullets.
- •Avoid duplicate/redundant wording (e.g., repeated “Spring Boot” phrases in conclusions).
C) Professional editing checks
- •Headings must reflect the section content; remove vague or dead headings.
- •Keep terminology consistent across the post (same concept, same naming).
- •Validation/testing instructions should include expected behavior (not just commands).
- •Conclusion should not be generic filler; it must summarize the delivered architecture/pattern.
Batch standardization flow
# 1) Headings + typo/language cleanup + spacer cleanup node .codex/skills/blog-content-authoring/scripts/standardize-posts.mjs --dry-run node .codex/skills/blog-content-authoring/scripts/standardize-posts.mjs # 2) Professional, non-generic conclusions (rewrite mode) node .codex/skills/blog-content-authoring/scripts/standardize-conclusions.mjs --rewrite
Image Standards
Iram City Art Direction (Thumbnails & Inline Images)
Goal: make all post visuals (thumbnails + optional inline images) feel like they belong to the same world:
- •Iram of the Pillars (Irem Şehri), ancient Arab myth-inspired lost city
- •endless columns, monumental palaces, sacred timeless atmosphere
- •terraced nature, clear water channels, reflective pools
- •golden-hour / “golden light” beams, volumetric light, cinematic haze
- •no people, no modern elements, no readable text/logos/watermarks
- •style: fantastical realism, epic cinematic, wide angle, high detail
Generate base Iram prompts for all posts
The helper script outputs one JSONL line per post with a single, topic-independent Iram prompt.
node .codex/skills/blog-content-authoring/scripts/generate-thumbnail-prompts.mjs > /tmp/irem-prompts.jsonl
Prompt template (copy/paste)
Use this as-is in your image generator (SDXL / Midjourney / etc.):
Base prompt
- •“Iram of the Pillars (Irem Şehri), ancient Arab myth-inspired lost city, majestic and mysterious sacred place, timeless, uninhabited (no people), endless columns and towering palaces, monumental architecture, terraced gardens integrated with nature, clear water channels, reflective pools, golden hour light beams, volumetric light, atmospheric haze, epic cinematic mood, fantastical realism, ultra-detailed, wide-angle, HDR”
Negative prompt
- •“people, faces, crowds, text, logos, watermark, lowres, blurry, noise, oversaturated, cartoon, anime”
Batch prompt generation for all existing posts
Generate one JSONL line per post (includes EN/TR prompts + negative prompt + suggested thumbnail path):
node .codex/skills/blog-content-authoring/scripts/generate-thumbnail-prompts.mjs > /tmp/irem-prompts.jsonl
Workflow suggestion:
- •Pick a post from
/tmp/irem-prompts.jsonl - •Generate an image at 1200x630 (or generate larger, then crop)
- •Convert/crop to blog thumbnail:
node .codex/skills/blog-content-authoring/scripts/make-thumbnail.mjs --in /path/to/generated.png --out public/images/<slug>-thumbnail.webp
1) Post thumbnail (required)
- •Purpose: post list card + RSS/sitemap image + OG-like share image
- •Format:
webp - •Dimensions:
1200x630 - •Location:
public/images/ - •Path in Markdown/post index JSON:
/images/<slug>-thumbnail.webp
Thumbnail quality checklist (must pass)
- •No readable text (no UI text, no captions, no logos, no watermarks)
- •Composition centered, with strong leading lines (columns/arches/perspective)
- •1200x630 output (crop if needed; avoid distorted aspect ratios)
- •
webponly - •Target file size: < 350KB (optimize/crop if larger)
Generate:
node .codex/skills/blog-content-authoring/scripts/make-thumbnail.mjs \ --in /path/to/source.png \ --out public/images/<slug>-thumbnail.webp
2) Inline post images (optional)
If you add images inside the post body (Markdown/HTML):
- •Format: prefer
webp - •Location:
public/images/posts/<slug>/ - •Reference path:
/images/posts/<slug>/<name>.webp
Generate (keeps aspect ratio, resizes to a max width):
node .codex/skills/blog-content-authoring/scripts/make-post-image.mjs \ --in /path/to/source.png \ --out public/images/posts/<slug>/<name>.webp \ --maxWidth 1200
Recommended markup (for better layout stability):
<figure>
<img
src="/images/posts/<slug>/<name>.webp"
alt="Describe the image"
width="1200"
height="675"
loading="lazy"
decoding="async"
/>
<figcaption>Optional caption</figcaption>
</figure>
Tip: use the generated file’s real width/height (the script prints it) to avoid layout shift.
Icon & Heading Standards
Tab icons (:::tabs + @tab)
Format:
:::tabs @tab Java [icon=java] ... :::
Allowed tab icons:
- •Languages:
java,kotlin,go,javascript,typescript - •Build tools:
maven,gradle
Heading emojis (recommended)
Keep headings consistent across posts:
- •Overview / Why
- •EN:
## 🌟 ... - •TR:
## 🌟 ...
- •EN:
- •Prerequisites
- •EN:
## 📋 Prerequisites - •TR:
## 📋 Gereksinimler
- •EN:
- •Steps
- •Build/implementation step:
- •EN:
## 🛠️ Step N: ... - •TR:
## 🛠️ Adım N: ...
- •EN:
- •Testing/verification step:
## 🧪 Step N: .../## 🧪 Adım N: ... - •Run/start step:
## ▶️ Step N: .../## ▶️ Adım N: ...
- •Build/implementation step:
Note: Avoid “random” emojis in headings. Prefer the small set above so posts feel consistent.
Heading hierarchy & text style (repo standard)
Apply these rules for all EN/TR post markdown files:
- •TOC is main-section oriented: keep main sections as
##only. - •Use
###for sub-sections (examples, controller snippets, notes). - •Every
###heading must be followed by a short editorial lead-in (1-2 sentences) that explains intent/value before code/list blocks. - •Do not use
####and deeper levels; collapse them to###. - •If a section title is plain (non-step/non-standard emoji), prefer making it a sub-section (
###) rather than a new##. - •Keep body/list text plain; avoid bold emphasis markers (
**text**,__text__) in prose. - •Keep technical tokens in inline code (
`@ConfigurationProperties`,`application.yml`), not bold.
Goal: visual rhythm and hierarchy stay consistent across all posts without noisy emphasis.
Conclusion Standard (Required)
All posts should end with a short, consistent conclusion section:
- •EN:
## 🏁 Conclusion - •TR:
## 🏁 Sonuç
Template (EN):
- •“This setup delivers a robust, production-ready … by combining …”
Template (TR):
- •“Bu kurulum, … için sağlam ve üretim‑hazır bir yaklaşım sunar; …”
You can batch-apply this standard to all posts with:
node .codex/skills/blog-content-authoring/scripts/standardize-conclusions.mjs
Add a New Post (Step-by-Step)
Random Post Generation (Constrained Topics)
If you want to generate a random new post idea that still fits this blog’s content constraints, use the helper script below.
Constraints (topic pool):
- •Java (
java) - •Kotlin (
kotlin) - •Spring Boot (
spring-boot) - •Kubernetes (
kubernetes) - •Go / Golang (
go)
Generate a random post idea (deterministic with a seed):
node .codex/skills/blog-content-authoring/scripts/suggest-random-post.mjs --seed=2026-02-04
It prints:
- •suggested
slug+date - •EN/TR
title+summary - •topic entries (id/name/color) for both locales
- •a minimal outline that already follows the standard heading emojis and the single Conclusion rule
After picking an idea:
- •Create
content/posts/en/<slug>.mdandcontent/posts/tr/<slug>.md - •Add the post to
public/data/posts.en.jsonandpublic/data/posts.tr.json - •Create
public/images/<slug>-thumbnail.webp(1200x630) using the Iram art direction - •Run the checker:
node .codex/skills/blog-content-authoring/scripts/check-content.mjs
Documentation Source (Context7 MCP Required)
When writing technical posts (Java/Kotlin/Spring Boot/Kubernetes/Go), always pull current API guidance from Context7 before finalizing code/config snippets.
Workflow:
- •Resolve the library id:
- •
mcp__context7__resolve-library-id(example inputs: “spring boot”, “kubernetes”, “go”)
- •
- •Query for the exact topic you’re writing about:
- •
mcp__context7__query-docs(ask for the specific feature, version caveats, and example snippets)
- •
- •Adapt examples to this repo’s constraints:
- •Blog markdown conventions (headings/steps/conclusion)
- •Keep code snippets minimal and production-safe
1) Choose the slug/ID
- •Use only lowercase letters + digits + hyphens:
spring-boot-ai - •The file name and the post index
idmust match.
2) Create the thumbnail (WebP, 1200x630)
This skill includes a helper script:
node .codex/skills/blog-content-authoring/scripts/make-thumbnail.mjs \ --in /path/to/source.png \ --out public/images/<slug>-thumbnail.webp
- •Put the output exactly under
public/images/.... - •Reference it in Markdown/post index JSON as:
"/images/<slug>-thumbnail.webp".
3) Pick topics / add a new topic if needed
- •To see existing topics:
- •
public/data/topics.en.json - •
public/data/topics.tr.json
- •
- •If you need a new topic, follow “Add a New Topic” below, then use it in the post.
Add a New Topic (Step-by-Step)
When you introduce a new topic (e.g. redis, kafka), it must be added to both locale files and then used consistently.
- •Pick a stable topic
id(kebab-case), e.g.spring-ai - •Add it to
public/data/topics.en.json:- •
id: the same id - •
name: English display name (e.g.Spring AI) - •
color: pick from the allowed set (see checker’sALLOWED_TOPIC_COLORS)
- •
- •Add it to
public/data/topics.tr.json:- •
id: the same id - •
name: Turkish display name (e.g.Spring AIor a localized equivalent) - •
color: must match the EN color
- •
- •Use the topic in both
public/data/posts.en.jsonandpublic/data/posts.tr.jsonentries (topic object must includeid/name/color) - •Re-run the checker:
- •
node .codex/skills/blog-content-authoring/scripts/check-content.mjs
- •
4) Create Markdown files (en + tr)
Create two files:
- •
content/posts/en/<slug>.md - •
content/posts/tr/<slug>.md
Frontmatter template (example):
---
title: '...'
date: 'YYYY-MM-DD'
summary: '...'
thumbnail: '/images/<slug>-thumbnail.webp'
readingTime: '3 min read' # Note: computed in the app; optional/ignored as a source of truth
topics:
- id: 'java'
name: 'Java'
color: 'red'
---
Notes:
- •Keep
summaryshort and scannable:- •Recommended: 140–180 characters
- •Hard limit: ≤ 200 characters
- •Keep
titleclean and SEO-friendly:- •Avoid parentheses in titles (e.g. do not use “(Type-Safe Config + Profiles)”)
- •
dateformat:YYYY-MM-DD(e.g.2026-02-03) - •
topicsentries must be objects (id/name/color). Theidmust exist in topic index JSON. - •
readingTimeis computed automatically; you may keep it for consistency, but it is not a reliable source of truth. - •Content supports GitHub Flavored Markdown (tables/lists/code blocks).
- •If you want tabbed blocks:
:::tabs @tab Maven [icon=maven] ```xml ... ``` @tab Gradle [icon=gradle] ```kts ... ``` :::
Constraint:
- •The
@tabtitle is parsed via a regex; avoid emojis/special characters. Use letters/numbers/spaces.
Link rule:
- •Write internal links as
/posts/<id>or/topics/<id>; the renderer will add the locale prefix automatically.
5) Update post index JSON (en + tr)
Add the new entry (same id) to both files:
- •
public/data/posts.en.json - •
public/data/posts.tr.json
Entry template:
{
"id": "<slug>",
"title": "...",
"date": "YYYY-MM-DD",
"summary": "...",
"thumbnail": "/images/<slug>-thumbnail.webp",
"topics": [{ "id": "java", "name": "Java", "color": "red" }]
}
Notes:
- •
title/summary/topic.namemust be translated per locale (envstr). - •
topics[].idandtopics[].colormust remain the same across locales. - •Sorting is done at runtime by date; still, keeping JSON roughly newest to oldest is practical.
6) Quick validation
This skill includes a content check script:
node .codex/skills/blog-content-authoring/scripts/check-content.mjs
To see a quick inventory of images referenced by posts:
node .codex/skills/blog-content-authoring/scripts/report-images.mjs
To standardize existing posts (headings/steps/prerequisites), run:
node .codex/skills/blog-content-authoring/scripts/standardize-posts.mjs --dry-run node .codex/skills/blog-content-authoring/scripts/standardize-posts.mjs
To sync readingTime from Markdown into post index JSON, run:
pnpm run sync:reading-time
Then run the repo quality gates:
pnpm test pnpm run lint pnpm build
Add a New Topic (Step-by-Step)
- •Choose a new topic
id(kebab-case):spring-ai - •Add it to both locale files:
- •
public/data/topics.en.json - •
public/data/topics.tr.json
- •
- •Template:
{ "id": "spring-ai", "name": "Spring AI", "color": "orange" }
- •
colormust be one of:
primary, secondary, success, info, warning, danger, light, dark, red, green, blue, orange, yellow, purple, gray, brown, pink, cyan
- •Then add the same
id/name/colorto:- •the Markdown frontmatter
topicslist - •the post index JSON
topicslist for the relevant posts.
- •the Markdown frontmatter
Common Mistakes
- •Adding only the Markdown file but not updating post index JSON (the post won’t appear in list/RSS/sitemap).
- •Mismatched
idvs filename (post indexid!=<slug>.md). - •Putting the thumbnail outside
public/images/or referencing it with a path not starting with/images/.... - •Adding a topic in only one locale (topic pages/build become inconsistent).
- •Using emojis/special characters in
@tabtitles (tab parsing may break).