{"slug": "i-spent-5-on-openrouter-while-building-ai-features-for-an-ngo-app", "title": "I Spent $5 on OpenRouter While Building AI Features for an NGO App", "summary": "A developer building AI features for the PSS NGO website spent about $5 on OpenRouter during development. The project integrates a knowledge base with MongoDB and embeddings to control AI-generated content, and encountered issues with output limits and factual contradictions. The developer emphasizes the importance of application-level control over AI responses.", "body_md": "I've been working on the PSS website for quite some time, and recently a lot of my work went into its AI features.\n\nThe application already handles sessions, events, staff, blog posts, gallery, testimonials, donations, settings, and an admin CMS.\n\nFor the AI work, I wanted two things:\n\nThe stack is **Next.js, React, TypeScript, MongoDB, Mongoose, Clerk, Cloudinary, Tailwind CSS, shadcn/ui, TanStack Query and OpenRouter**.\n\nDuring development, my OpenRouter dashboard reached about **$4.99 in total spend**.\n\nThe $5 isn't the interesting part.\n\nWhat happened while building the features is.\n\nI didn't want the AI to answer PSS-related questions only from its general knowledge.\n\nI needed information that the application could control and update.\n\nSo I built a knowledge flow around approved PSS content:\n\n```\nApproved PSS knowledge\n        ↓\n     Chunking\n        ↓\n    Embeddings\n        ↓\n     MongoDB\n        ↓\nRelevant knowledge retrieved\n        ↓\n    AI context\n        ↓\n Response / content generation\n```\n\nThe stored knowledge includes the content plus details such as its source, authority, status and visibility.\n\nThat also gives me a way to separate public knowledge from internal AI guidance and policies.\n\nThe idea I ended up using is simple:\n\nThe knowledge base decides what PSS teaches. The model decides how to communicate it.\n\nThat became much more important once I started checking the generated content.\n\nThe admin CMS also has AI-assisted blog creation.\n\nAI can help generate:\n\nI didn't want one button to generate an entire blog post from nothing.\n\nFor smaller fields, the admin can run individual AI actions. Full article generation is a separate flow.\n\nThe article generation can use the information already entered in the editor:\n\n```\nTitle\nCategory\nTags\nSEO title\nSEO description\nExcerpt\nWriting instruction\nRelevant PSS knowledge\n        ↓\n     AI model\n        ↓\n Generated article\n        ↓\n   Article editor\n```\n\nThis is much more useful than sending something generic like:\n\n```\n\"Write a blog post about meditation.\"\n```\n\nThe application already has context. The AI should use it.\n\nMy first full-article generation didn't finish.\n\nThe logs showed:\n\n```\nmodel: openai/gpt-5-mini\ntask: full_article\npromptTokens: 1013\ncompletionTokens: 1800\nfinishReason: length\n```\n\nThe application reported:\n\n```\nAI generation reached the model's output limit.\n```\n\nI increased:\n\n```\nAI_CONTENT_MAX_TOKENS\n```\n\nfrom `1800`\n\nto `2000`\n\n, and after testing again, the generation completed.\n\nIt was a small configuration issue, but it reminded me that an AI feature has limits that a normal API call doesn't have.\n\nThe request can succeed while the output is still incomplete.\n\nThe application needs to detect and handle that.\n\nThe generated article looked good.\n\nThat was actually the problem.\n\nWhen I compared it with the approved PSS knowledge, I found some contradictions.\n\nThe approved information included specific guidance around:\n\nThe generated article introduced more general meditation advice, including things like resting the hands in the lap or on the knees, allowing the eyes to remain open, and suggesting specific practice durations.\n\nThose suggestions may sound reasonable for meditation in general.\n\nBut the website isn't publishing generic meditation advice.\n\nIt represents PSS.\n\nSo the output can be well written and still be wrong **for the application**.\n\nThat was the most useful thing I found during testing.\n\nBefore this work, I mostly thought of retrieval as a way to give the model better information.\n\nNow I also see it as a way to keep the application's content under control.\n\nThe embeddings help find relevant information, but the application still needs to know:\n\nSo it isn't simply:\n\n```\ndocuments → embeddings → model\n```\n\nThere is an application around it.\n\nGetting the backend generation working wasn't enough.\n\nWhile using the admin workflow, I also found that the AI actions needed to behave like normal application features.\n\nI worked on things such as:\n\nAdding AI doesn't remove normal UX problems.\n\nIt gives you a few more.\n\nMy OpenRouter dashboard showed approximately:\n\nThe dashboard also showed usage from **GPT-5.4, GPT-5 Mini and Text Embedding 3 Small**.\n\nOne clarification: 73.5M is the **token-volume metric shown by the dashboard**. I wouldn't describe it as 73.5M tokens of generated text.\n\nMost of this usage came from development, testing AI flows, model calls and embeddings.\n\nThe useful part wasn't getting a lot of AI work done for $5.\n\nIt was being able to see what experimentation actually costs.\n\nThe 94.7% cache hit rate also made me think more about repeated context and what these costs could look like with more traffic.\n\nI'm trying not to judge an AI feature only by whether the API returns a successful response.\n\nI also need to ask:\n\nSome of these are things I've already encountered during development. Others are areas I still want to make more systematic with testing.\n\nThe AI system isn't finished.\n\nIf I started this part of the project again, I'd think about the knowledge and failure cases earlier.\n\nNot only:\n\n```\nWhich model should I use?\n```\n\nBut also:\n\n```\nWhat information should the AI use?\n\nWhat information should it never use?\n\nWhat happens when there is no relevant information?\n\nWhat happens when the model doesn't finish?\n\nHow do I know the generated content is acceptable?\n```\n\nThe model is only one part of the feature.\n\nThe rest is application engineering.\n\nThe biggest thing I learned wasn't about a particular model.\n\nIt was that adding AI to an existing application means dealing with a lot more than an API call:\n\nThe AI can generate a very good-looking article.\n\nI still have to ask:\n\nIs this actually what we want the application to say?\n\nFor this project, that question matters more than whether the model produced a polished paragraph.\n\nYou can see the application here:\n\nIf you're building AI into an existing application, I'd be interested to hear what surprised you after the first successful API response.", "url": "https://wpnews.pro/news/i-spent-5-on-openrouter-while-building-ai-features-for-an-ngo-app", "canonical_source": "https://dev.to/nishchaldev/i-spent-5-on-openrouter-while-building-ai-features-for-a-nextjs-app-566b", "published_at": "2026-09-03 13:01:15+00:00", "updated_at": "2026-09-03 13:25:47.337409+00:00", "lang": "en", "topics": ["artificial-intelligence", "ai-products", "ai-tools", "developer-tools", "large-language-models"], "entities": ["OpenRouter", "PSS", "MongoDB", "Next.js", "Clerk", "Cloudinary", "TanStack Query", "GPT-5-mini"], "alternates": {"html": "https://wpnews.pro/news/i-spent-5-on-openrouter-while-building-ai-features-for-an-ngo-app", "markdown": "https://wpnews.pro/news/i-spent-5-on-openrouter-while-building-ai-features-for-an-ngo-app.md", "text": "https://wpnews.pro/news/i-spent-5-on-openrouter-while-building-ai-features-for-an-ngo-app.txt", "jsonld": "https://wpnews.pro/news/i-spent-5-on-openrouter-while-building-ai-features-for-an-ngo-app.jsonld"}}