Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 130 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# Story Bot - AI Coding Agent Instructions

## Project Overview

Story Bot is an **AI-powered blog platform** where stories are generated by GPT models based on user-submitted prompts. The entire content pipeline—from story generation to image creation—is automated via GitHub Actions.

**Tech Stack**: Eleventy (11ty) static site generator, Tailwind CSS + DaisyUI, OpenAI API (GPT + DALL-E)

## Architecture

### Three Core Components

1. **Static Site (Eleventy)**: Renders blog posts from Markdown files in `src/blog/` to static HTML in `dist/`
2. **Story Generation Scripts** (`scripts/`): Node.js scripts that call OpenAI APIs to generate stories and images
3. **GitHub Actions Automation**: Workflows that orchestrate the prompt-to-publication pipeline

### Content Flow

```
GitHub Issue (prompt) → Parse Issue → Call GPT API → Generate Story + Image
→ Optimize Image → Write Markdown → Commit → Create PR → Deploy Static Site
```

**Key Files**:
- `scripts/story-generator.js`: Writes markdown files with frontmatter (title, image, temperature)
- `scripts/action.js`: Entry point for GitHub Actions, reads `story.json` and generates blog post
- `.github/workflows/prompt-deployment.yml`: Orchestrates the entire pipeline from issue to deployment

## Development Workflows

### Local Development
```bash
npm install # Node 18+ required
npm start # Serve with live reload (Eleventy watch mode)
npm run build # Production build to dist/
```

### Story Generation (Manual)
```bash
npm run write # Reads prompt.txt, generates story via OpenAI
npm run action # Processes story.json (used by GH Actions)
```

## Critical Conventions

### Blog Post Structure
All posts in `src/blog/` follow this pattern:
- **Filename**: `YYYY-MM-DD-kebab-case-title.md` (date prefix is critical for sorting)
- **Frontmatter**: YAML with `layout`, `title`, `date`, `categories`, `tags`, `generation.temperature`, `image`, `generation.helper` (optional)
- **Images**: Generated as WebP in `src/img/blog/` with matching filename

**Example**: `2023-03-19-the-rise-of-aigenerated-content-exploring-story-bot.md` with image `2023-03-19-the-rise-of-aigenerated-content-exploring-story-bot.webp`

### Duplicate Title Prevention
**Critical**: Blog post titles MUST be unique. When creating/editing posts:
1. Check for duplicate titles across all `src/blog/*.md` files
2. Filenames can differ while titles match—this causes overwrites or confusion
3. If fixing duplicates, ensure the image filename matches the post filename

### Eleventy Configuration (`.eleventy.js`)

**Custom Filters**:
- `postcss`: Processes Tailwind CSS via PostCSS pipeline (inline in templates)
- `excerpt`: Truncates content to ~200 chars for blog previews
- `w3DateFilter`: Formats dates for W3C standards (RSS feed)
- `isOneDayOld`: Checks if post was published today (for "new" badges)

**Collections**: `blog` collection returns all posts in `src/blog/*.md` in reverse chronological order

**Template Engine**: Nunjucks (`.njk`) for layouts and includes, but Markdown posts use `markdownTemplateEngine: 'njk'`

### Styling Architecture

**Tailwind + DaisyUI Integration**:
- Config: `tailwind.config.js` (content: `src/**/*.{njk,md,html}`)
- Processing: Custom `postcss` filter in `.eleventy.js` compiles Tailwind inline
- Usage: Apply utility classes in Nunjucks templates and Markdown (via `@tailwindcss/typography`)
- DaisyUI: Component library enabled as Tailwind plugin—see `.github/instructions/daisyui.instructions.md` for component docs

**Critical**: The `postcss` filter is async and registered as `addNunjucksAsyncFilter` in `.eleventy.js`

### GitHub Actions Integration

**Issue-Driven Story Creation** (`prompt-deployment.yml`):
1. Triggered when issue labeled with `story`
2. Parses issue body using `peter-murray/issue-forms-body-parser`
3. Runs `npm run action` to generate story from `story.json`
4. Commits to `main` with message format: `✍️ {story.title}` and closes the original issue
5. Triggers separate deployment workflow
6. Auto-closes issue with comment linking to published post

**Environment Variables for GH Actions**:
- `USER_NAME` and `USER_AVATAR`: Stored in `generation.helper` frontmatter to credit prompt authors

## Common Pitfalls

1. **Google Fonts Plugin**: The `eleventy-google-fonts` plugin can fail in sandboxed environments. Use standard `<link>` tags in `src/_includes/partials/head.html` instead
2. **Image Optimization**: Always use `@11ty/eleventy-img` to compress images—raw DALL-E PNGs bloat the repo
3. **Markdown Frontmatter**: YAML must be valid; use `json2yaml` in `story-generator.js` to ensure correctness
4. **Build Output**: `dist/` is gitignored—never commit build artifacts
5. **Node Version**: Project requires Node 18+ (uses ES modules with `type: "module"` in package.json during GH Actions)

## Testing Changes

Before committing layout/style changes:
1. Run `npm start` and verify changes in browser
2. Check multiple blog posts (not just homepage)
3. Verify RSS feed still works: `/feed.xml`
4. Run `npm run build` to catch any production-only issues

## File Organization

```
src/
├── _includes/
│ ├── layouts/ # Base templates (base.html, blog.html)
│ ├── partials/ # Reusable components (head.html, footer.html)
│ └── styles/ # Tailwind CSS source files
├── blog/ # Markdown blog posts (date-prefixed)
├── img/blog/ # Optimized WebP images (generated)
├── filters/ # Eleventy custom filters
└── *.md # Top-level pages (index, about, create)
```

## Additional Context

- **RSS Feed**: Generated via `@11ty/eleventy-plugin-rss` at `/feed.xml`
- **Syntax Highlighting**: Uses Prism.js via `@11ty/eleventy-plugin-syntaxhighlight`
- **Custom Domain**: `CNAME` file contains `storybot.dev`
- **Analytics**: Umami tracking injected in `head.html` partial
1 change: 1 addition & 0 deletions .github/instructions/daisyui.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
curl -L https://daisyui.com/llms.txt --create-dirs -o .github/instructions/daisyui.instructions.md
Copy link

Copilot AI Oct 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file contains a curl command instead of the actual DaisyUI documentation. The command should be executed to populate this file with the fetched content, or this should be moved to a setup script or README with instructions on how to fetch the documentation.

Suggested change
curl -L https://daisyui.com/llms.txt --create-dirs -o .github/instructions/daisyui.instructions.md
# DaisyUI Documentation for LLMs
DaisyUI is a Tailwind CSS plugin that adds component classes to your project. It makes it easy to build beautiful interfaces quickly.
## Installation
```bash
npm install daisyui

Add daisyui to your Tailwind CSS plugins in tailwind.config.js:

module.exports = {
  plugins: [require('daisyui')],
}

Usage

Use DaisyUI component classes in your HTML:

<button class="btn btn-primary">Button</button>

Customization

DaisyUI can be customized via the daisyui key in your Tailwind config:

module.exports = {
  daisyui: {
    themes: ["light", "dark", "cupcake"],
  },
}

Documentation

For full documentation, visit https://daisyui.com/docs/

Copilot uses AI. Check for mistakes.