{"id":32492411,"url":"https://github.com/bighadj22/chatgpt-apps-sdk-examples","last_synced_at":"2026-05-15T18:02:35.629Z","repository":{"id":319176058,"uuid":"1077643739","full_name":"bighadj22/chatgpt-apps-sdk-examples","owner":"bighadj22","description":"A ChatGPT App that brings high-quality, royalty-free photography from Pexels directly into your conversations. Built with the Model Context Protocol (MCP) and powered by Cloudflare Workers.","archived":false,"fork":false,"pushed_at":"2025-10-16T22:23:42.000Z","size":1831,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-27T11:02:57.961Z","etag":null,"topics":["apps-sdk","chatgpt-apps-sdk","cloudflare","cloudflare-mcp","mcp-server","openai-apps-sdk"],"latest_commit_sha":null,"homepage":"https://chatgptappsbuilders.com","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bighadj22.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-16T14:32:25.000Z","updated_at":"2025-10-19T00:14:45.000Z","dependencies_parsed_at":"2025-10-18T10:00:34.385Z","dependency_job_id":"7411e134-ddf0-45c6-a229-696e3af44bc5","html_url":"https://github.com/bighadj22/chatgpt-apps-sdk-examples","commit_stats":null,"previous_names":["bighadj22/chatgpt-apps-sdk-examples"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/bighadj22/chatgpt-apps-sdk-examples","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bighadj22%2Fchatgpt-apps-sdk-examples","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bighadj22%2Fchatgpt-apps-sdk-examples/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bighadj22%2Fchatgpt-apps-sdk-examples/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bighadj22%2Fchatgpt-apps-sdk-examples/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bighadj22","download_url":"https://codeload.github.com/bighadj22/chatgpt-apps-sdk-examples/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bighadj22%2Fchatgpt-apps-sdk-examples/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33074393,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-15T11:35:32.926Z","status":"ssl_error","status_checked_at":"2026-05-15T11:35:31.362Z","response_time":103,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["apps-sdk","chatgpt-apps-sdk","cloudflare","cloudflare-mcp","mcp-server","openai-apps-sdk"],"created_at":"2025-10-27T11:00:46.459Z","updated_at":"2026-05-15T18:02:35.624Z","avatar_url":"https://github.com/bighadj22.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Pexels ChatGPT App \n\nA ChatGPT App that brings high-quality, royalty-free photography from [Pexels](https://www.pexels.com) directly into your conversations. Built with the Model Context Protocol (MCP) and powered by Cloudflare Workers.\n\n![Version](https://img.shields.io/badge/version-1.0.0-blue)\n![TypeScript](https://img.shields.io/badge/TypeScript-5.9.3-blue)\n![React](https://img.shields.io/badge/React-18.3.1-blue)\n![Cloudflare Workers](https://img.shields.io/badge/Cloudflare-Workers-orange)\n\n---\n\n![Pexels ChatGPT App Demo](docs/Screenshot.png)\n\n---\n\n## What is This?\n\nThis project is a **Model Context Protocol (MCP) server** that integrates the Pexels API into ChatGPT. Users can search for professional stock photos directly in their chat conversations and view results in an interactive, responsive gallery widget.\n\n### Key Features\n\n- **🔍 Advanced Photo Search** - Search by keywords, orientation, color palette, size, and more\n- **🎨 Interactive Gallery Widget** - Beautiful carousel interface with photo cards\n- **🌓 Theme Aware** - Automatically adapts to light/dark mode\n- **♿ Accessible** - Full screen reader support and keyboard navigation\n- **⚡ Serverless** - Runs on Cloudflare Workers edge network for global performance\n- **📱 Responsive** - Works seamlessly across desktop, tablet, and mobile\n\n---\n\n## Architecture\n\nThis project demonstrates a complete MCP application architecture:\n\n```\n┌─────────────────────────────────────────────────────────────┐\n│                         ChatGPT UI                          │\n├─────────────────────────────────────────────────────────────┤\n│  React Widget (Embedded Gallery)                            │\n│  ↓ Uses OpenAI SDK                                          │\n├─────────────────────────────────────────────────────────────┤\n│  MCP Protocol (SSE)                                          │\n│  ↓ Tool Invocation                                          │\n├─────────────────────────────────────────────────────────────┤\n│  Cloudflare Worker (Durable Objects)                        │\n│  ↓ HTTP Request                                             │\n├─────────────────────────────────────────────────────────────┤\n│  Pexels API (https://api.pexels.com)                        │\n└─────────────────────────────────────────────────────────────┘\n```\n\n### Tech Stack\n\n**Backend:**\n- [Cloudflare Workers](https://workers.cloudflare.com/) - Serverless edge computing\n- [Durable Objects](https://developers.cloudflare.com/durable-objects/) - Stateful MCP server instances\n- [@modelcontextprotocol/sdk](https://github.com/modelcontextprotocol/sdk) - MCP implementation\n- TypeScript 5.9.3\n\n**Frontend:**\n- React 18.3.1 - UI framework\n- [embla-carousel-react](https://www.embla-carousel.com/) - Carousel functionality\n- [lucide-react](https://lucide.dev/) - Icon library\n- esbuild - Fast bundler\n\n**External API:**\n- [Pexels API](https://www.pexels.com/api/) - Free stock photography\n\n---\n\n## Project Structure\n\n```\npexels-app/\n├── src/                              # Backend (Cloudflare Worker)\n│   ├── index.ts                      # MCP Durable Object \u0026 worker entry\n│   ├── types.ts                      # Shared TypeScript types\n│   ├── tools/\n│   │   └── pexels.ts                 # Pexels search tool implementation\n│   └── components/\n│       ├── react-widget-inline.ts    # Bundled React widget (auto-generated)\n│       └── react-widget-resource.ts  # HTML wrapper for widget\n│\n├── web/                              # Frontend (React Widget)\n│   ├── src/\n│   │   ├── component.tsx             # React entry point\n│   │   ├── theme.tsx                 # Theme tokens \u0026 context\n│   │   ├── components/\n│   │   │   ├── App.tsx               # Main gallery application\n│   │   │   └── cards/                # Photo card components\n│   │   └── hooks/\n│   │       ├── use-openai-global.ts  # OpenAI SDK integration\n│   │       └── use-widget-state.ts   # Persistent state management\n│   └── dist/                         # Build output\n│\n├── scripts/\n│   └── inline-react-widget.js        # Bundles React into Worker\n│\n├── docs/                             # Comprehensive documentation\n│   ├── ARCHITECTURE.md               # System design\n│   ├── DEPLOYMENT-GUIDE.md           # Deployment instructions\n│   └── ...                           # More guides\n│\n├── wrangler.jsonc                    # Cloudflare Worker config\n├── .dev.vars.example                 # Environment variable template\n└── package.json                      # Dependencies \u0026 scripts\n```\n\n---\n\n## Getting Started\n\n### Prerequisites\n\n- Node.js 18+ and npm\n- [Pexels API key](https://www.pexels.com/api/) (free)\n- [Cloudflare account](https://dash.cloudflare.com/sign-up/workers-and-pages) (free tier available)\n\n### Installation\n\n1. **Clone the repository:**\n   ```bash\n   git clone https://github.com/yourusername/pexels-app.git\n   cd pexels-app\n   ```\n\n2. **Install dependencies:**\n   ```bash\n   npm install\n   cd web \u0026\u0026 npm install \u0026\u0026 cd ..\n   ```\n\n3. **Configure environment variables:**\n   ```bash\n   cp .dev.vars.example .dev.vars\n   ```\n\n   Edit `.dev.vars` and add your Pexels API key:\n   ```\n   PEXELS_API_KEY=your_actual_api_key_here\n   ```\n\n4. **Build and run locally:**\n   ```bash\n   npm run dev\n   ```\n\n   The MCP server will be available at `http://localhost:8787`\n\n### Deployment\n\n1. **Authenticate with Cloudflare:**\n   ```bash\n   npx wrangler login\n   ```\n\n2. **Set production secrets:**\n   ```bash\n   npx wrangler secret put PEXELS_API_KEY\n   # Enter your API key when prompted\n   ```\n\n3. **Deploy to Cloudflare:**\n   ```bash\n   npm run deploy\n   ```\n\n   Your app will be live at `https://your-worker-name.workers.dev`\n\n---\n\n## Usage\n\n### MCP Tool: `pexels.searchPhotos`\n\nSearch the Pexels library with powerful filtering options:\n\n**Parameters:**\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `query` | string | Yes | Search keywords (1-120 characters) |\n| `page` | number | No | Page number (1-50, default: 1) |\n| `perPage` | number | No | Results per page (1-30, default: 12) |\n| `orientation` | string | No | `landscape`, `portrait`, or `square` |\n| `size` | string | No | `large`, `medium`, or `small` |\n| `color` | string | No | Hex code or color keyword |\n| `locale` | string | No | ISO locale code (e.g., `en-US`) |\n\n**Example in ChatGPT:**\n\n```\nUser: Show me portrait photos of mountain landscapes\n\n[ChatGPT invokes: pexels.searchPhotos({\n  query: \"mountain landscapes\",\n  orientation: \"portrait\",\n  perPage: 15\n})]\n\n[Interactive gallery widget displays with 15 photos]\n```\n\n**Output:**\n\n- Text summary: \"Found X Pexels photos for 'query'\"\n- Interactive gallery widget with photo cards\n- Each card shows:\n  - High-quality photo preview\n  - Photographer attribution\n  - \"View on Pexels\" button (opens in new tab)\n\n---\n\n## Development\n\n### NPM Scripts\n\n```bash\n# Development\nnpm start                 # Start local dev server\nnpm run dev              # Same as start\n\n# Building\nnpm run build:widget     # Build React widget only\nnpm run deploy           # Build everything and deploy\n\n# React Development (in web/ directory)\ncd web\nnpm run build            # Build React bundle\nnpm run watch            # Watch mode for React changes\n\n# Type Checking\nnpm run type-check       # Check TypeScript types\n```\n\n### Development Workflow\n\n1. **Make changes to React widget** (`web/src/`)\n2. **Build widget:** `cd web \u0026\u0026 npm run build`\n3. **Inline bundle:** `node scripts/inline-react-widget.js`\n4. **Test locally:** `npm run dev`\n5. **Deploy:** `npm run deploy`\n\nFor faster iteration, use watch mode in a separate terminal:\n```bash\ncd web \u0026\u0026 npm run watch\n```\n\n---\n\n## Configuration\n\n### Environment Variables\n\n**Development (`.dev.vars`):**\n```bash\nPEXELS_API_KEY=your_api_key_here\n```\n\n**Production (Cloudflare Secrets):**\n```bash\nnpx wrangler secret put PEXELS_API_KEY\nnpx wrangler secret list  # View configured secrets\n```\n\n### Wrangler Configuration\n\nKey settings in `wrangler.jsonc`:\n\n```json\n{\n  \"name\": \"pexels\",\n  \"main\": \"src/index.ts\",\n  \"compatibility_date\": \"2025-03-10\",\n  \"durable_objects\": {\n    \"bindings\": [{\n      \"class_name\": \"MyMCP\",\n      \"name\": \"MCP_OBJECT\"\n    }]\n  },\n  \"vars\": {\n    \"PEXELS_API_BASE_URL\": \"https://api.pexels.com/v1\"\n  }\n}\n```\n\n---\n\n## Documentation\n\nComprehensive documentation is available in the `docs/` directory:\n\n- **[ARCHITECTURE.md](docs/ARCHITECTURE.md)** - How frontend and backend connect\n- **[DEPLOYMENT-GUIDE.md](docs/DEPLOYMENT-GUIDE.md)** - Complete deployment instructions\n- **[PROJECT-TOUR.md](docs/PROJECT-TOUR.md)** - File-by-file walkthrough\n- **[APP_DESIGN_GUIDELINES.md](docs/APP_DESIGN_GUIDELINES.md)** - OpenAI design principles\n- **[METADATA-OPTIMIZATION.md](docs/METADATA-OPTIMIZATION.md)** - MCP metadata tuning\n- **[FUTURE-UI-UX-GUIDE.md](docs/FUTURE-UI-UX-GUIDE.md)** - UI styling best practices\n- **[WRANGLER-SECRET-COMMANDS.md](docs/WRANGLER-SECRET-COMMANDS.md)** - Secret management\n\n---\n\n## Design Philosophy\n\nThis project follows OpenAI's ChatGPT App design guidelines:\n\n1. **Conversational** - Seamlessly integrated into chat flow\n2. **Intelligent** - Context-aware tool invocation\n3. **Simple** - Focused, single-purpose interactions\n4. **Responsive** - Fast, lightweight, edge-optimized\n5. **Accessible** - Screen reader support, keyboard navigation\n\n### UI/UX Principles\n\n- **System-First Design** - Inherits ChatGPT's colors, fonts, and spacing\n- **Theme Tokens** - Dynamic light/dark theme support\n- **Transparent Backgrounds** - Blends naturally with host environment\n- **Component-Scoped Styles** - No global CSS to avoid conflicts\n- **Minimal Branding** - Only subtle accent colors on CTAs\n\n---\n\n## API Reference\n\n### Pexels API Integration\n\nThe tool makes requests to the Pexels API v1:\n\n**Endpoint:** `GET https://api.pexels.com/v1/search`\n\n**Authentication:** Bearer token via `Authorization` header\n\n**Rate Limits:** 200 requests/hour (free tier)\n\n**Response Format:** Normalized from snake_case to camelCase for TypeScript\n\nFor full Pexels API documentation, visit: https://www.pexels.com/api/documentation/\n\n---\n\n## Advanced Features\n\n### Custom React Hooks\n\n**`useOpenAiGlobal(key)`** - Access OpenAI SDK globals\n```typescript\nconst theme = useOpenAiGlobal('theme'); // 'light' | 'dark'\nconst toolOutput = useOpenAiGlobal('toolOutput'); // Tool result data\n```\n\n**`useWidgetState(defaultState)`** - Persistent widget state\n```typescript\nconst [state, setState] = useWidgetState({ page: 1 });\n// State survives widget remounts\n```\n\n**`useThemeTokens()`** - Access theme design tokens\n```typescript\nconst tokens = useThemeTokens();\n// tokens.colors.background, tokens.fonts.body, etc.\n```\n\n### Type Safety\n\n- Full TypeScript coverage with strict mode\n- Zod validation for all tool inputs\n- Shared types between frontend and backend\n- Automatic type inference from OpenAI SDK\n\n### Error Handling\n\nGraceful handling of:\n- API authentication failures\n- Network errors\n- Missing configuration\n- Invalid parameters\n- Empty search results\n- User-friendly error messages in widget\n\n---\n\n## Security\n\n### Content Security Policy\n\nThe widget enforces a strict CSP:\n\n```\ndefault-src 'none';\nscript-src 'self' 'unsafe-inline';\nstyle-src 'self' 'unsafe-inline';\nimg-src 'self' data: https://images.pexels.com;\nframe-ancestors 'none';\n```\n\n### Best Practices\n\n- API keys stored as Cloudflare secrets (never in code)\n- `.dev.vars.example` provided as template\n- Input validation with Zod schemas\n\n---\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n---\n\n## Acknowledgments\n\n- **[Pexels](https://www.pexels.com)** - For providing free, high-quality stock photography\n- **[Cloudflare Workers](https://workers.cloudflare.com/)** - For serverless infrastructure\n- **[OpenAI](https://openai.com)** - For ChatGPT and the MCP specification\n- **[Model Context Protocol](https://modelcontextprotocol.io/)** - For the protocol specification\n\n---\n\n\n## Learn More\n\n### MCP Resources\n- [Model Context Protocol Docs](https://modelcontextprotocol.io/)\n- [MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk)\n\n### Cloudflare Resources\n- [Workers Documentation](https://developers.cloudflare.com/workers/)\n- [Durable Objects Guide](https://developers.cloudflare.com/durable-objects/)\n- [Wrangler CLI](https://developers.cloudflare.com/workers/wrangler/)\n\n### ChatGPT App Development\n- [OpenAI App Guidelines](https://platform.openai.com/docs/guides/apps)\n- [ChatGPT App Design](docs/APP_DESIGN_GUIDELINES.md)\n\n---\n\n**Built with ❤️ using the Model Context Protocol**\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbighadj22%2Fchatgpt-apps-sdk-examples","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbighadj22%2Fchatgpt-apps-sdk-examples","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbighadj22%2Fchatgpt-apps-sdk-examples/lists"}