Moving Article Workflow

This document explains the full process for generating fictionalized moving articles sourced from Reddit threads. Follow this any time you want to produce new articles for the vibe-living/moving/ section.


Overview

Articles are sourced from real Reddit threads in r/moving, fictionalized into narrative-style guides written as Emilia Grey, and published to the site. The process takes about 10 minutes of your time per batch of 5.

run generate_articles.py
    -> fetches top threads from r/moving
    -> skips any already used (dedup log)
    -> writes article-briefs.txt
-> open Cursor chat
-> say "write the 5 articles from article-briefs.txt"
-> Cursor writes all 5 articles as .md files
-> you review and publish

Files

File Purpose
generate_articles.py Main script. Fetches Reddit threads and writes briefs.
used-threads.json Permanent dedup log. Every used thread ID lives here forever.
article-briefs.txt Generated each run. Contains raw Reddit content + writing instructions for Cursor.
ideas.txt Manual scratch pad. Optional. Not used by the script.

Step-by-Step: Generating 5 New Articles

Step 1: Run the script

Open the Cursor terminal (Ctrl+`) and run:

python "C:\Users\jssan\OneDrive\Documents\CityVibeCheck\vibe-living\moving\generate_articles.py"

The script will:

You will see output like:

[INFO] Loaded 7 previously used thread ID(s)
[INFO] Searching Reddit for moving threads...
[INFO] Found 34 unique qualifying threads.
[INFO] Auto-selected top 5:

  [1] Score  62.1 | First apartment move - totally overwhelmed
  [2] Score  58.3 | Hired movers ghosted me day of move
  ...

[DONE] Briefs written to: article-briefs.txt
Next step: In Cursor chat, say 'write the 5 articles from article-briefs.txt'

Step 2: Ask Cursor to write the articles

In Cursor chat, say:

write the 5 articles from article-briefs.txt

Cursor will read the briefs and write each article as a .md file in vibe-living/moving/, following the Emilia Grey style guide embedded in each brief.

Step 3: Review

Open each new .md file. Check:

Step 4: Add featured images

Each article has a featured_image and inline image placeholders. Source or generate images and save them to /vibe-living/images/moving/ using the slugs specified in the article.

Step 5: Publish

Move the finished .md file into your site's publishing pipeline as normal.


How Deduplication Works

Every time the script runs and selects threads, their Reddit IDs are written to used-threads.json:

{
  "used": [
    {
      "thread_id": "1l586d3",
      "article": "pending-1l586d3.md",
      "date": "2026-03-14",
      "url": "https://www.reddit.com/r/moving/comments/1l586d3/...",
      "title": "Tips and tricks for those who need it"
    }
  ]
}

The script checks this file before selecting any thread. A thread that appears here will never be selected again, even if it surfaces in search results. This prevents duplicate articles permanently.

When you finish writing an article, update the article field in the log entry to the actual filename (e.g., "article": "first-apartment-move-guide.md"). This is optional but keeps the log clean and useful as a content index.


Article Style Reference

All articles are written as Emilia Grey. The full style guide is embedded in generate_articles.py and gets included in every brief automatically.

Author Block

Use exactly this in every article's frontmatter:

author: "Emilia Grey"
author_bio: "Emilia Grey is a writer who helps people navigate the complexities of personal finance and relocation. With a practical approach and a knack for breaking down complex topics with story-telling, Emilia provides actionable advice for those looking to save money, invest wisely, and make informed decisions about their next move. In her free time, she's a fan fiction enthusiast, getting lost in the worlds of her favorite books and TV shows."
author_photo: "/vibe-living/images/authors/emilia-grey.webp"
author_title: "Personal Finance & Relocation"

Frontmatter Checklist

Every article must have all of these fields filled in:

layout: article.njk
title:          # Narrative title with a character name or situation — not SEO keyword stuffing
excerpt:        # One sentence that hooks on the story, not the advice
description:    # SEO-friendly 1-2 sentence summary of the practical value
keywords:       # Comma-separated, 6-10 terms
category: "moving"
author: "Emilia Grey"
author_bio:     # Full bio above
author_photo: "/vibe-living/images/authors/emilia-grey.webp"
author_title: "Personal Finance & Relocation"
featured_image: "/vibe-living/images/moving/[descriptive-slug].webp"
image_caption:  # Short, descriptive
date:           # YYYY-MM-DD — spread across a range when doing batch runs, do not use the same date for all articles
read_time: 5
tags:
  - moving
  - [2-4 additional specific tags]

Narrative Structure

  1. Opening hook (italicised paragraph) — fictional character mid-crisis, present tense feel, no more than 4-5 sentences
  2. H2: Context/Problem — stakes, what made this hard, emotional weight without melodrama
  3. H2: Discovery/Research — character investigates; Reddit comment insights woven in naturally as what the character found or was told
  4. H2: Solution or Method — practical breakdown with sub-sections if needed
  5. Callout box — real numbers, checklist, or decision framework
  6. H2: Complication or Non-Obvious Factor — something most people miss
  7. H2: Outcome — brief, grounded, not triumphant
  8. Closing paragraph — one broader lesson + CTA link

Callout Box Format

Always use markdown blockquote with a bold H3 title:

> ### Title Here
> - bullet one
> - bullet two
> - bullet three

Inline Images

Place 1-2 images inside the article body. Use descriptive alt text and slugs that match what will actually be saved to /vibe-living/images/moving/:

![descriptive alt text](/vibe-living/images/moving/descriptive-slug.webp)

CTA Links

Use one of these at the end of every article. Pick the one that fits the topic:

External Links

Every article must contain 2-3 authoritative external links placed inline within the text, opening in a new tab.

Format (plain Markdown does not support target="_blank" — use inline HTML):

<a href="https://www.fmcsa.dot.gov/protect-your-move" target="_blank" rel="noopener noreferrer">FMCSA's Protect Your Move</a>

Rules:

Common link targets by topic:

Article topic Good external link
Mover liability / released valuation fmcsa.dot.gov/protect-your-move
FMCSA delivery window regulations fmcsa.dot.gov
U-Haul U-Box specs / pricing uhaul.com/Storage/UBox
PODS container specs pods.com
U-Pack ReloCube upack.com
Tow ratings (vehicle-specific) Manufacturer's official spec page
Auto transport shipping uship.com
Pet travel safety avma.org
Discounted shipping rates pirateship.com
Rental apartment qualification / credit consumerfinance.gov

Writing Rules (Non-Negotiable)

Fact-Check Pass

Before saving any article, verify every specific claim:

Claim type How to verify
Product weights (trailers, containers) Check manufacturer/rental company site
Tow ratings Owner's manual or manufacturer spec page
Legal/regulatory claims (FMCSA, 49 CFR) Government source or legal reference
Cost ranges (moving, shipping, storage) Cross-check against 2-3 current sources
City-specific facts (population, climate) Census, city data sites
Insurance/liability rules FMCSA.dot.gov or equivalent

If a claim cannot be verified with confidence, either remove it, soften it to "typically" or "often," or attribute it to the character's experience rather than stating it as fact.

Date Spreading

When generating a batch of articles, spread dates naturally across a range rather than using the same publish date for all of them. A realistic spread looks like articles published 1-3 weeks apart. This applies to batch runs done in the same session. Future one-off runs can use the current date.


Running Options

Command What it does
python generate_articles.py Standard run: auto-select top 5, update log
python generate_articles.py --count 3 Generate 3 articles instead of 5
python generate_articles.py --keyword "moving truck rental" Search with a specific keyword
python generate_articles.py --dry-run Fetch and score threads but do NOT update used-threads.json

Expanding to Other Categories

When ready to set up the same pipeline for other vibe-living categories, duplicate generate_articles.py and used-threads.json into the relevant folder and change:

SUBREDDITS = ["moving"]

to the appropriate subreddit for that category, for example:

Category Subreddit
Money personalfinance
Relationships relationships
Wellness mentalhealth

Each category gets its own separate dedup log so there is no cross-contamination.


Troubleshooting

Script finds 0 threads: Reddit occasionally rate-limits anonymous requests. Wait 5 minutes and try again. If persistent, try --keyword with a more specific term.

"Missing dependency" error: Run pip install requests in the terminal.

Thread content looks thin: The script filters out threads with fewer than 80 words in the OP body. Some topics naturally produce thinner posts. Try --keyword to target richer topics.

used-threads.json got corrupted: The file is plain JSON. Open it, check that it is valid (you can paste it into jsonlint.com), and fix any syntax errors. The structure is always { "used": [ ... ] }.