diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..5ae62fc --- /dev/null +++ b/.github/copilot-instructions.md @@ -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 `` 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 diff --git a/.github/instructions/daisyui.instructions.md b/.github/instructions/daisyui.instructions.md new file mode 100644 index 0000000..0df1c27 --- /dev/null +++ b/.github/instructions/daisyui.instructions.md @@ -0,0 +1 @@ +curl -L https://daisyui.com/llms.txt --create-dirs -o .github/instructions/daisyui.instructions.md