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
15 changes: 15 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Engine selection (optional).
# Auto-detection order: claude (local CLI login) -> codex (local CLI login) -> openrouter.
# Set to force one: claude | codex | openrouter
# CODEFOX_ENGINE=

# OpenRouter API key — required only when using the openrouter engine
# (i.e. no logged-in `claude`/`codex` CLI on PATH, or CODEFOX_ENGINE=openrouter).
# Also used for project title generation (skipped without a key).
# OPENROUTER_API_KEY=your_openrouter_api_key_here

# Default model for the OpenRouter engine (harness engines use the CLI's default model)
NEXT_PUBLIC_DEFAULT_MODEL=anthropic/claude-sonnet-4.5

# App name
NEXT_PUBLIC_APP_NAME=CodeFox Local
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ yarn-error.log*

# env files (can opt-in for committing if needed)
.env*
!.env.example

# vercel
.vercel
Expand Down
62 changes: 61 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,64 @@ An AI-powered local website project generator that allows users to create comple
3. **Date serialization in Zustand persist**:
- Date objects are serialized to strings in localStorage
- Always handle both Date and string types when accessing `lastAccessedAt` or `createdAt`
- Use custom deserialization in `createJSONStorage` getItem
- Use custom deserialization in `createJSONStorage` getItem

4. **Loading external packages (CSS/JS) in Sandpack preview**:
- Sandpack runs in a browser sandbox and cannot access node_modules directly
- ❌ WRONG: Adding `<script src="https://cdn.tailwindcss.com"></script>` in `/public/index.html`
- ❌ WRONG: Using `@import "tailwindcss"` in CSS (requires PostCSS, not available in browser)
- ✅ CORRECT: Use `externalResources` option in SandpackProvider:
```tsx
<SandpackProvider
options={{
externalResources: ["https://cdn.tailwindcss.com"]
}}
>
```
- This method works for ANY external CSS/JS library (e.g., Bootstrap, Alpine.js, etc.)
- The resources are automatically injected into the Sandpack iframe at initialization

## Modifying AI Prompt System

When you need to add new context to the AI's system prompt (e.g., file organization rules, coding standards, etc.):

### Steps to modify prompt:

1. **Update `lib/prompts.ts`**:
- Add new parameter to `createSystemPrompt` function options
- Create a new section function (e.g., `createFileInstructionSection`)
- Add the section to the sections array

2. **Update API route `app/api/chat/route.ts`**:
- Extract the new parameter from request body: `const { messages, projectId, files, newParam } = await req.json()`
- Pass it to `createSystemPrompt({ files, newParam })`

3. **Update frontend transport `app/page.tsx`**:
- In the `transport` useMemo, add the new data to the return object in `body: async () => { ... }`
- Can use environment variables: `process.env.NEXT_PUBLIC_YOUR_VAR`
- Return: `{ projectId, files, newParam }`

### Example: Adding file organization instructions

```typescript
// 1. lib/prompts.ts
export function createSystemPrompt(options?: {
files?: string[];
fileInstruction?: string; // ← New parameter
}): string {
// ...
if (options?.fileInstruction) {
sections.push(createFileInstructionSection(options.fileInstruction));
}
}

// 2. app/api/chat/route.ts
const { messages, projectId, files, fileInstruction } = await req.json();
const systemPrompt = createSystemPrompt({ files, fileInstruction });

// 3. app/page.tsx
body: async () => {
const fileInstruction = process.env.NEXT_PUBLIC_FILE_INSTRUCTION || "default rules";
return { projectId, files, fileInstruction };
}
```
25 changes: 18 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# CodeFox Chat 🦊
# CodeFox Local 🦊

A sleek, geek-style chat application with AI assistant and integrated web preview. Built with Next.js 15, Bun, and Claude Sonnet 4.5.
A local-first AI website generator: describe the site you want, and CodeFox builds it in a live Sandpack preview, editing real project files under `~/.codefox-local/projects`. Built with Next.js 15, Bun, and the Vercel AI SDK.

## 🎨 Features

Expand All @@ -19,8 +19,13 @@ A sleek, geek-style chat application with AI assistant and integrated web previe
- **Runtime**: Bun
- **Language**: TypeScript
- **Styling**: Tailwind CSS 4
- **AI SDK**: Vercel AI SDK v5
- **AI Model**: Claude Sonnet 4.5 (via OpenRouter)
- **AI SDK**: Vercel AI SDK v7
- **Supported engines** (auto-detected in this order, first match wins):
1. **Claude Code** — uses your local `claude` CLI login (subscription, no API key), default when installed and logged in
2. **Codex** — uses your local `codex` CLI login
3. **OpenRouter** — API fallback, needs `OPENROUTER_API_KEY`

Force a specific engine with `CODEFOX_ENGINE=claude|codex|openrouter`. The local engines run through `@ai-sdk/harness` rooted at the project directory, so the agent edits your project files directly with its own coding tools.
- **Icons**: Lucide React
- **Markdown**: react-markdown + react-syntax-highlighter

Expand All @@ -41,15 +46,21 @@ cp .env.example .env.local

## 🔑 Configuration

Create a `.env.local` file with your OpenRouter API key:
With a logged-in `claude` or `codex` CLI on your PATH, no configuration is needed — the engine is detected automatically. Otherwise create a `.env.local`:

```env
# Optional: force an engine instead of auto-detection (claude | codex | openrouter)
CODEFOX_ENGINE=

# Required only for the OpenRouter engine
OPENROUTER_API_KEY=your_openrouter_api_key_here

# OpenRouter model (harness engines use the CLI's default model)
NEXT_PUBLIC_DEFAULT_MODEL=anthropic/claude-sonnet-4.5
NEXT_PUBLIC_APP_NAME=CodeFox Chat
NEXT_PUBLIC_APP_NAME=CodeFox Local
```

Get your OpenRouter API key from: https://openrouter.ai/
Get an OpenRouter API key from: https://openrouter.ai/ — project title generation also uses OpenRouter and is skipped without a key.

## 🎯 Usage

Expand Down
Loading
Loading