autoblogger 0.1.16 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,603 +3,172 @@
3
3
  [![npm version](https://img.shields.io/npm/v/autoblogger.svg)](https://www.npmjs.com/package/autoblogger)
4
4
  [![license](https://img.shields.io/npm/l/autoblogger.svg)](https://github.com/hrosenblume/autoblogger/blob/main/LICENSE)
5
5
 
6
- A complete content management system that embeds into your Next.js app. Write blog posts with AI assistance, manage revisions, handle comments, and auto-generate drafts from RSS feeds—all from a dashboard that lives inside your existing application.
6
+ An AI-powered CMS that embeds into your Next.js app. Write blog posts with AI assistance, manage revisions, handle comments, and auto-generate drafts from RSS feeds.
7
7
 
8
8
  ```bash
9
9
  npm install autoblogger
10
10
  ```
11
11
 
12
- ---
13
-
14
- ## What is Autoblogger?
15
-
16
- Autoblogger is an **embeddable CMS package**. Instead of running a separate blog platform like WordPress or Ghost, you install Autoblogger as an npm package and mount it inside your Next.js app. It becomes part of your application—using your database, your auth system, and your hosting.
17
-
18
- **This is not a standalone application.** It's a library that provides:
19
-
20
- 1. **A React dashboard** — A full writer/admin interface you mount at a route like `/writer`
21
- 2. **API handlers** — RESTful endpoints you mount at a route like `/api/cms`
22
- 3. **Data utilities** — Functions to query posts, render markdown, generate SEO metadata
23
-
24
- You keep full control. Autoblogger uses your Prisma client, respects your auth, and stores everything in your database.
25
-
26
- ---
27
-
28
- ## Who is this for?
29
-
30
- - **Developers building blogs** who want a writing dashboard without building one from scratch
31
- - **Teams** who need collaborative editing with comments and revision history
32
- - **AI-assisted writers** who want to generate drafts with Claude or GPT
33
- - **Content aggregators** who want to auto-draft posts from RSS feeds
34
-
35
- ---
36
-
37
- ## Features
38
-
39
- | Feature | Description |
40
- |---------|-------------|
41
- | **AI Writing** | Generate essays with Claude or GPT. Stream responses in real-time. Chat to refine your content. |
42
- | **WYSIWYG Editor** | Tiptap-based editor with formatting toolbar. Syncs to markdown for storage. |
43
- | **Revision History** | Every save creates a revision. Browse and restore any previous version. |
44
- | **Inline Comments** | Highlight text and leave comments. Reply in threads. Resolve when done. |
45
- | **RSS Auto-Draft** | Subscribe to RSS feeds. Filter articles by keywords. Auto-generate draft posts from news. |
46
- | **Tag Management** | Organize posts with tags. Bulk edit from the settings panel. |
47
- | **User Roles** | Admin, writer, and drafter roles with different permissions. |
48
- | **SEO Fields** | Custom title, description, keywords, and OG image per post. |
49
- | **Preview Links** | Generate expiring preview URLs for unpublished drafts. |
50
-
51
- ---
52
-
53
- ## Requirements
54
-
55
- Before installing, make sure you have:
56
-
57
- - **Next.js 14 or 15** (App Router)
58
- - **React 18 or 19**
59
- - **Prisma 5 or 6** with a configured database
60
- - **Node.js 20+**
61
-
62
- You'll also need API keys if you want AI features:
63
-
64
- - **Anthropic API key** for Claude models
65
- - **OpenAI API key** for GPT models
66
-
67
- ---
68
-
69
- ## Installation
70
-
71
- ### Quick Start (CLI)
72
-
73
- The fastest way to set up Autoblogger is with the CLI:
12
+ ## Quick Start
74
13
 
75
14
  ```bash
76
15
  npx autoblogger init
77
16
  ```
78
17
 
79
- This command will:
80
-
81
- 1. Detect your Next.js project and Prisma setup
82
- 2. Merge the required models into your Prisma schema
83
- 3. Create boilerplate files (`lib/cms.ts`, API route, dashboard page)
84
- 4. Patch your Tailwind config to include Autoblogger's components
85
- 5. Run the database migration
86
- 6. Optionally import existing markdown content
87
-
88
- **CLI Options:**
89
-
90
- ```bash
91
- npx autoblogger init --yes # Skip prompts, use defaults
92
- npx autoblogger init --dry-run # Preview changes without writing files
93
- npx autoblogger init --skip-migrate # Skip database migration
94
- npx autoblogger init --import=./posts # Import content after setup
95
- ```
96
-
97
- **Import Existing Content:**
98
-
99
- If you have markdown or MDX files, import them into the database:
100
-
101
- ```bash
102
- npx autoblogger import ./content/posts
103
- npx autoblogger import ./posts --status=published # Import as published
104
- npx autoblogger import ./posts --tag=imported # Add a tag to all
105
- ```
106
-
107
- ### Manual Installation
108
-
109
- If you prefer to set things up manually:
110
-
111
- #### Step 1: Install the package
112
-
113
- ```bash
114
- npm install autoblogger
115
- ```
116
-
117
- This installs Autoblogger and its dependencies (Tiptap editor, AI SDKs, markdown utilities).
118
-
119
- #### Step 2: Add the database models
120
-
121
- Autoblogger needs several tables in your database. Copy the models from the package's schema file into your own Prisma schema.
122
-
123
- **Option A: Copy the file and merge manually**
124
-
125
- ```bash
126
- # View the schema
127
- cat node_modules/autoblogger/prisma/schema.prisma
128
- ```
129
-
130
- Then copy the models (Post, Revision, Comment, User, Tag, etc.) into your `prisma/schema.prisma`.
131
-
132
- **Option B: If starting fresh, use it directly**
133
-
134
- ```bash
135
- cp node_modules/autoblogger/prisma/schema.prisma ./prisma/schema.prisma
136
- ```
137
-
138
- The required models are:
139
-
140
- | Model | Purpose |
141
- |-------|---------|
142
- | `Post` | Blog posts with title, markdown content, status, SEO fields |
143
- | `Revision` | Version history for posts |
144
- | `Comment` | Inline editor comments with threading |
145
- | `User` | CMS users with roles (admin, writer, drafter) |
146
- | `Tag` | Tags for organizing posts |
147
- | `PostTag` | Many-to-many relation between posts and tags |
148
- | `AISettings` | AI model preferences and prompt templates |
149
- | `IntegrationSettings` | Feature flags like auto-draft enabled |
150
- | `TopicSubscription` | RSS feed subscriptions for auto-drafting |
151
- | `NewsItem` | Individual RSS items fetched from subscriptions |
18
+ The CLI automatically:
19
+ - Detects your Next.js and Prisma setup
20
+ - Adds required database models to your schema
21
+ - Creates config, API route, and dashboard page
22
+ - Patches Tailwind to include Autoblogger styles
23
+ - Runs the database migration
152
24
 
153
- #### Step 3: Run the migration
25
+ Visit `/writer` to start writing.
154
26
 
155
- After adding the models to your schema:
27
+ ## Features
156
28
 
157
- ```bash
158
- npx prisma migrate dev --name add-autoblogger
159
- ```
29
+ - **AI Writing** — Generate essays with Claude or GPT. Stream responses in real-time.
30
+ - **Chat Modes** Ask questions, let AI edit directly (Agent mode), or generate outlines (Plan mode).
31
+ - **WYSIWYG Editor** — Tiptap-based editor with formatting toolbar. Syncs to markdown.
32
+ - **Revision History** — Every save creates a revision. Browse and restore any version.
33
+ - **Inline Comments** — Highlight text and leave threaded comments.
34
+ - **RSS Auto-Draft** — Subscribe to feeds, filter by keywords, auto-generate drafts.
35
+ - **User Roles** — Admin, writer, and drafter with different permissions.
36
+ - **SEO Fields** — Custom title, description, keywords, and OG image per post.
160
37
 
161
- This creates the tables in your database.
38
+ ## Requirements
162
39
 
163
- #### Step 4: Generate the Prisma client
40
+ - Next.js 14 or 15 (App Router)
41
+ - Prisma 5 or 6
42
+ - Node.js 20+
164
43
 
165
- ```bash
166
- npx prisma generate
167
- ```
168
-
169
- ---
44
+ For AI features, you'll need API keys from [Anthropic](https://console.anthropic.com/) and/or [OpenAI](https://platform.openai.com/).
170
45
 
171
46
  ## Configuration
172
47
 
173
- Create a configuration file that sets up Autoblogger with your app's Prisma client and auth:
48
+ The CLI creates `lib/cms.ts` for you. Customize it as needed:
174
49
 
175
50
  ```typescript
176
51
  // lib/cms.ts
177
52
  import { createAutoblogger } from 'autoblogger'
178
- import { prisma } from '@/lib/db' // Your Prisma client
179
- import { auth } from '@/lib/auth' // Your auth function (e.g., NextAuth)
53
+ import { prisma } from '@/lib/db'
54
+ import { auth } from '@/lib/auth'
180
55
 
181
56
  export const cms = createAutoblogger({
182
- // Required: Your Prisma client instance
183
57
  prisma,
184
-
185
- // Required: Authentication configuration
186
58
  auth: {
187
- // Function that returns the current session/user
188
59
  getSession: () => auth(),
189
-
190
- // Check if user is an admin (can access settings, manage users)
191
60
  isAdmin: (session) => session?.user?.role === 'admin',
192
-
193
- // Check if user can publish posts (admins and writers can, drafters can't)
194
61
  canPublish: (session) => ['admin', 'writer'].includes(session?.user?.role ?? ''),
195
62
  },
196
-
197
- // Optional: AI configuration
198
63
  ai: {
199
64
  anthropicKey: process.env.ANTHROPIC_API_KEY,
200
65
  openaiKey: process.env.OPENAI_API_KEY,
201
66
  },
202
-
203
- // Optional: File upload handler
204
- storage: {
205
- upload: async (file: File) => {
206
- // Implement your upload logic here (S3, Cloudflare R2, Vercel Blob, etc.)
207
- // Return an object with the public URL
208
- const url = await uploadToYourStorage(file)
209
- return { url }
210
- }
211
- },
212
67
  })
213
68
  ```
214
69
 
215
- ### Environment Variables
216
-
217
- Add these to your `.env.local`:
218
-
219
- ```bash
220
- # Database (you probably already have this)
221
- DATABASE_URL="postgresql://..."
222
-
223
- # AI API keys (optional, only needed for AI features)
224
- ANTHROPIC_API_KEY="sk-ant-..."
225
- OPENAI_API_KEY="sk-..."
226
- ```
227
-
228
- ---
229
-
230
- ## Mounting the API
231
-
232
- Autoblogger needs API routes to handle requests from the dashboard. Create a catch-all route:
233
-
234
- ```typescript
235
- // app/api/cms/[...path]/route.ts
236
- import { cms } from '@/lib/cms'
237
- import { NextRequest } from 'next/server'
238
-
239
- async function handler(
240
- req: NextRequest,
241
- { params }: { params: Promise<{ path: string[] }> }
242
- ) {
243
- const { path } = await params
244
- return cms.handleRequest(req, path.join('/'))
245
- }
246
-
247
- export { handler as GET, handler as POST, handler as PATCH, handler as DELETE }
248
- ```
249
-
250
- This single file handles all CMS API routes:
251
-
252
- | Route | Purpose |
253
- |-------|---------|
254
- | `GET /api/cms/posts` | List all posts |
255
- | `POST /api/cms/posts` | Create a new post |
256
- | `PATCH /api/cms/posts/:id` | Update a post |
257
- | `DELETE /api/cms/posts/:id` | Delete a post |
258
- | `GET /api/cms/revisions` | List revisions |
259
- | `POST /api/cms/revisions/:id/restore` | Restore a revision |
260
- | `GET /api/cms/comments` | List comments |
261
- | `POST /api/cms/ai/generate` | Generate essay with AI |
262
- | `POST /api/cms/ai/chat` | Chat with AI (streaming) |
263
- | ... | And more |
264
-
265
- ---
266
-
267
- ## Mounting the Dashboard
70
+ ## Displaying Posts
268
71
 
269
- The dashboard is a React component that renders the full CMS interface. Mount it at a route in your app:
270
-
271
- ```typescript
272
- // app/writer/[[...path]]/page.tsx
273
- import { AutobloggerDashboard } from 'autoblogger/ui'
274
- import { auth } from '@/lib/auth'
275
- import { redirect } from 'next/navigation'
276
-
277
- export default async function WriterPage({
278
- params
279
- }: {
280
- params: Promise<{ path?: string[] }>
281
- }) {
282
- // Protect this route - only authenticated users
283
- const session = await auth()
284
- if (!session) {
285
- redirect('/login')
286
- }
287
-
288
- const { path } = await params
289
-
290
- return (
291
- <AutobloggerDashboard
292
- apiBasePath="/api/cms"
293
- session={session}
294
- path={path?.join('/') || ''}
295
- />
296
- )
297
- }
298
- ```
299
-
300
- The `[[...path]]` syntax is a catch-all route that captures the dashboard's internal navigation:
301
-
302
- | URL | Dashboard Page |
303
- |-----|----------------|
304
- | `/writer` | Post list (drafts, published, suggested) |
305
- | `/writer/editor/my-post-slug` | Edit a specific post |
306
- | `/writer/settings` | Settings overview |
307
- | `/writer/settings/ai` | AI model and prompt configuration |
308
- | `/writer/settings/users` | User management |
309
- | `/writer/settings/tags` | Tag management |
310
- | `/writer/settings/topics` | RSS topic subscriptions |
311
-
312
- ---
313
-
314
- ## Configuring Tailwind
315
-
316
- Autoblogger's UI uses Tailwind CSS classes. Add the package's files to your Tailwind content configuration so the classes aren't purged:
317
-
318
- ```javascript
319
- // tailwind.config.js (or tailwind.config.ts)
320
- module.exports = {
321
- content: [
322
- './app/**/*.{js,ts,jsx,tsx}',
323
- './components/**/*.{js,ts,jsx,tsx}',
324
- // Add this line to include Autoblogger's components
325
- './node_modules/autoblogger/dist/**/*.{js,mjs}',
326
- ],
327
- // ... rest of your config
328
- }
329
- ```
330
-
331
- The dashboard uses semantic color tokens like `bg-card`, `text-muted-foreground`, `border-border`, etc. These come from shadcn/ui conventions. If you're using shadcn, they'll work automatically. Otherwise, add these CSS variables to your globals:
332
-
333
- ```css
334
- /* globals.css */
335
- :root {
336
- --background: 0 0% 100%;
337
- --foreground: 0 0% 3.9%;
338
- --card: 0 0% 100%;
339
- --card-foreground: 0 0% 3.9%;
340
- --popover: 0 0% 100%;
341
- --popover-foreground: 0 0% 3.9%;
342
- --primary: 0 0% 9%;
343
- --primary-foreground: 0 0% 98%;
344
- --secondary: 0 0% 96.1%;
345
- --secondary-foreground: 0 0% 9%;
346
- --muted: 0 0% 96.1%;
347
- --muted-foreground: 0 0% 45.1%;
348
- --accent: 0 0% 96.1%;
349
- --accent-foreground: 0 0% 9%;
350
- --destructive: 0 84.2% 60.2%;
351
- --destructive-foreground: 0 0% 98%;
352
- --border: 0 0% 89.8%;
353
- --input: 0 0% 89.8%;
354
- --ring: 0 0% 3.9%;
355
- }
356
-
357
- .dark {
358
- --background: 0 0% 3.9%;
359
- --foreground: 0 0% 98%;
360
- --card: 0 0% 3.9%;
361
- --card-foreground: 0 0% 98%;
362
- --popover: 0 0% 3.9%;
363
- --popover-foreground: 0 0% 98%;
364
- --primary: 0 0% 98%;
365
- --primary-foreground: 0 0% 9%;
366
- --secondary: 0 0% 14.9%;
367
- --secondary-foreground: 0 0% 98%;
368
- --muted: 0 0% 14.9%;
369
- --muted-foreground: 0 0% 63.9%;
370
- --accent: 0 0% 14.9%;
371
- --accent-foreground: 0 0% 98%;
372
- --destructive: 0 62.8% 30.6%;
373
- --destructive-foreground: 0 0% 98%;
374
- --border: 0 0% 14.9%;
375
- --input: 0 0% 14.9%;
376
- --ring: 0 0% 83.1%;
377
- }
378
- ```
379
-
380
- ---
381
-
382
- ## Displaying Posts on Your Site
383
-
384
- Use the CMS data layer to fetch posts for your public pages:
72
+ Fetch published posts for your public pages:
385
73
 
386
74
  ```typescript
387
75
  // app/blog/page.tsx
388
76
  import { cms } from '@/lib/cms'
389
- import Link from 'next/link'
390
77
 
391
78
  export default async function BlogPage() {
392
79
  const { posts } = await cms.data.posts.findAll({
393
80
  where: { status: 'published' },
394
81
  orderBy: { publishedAt: 'desc' },
395
- take: 20,
396
82
  })
397
83
 
398
84
  return (
399
- <div>
400
- <h1>Blog</h1>
401
- <ul>
402
- {posts.map(post => (
403
- <li key={post.id}>
404
- <Link href={`/blog/${post.slug}`}>
405
- {post.title}
406
- </Link>
407
- </li>
408
- ))}
409
- </ul>
410
- </div>
85
+ <ul>
86
+ {posts.map(post => (
87
+ <li key={post.id}><a href={`/blog/${post.slug}`}>{post.title}</a></li>
88
+ ))}
89
+ </ul>
411
90
  )
412
91
  }
413
92
  ```
414
93
 
415
- ### Rendering a Single Post
94
+ Render a single post:
416
95
 
417
96
  ```typescript
418
97
  // app/blog/[slug]/page.tsx
419
98
  import { cms } from '@/lib/cms'
420
99
  import { renderMarkdown } from 'autoblogger/markdown'
421
- import { generateSeoMetadata } from 'autoblogger/seo'
422
100
  import { notFound } from 'next/navigation'
423
101
 
424
- export default async function PostPage({
425
- params
426
- }: {
427
- params: Promise<{ slug: string }>
428
- }) {
102
+ export default async function PostPage({ params }: { params: Promise<{ slug: string }> }) {
429
103
  const { slug } = await params
430
104
  const post = await cms.data.posts.findBySlug(slug)
431
105
 
432
- if (!post || post.status !== 'published') {
433
- notFound()
434
- }
435
-
436
- const html = renderMarkdown(post.markdown)
106
+ if (!post || post.status !== 'published') notFound()
437
107
 
438
108
  return (
439
109
  <article>
440
110
  <h1>{post.title}</h1>
441
- {post.subtitle && <p className="text-xl text-gray-600">{post.subtitle}</p>}
442
- <div
443
- className="prose dark:prose-invert"
444
- dangerouslySetInnerHTML={{ __html: html }}
445
- />
111
+ <div className="prose" dangerouslySetInnerHTML={{ __html: renderMarkdown(post.markdown) }} />
446
112
  </article>
447
113
  )
448
114
  }
115
+ ```
449
116
 
450
- // Generate SEO metadata
451
- export async function generateMetadata({
452
- params
453
- }: {
454
- params: Promise<{ slug: string }>
455
- }) {
456
- const { slug } = await params
457
- const post = await cms.data.posts.findBySlug(slug)
458
-
459
- if (!post) return {}
460
-
461
- return generateSeoMetadata(post)
462
- }
117
+ ## CLI Reference
118
+
119
+ ```bash
120
+ npx autoblogger init # Interactive setup
121
+ npx autoblogger init --yes # Use defaults, no prompts
122
+ npx autoblogger init --dry-run # Preview changes
123
+ npx autoblogger import ./posts # Import markdown files
463
124
  ```
464
125
 
465
- ---
126
+ ## Keyboard Shortcuts
466
127
 
467
- ## Package Exports
128
+ | Shortcut | Action |
129
+ |----------|--------|
130
+ | ⌘K | Toggle chat panel |
131
+ | ⌘⇧A | Toggle Ask/Agent mode |
132
+ | ⌘. | Toggle theme |
133
+ | ⌘/ | Toggle view |
134
+ | N | New article |
135
+ | Esc | Go back |
468
136
 
469
- Autoblogger provides several entry points:
137
+ ## Package Exports
470
138
 
471
139
  ```typescript
472
- // Main entry — server-side data layer and API handlers
140
+ // Server
473
141
  import { createAutoblogger } from 'autoblogger'
142
+ import { runAutoDraft } from 'autoblogger'
474
143
 
475
- // UI components — React dashboard (client-side)
144
+ // UI
476
145
  import { AutobloggerDashboard } from 'autoblogger/ui'
146
+ import { ChatProvider, ChatPanel, ChatButton } from 'autoblogger/ui'
477
147
 
478
- // Markdown utilities — render markdown to HTML, parse HTML to markdown
479
- import { renderMarkdown, parseMarkdown } from 'autoblogger/markdown'
480
-
481
- // SEO utilities generate meta tags from post data
482
- import { generateSeoMetadata } from 'autoblogger/seo'
483
-
484
- // Article styles — CSS class helpers for consistent article layout
485
- import { ARTICLE_STYLES } from 'autoblogger/styles/article'
148
+ // Utilities
149
+ import { renderMarkdown, htmlToMarkdown } from 'autoblogger/markdown'
150
+ import { getSeoValues } from 'autoblogger/seo'
151
+ import { ARTICLE_CLASSES } from 'autoblogger/styles/article'
486
152
  ```
487
153
 
488
- ---
489
-
490
- ## CLI Reference
491
-
492
- Autoblogger includes a CLI for project setup and content management.
493
-
494
- ### Commands
495
-
496
- | Command | Description |
497
- |---------|-------------|
498
- | `npx autoblogger init` | Set up Autoblogger in your Next.js project |
499
- | `npx autoblogger import <path>` | Import markdown/MDX content into the database |
500
-
501
- ### Init Options
502
-
503
- | Option | Description |
504
- |--------|-------------|
505
- | `--yes`, `-y` | Skip prompts and use defaults |
506
- | `--skip-migrate` | Don't run database migration |
507
- | `--import=<path>` | Import content from specified path after setup |
508
- | `--dry-run` | Show what would be done without making changes |
509
-
510
- ### Import Options
511
-
512
- | Option | Description |
513
- |--------|-------------|
514
- | `--status=<status>` | Set imported posts status (`draft` or `published`) |
515
- | `--tag=<tag>` | Add a tag to all imported posts |
516
- | `--dry-run` | Show what would be imported without making changes |
517
-
518
- ---
519
-
520
- ## AI Models
521
-
522
- Autoblogger supports these AI models out of the box:
523
-
524
- | ID | Name | Provider | Description |
525
- |----|------|----------|-------------|
526
- | `claude-sonnet` | Sonnet 4.5 | Anthropic | Fast, capable, best value |
527
- | `claude-opus` | Opus 4.5 | Anthropic | Highest quality, slower |
528
- | `gpt-5.2` | GPT-5.2 | OpenAI | Latest OpenAI flagship |
529
- | `gpt-5-mini` | GPT-5 Mini | OpenAI | Fast and cost-efficient |
530
-
531
- ### AI Features
532
-
533
- - **URL Context**: Paste a URL into your prompt and the AI will fetch and read the article content
534
- - **Chat Modes**: Rewrite, expand, shorten, or chat freely with your content
535
- - **Custom Prompts**: Configure prompt templates in **Settings → AI**
536
-
537
- Configure the default model and custom prompts in the dashboard under **Settings → AI**.
538
-
539
- ---
540
-
541
- ## User Roles
542
-
543
- Autoblogger supports three roles:
544
-
545
- | Role | Permissions |
546
- |------|-------------|
547
- | `admin` | Full access. Manage users, settings, publish/delete any post. |
548
- | `writer` | Create posts, publish their own posts, edit drafts. |
549
- | `drafter` | Create drafts only. Cannot publish. |
550
-
551
- Roles are stored in the `User.role` field. Your auth configuration determines how roles are checked.
552
-
553
- ---
554
-
555
154
  ## Troubleshooting
556
155
 
557
- ### "Cannot find module 'autoblogger/ui'"
558
-
559
- Make sure you're importing from the correct path and that the package is installed:
560
-
561
- ```bash
562
- npm install autoblogger
563
- ```
564
-
565
- ### Tailwind classes not applying
566
-
567
- Add the package to your Tailwind content config:
568
-
156
+ **Tailwind classes not applying?** Add to your Tailwind content config:
569
157
  ```javascript
570
- content: [
571
- // ... your files
572
- './node_modules/autoblogger/dist/**/*.{js,mjs}',
573
- ]
158
+ content: ['./node_modules/autoblogger/dist/**/*.{js,mjs}']
574
159
  ```
575
160
 
576
- ### AI features not working
577
-
578
- Check that your API keys are set in environment variables:
161
+ **Styles missing?** Import in `globals.css` before Tailwind directives:
162
+ ```css
163
+ @import 'autoblogger/styles/autoblogger.css';
164
+ ```
579
165
 
166
+ **AI not working?** Check your environment variables:
580
167
  ```bash
581
168
  ANTHROPIC_API_KEY="sk-ant-..."
582
169
  OPENAI_API_KEY="sk-..."
583
170
  ```
584
171
 
585
- And that you're passing them in the config:
586
-
587
- ```typescript
588
- ai: {
589
- anthropicKey: process.env.ANTHROPIC_API_KEY,
590
- openaiKey: process.env.OPENAI_API_KEY,
591
- }
592
- ```
593
-
594
- ### Database errors
595
-
596
- Make sure you've:
597
- 1. Added all required models to your Prisma schema
598
- 2. Run `npx prisma migrate dev`
599
- 3. Run `npx prisma generate`
600
-
601
- ---
602
-
603
172
  ## License
604
173
 
605
174
  MIT © [Hunter Rosenblume](https://github.com/hrosenblume)