{"id":30770508,"url":"https://github.com/sanand0/bootstrap-llm-provider","last_synced_at":"2026-02-14T10:03:24.514Z","repository":{"id":305486945,"uuid":"1023035455","full_name":"sanand0/bootstrap-llm-provider","owner":"sanand0","description":"Let users pick their OpenAI compatible API provider (e.g. OpenRouter, Ollama) via a Bootstrap modal","archived":false,"fork":false,"pushed_at":"2025-09-25T16:08:39.000Z","size":37,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-14T03:14:06.664Z","etag":null,"topics":["library","llm"],"latest_commit_sha":null,"homepage":"https://sanand0.github.io/bootstrap-llm-provider/","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sanand0.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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-07-20T11:44:47.000Z","updated_at":"2025-09-25T16:08:43.000Z","dependencies_parsed_at":"2025-07-20T12:19:19.243Z","dependency_job_id":"e3b46c37-9f5c-4333-9820-41e76a6fb549","html_url":"https://github.com/sanand0/bootstrap-llm-provider","commit_stats":null,"previous_names":["sanand0/bootstrap-llm-provider"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/sanand0/bootstrap-llm-provider","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sanand0%2Fbootstrap-llm-provider","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sanand0%2Fbootstrap-llm-provider/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sanand0%2Fbootstrap-llm-provider/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sanand0%2Fbootstrap-llm-provider/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sanand0","download_url":"https://codeload.github.com/sanand0/bootstrap-llm-provider/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sanand0%2Fbootstrap-llm-provider/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29442334,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-14T07:24:13.446Z","status":"ssl_error","status_checked_at":"2026-02-14T07:23:58.969Z","response_time":53,"last_error":"SSL_read: 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":["library","llm"],"created_at":"2025-09-04T23:08:48.047Z","updated_at":"2026-02-14T10:03:24.509Z","avatar_url":"https://github.com/sanand0.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Bootstrap LLM Provider\n\n[![npm version](https://img.shields.io/npm/v/bootstrap-llm-provider.svg)](https://www.npmjs.com/package/bootstrap-llm-provider)\n[![Bootstrap](https://img.shields.io/badge/Framework-Bootstrap%205-7952b3)](https://getbootstrap.com/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![bundle size](https://img.shields.io/bundlephobia/minzip/bootstrap-llm-provider)](https://bundlephobia.com/package/bootstrap-llm-provider)\n\nLet users pick their OpenAI compatible API provider (e.g. OpenRouter, Ollama) via a Bootstrap modal\n\n## Installation\n\nAdd this to your script:\n\n```js\nimport { geminiConfig, openaiConfig } from \"bootstrap-llm-provider\";\n```\n\nTo use via CDN, add this to your HTML file:\n\n```html\n\u003cscript type=\"importmap\"\u003e\n  {\n    \"imports\": {\n      \"bootstrap-llm-provider\": \"https://cdn.jsdelivr.net/npm/bootstrap-llm-provider@1\"\n    }\n  }\n\u003c/script\u003e\n```\n\nTo use locally, install via `npm`:\n\n```bash\nnpm install bootstrap-llm-provider\n```\n\n... and add this to your HTML file:\n\n```html\n\u003cscript type=\"importmap\"\u003e\n  {\n    \"imports\": {\n      \"bootstrap-llm-provider\": \"./node_modules/bootstrap-llm-provider/dist/bootstrap-llm-provider.js\"\n    }\n  }\n\u003c/script\u003e\n```\n\n## Usage\n\n```js\nimport { geminiConfig, openaiConfig } from \"https://cdn.jsdelivr.net/npm/bootstrap-llm-provider@1.2\";\n\n// Basic Config - Opens a model and asks user for provider details\nconst { baseUrl, apiKey, models } = await openaiConfig();\n\n// API key is optional if your provider doesn't require one\n\n// Always Show Modal - even if user has provided information before\nconst { baseUrl, apiKey, models } = await openaiConfig({ show: true });\n\n// Custom Base URLs (datalist)\nconst { baseUrl, apiKey, models } = await openaiConfig({\n  defaultBaseUrls: [\"https://api.openai.com/v1\", \"https://openrouter.com/api/v1\"],\n});\n\n// Base URL Options (select)\nconst { baseUrl, apiKey, models } = await openaiConfig({\n  baseUrls: [\n    { url: \"https://api.openai.com/v1\", name: \"OpenAI\" },\n    { url: \"https://openrouter.com/api/v1\", name: \"OpenRouter\" },\n  ],\n  // baseUrls overrides defaultBaseUrls\n});\n\n// Custom Storage - store in sessionStorage.llmProvider\nconst { baseUrl, apiKey, models } = await openaiConfig({ storage: sessionStorage, key: \"llmProvider\" });\n\n// Custom Labels\nconst { baseUrl, apiKey, models } = await openaiConfig({\n  title: \"Pick a provider\",\n  baseUrlLabel: \"Your URL\",\n  apiKeyLabel: \"Your Key\",\n  buttonLabel: \"Save\",\n});\n\n// Help HTML\nconst { baseUrl, apiKey, models } = await openaiConfig({\n  help: '\u003cdiv class=\"alert alert-info\"\u003eGet your key from \u003ca href=\"/\"\u003ehere\u003c/a\u003e\u003c/div\u003e',\n  show: true,\n});\n\n// Gemini Config - defaults to Google endpoint + three proxy hosts\nconst gemini = await geminiConfig();\nconsole.log(gemini.baseUrl, gemini.apiKey, gemini.models);\n\n// Gemini Proxy example (forces proxy base URL and opens modal)\nconst proxyResult = await geminiConfig({\n  defaultBaseUrls: [\"https://aipipe.org/geminiv1beta\"],\n  show: true,\n});\n// =\u003e { baseUrl: \"https://aipipe.org/geminiv1beta\", apiKey: \"...\", models: [\"gemini-1.5-flash\", ...] }\n```\n\n[](demo.html \":include\")\n\n## API\n\n```js\nasync function openaiConfig({\n  storage: localStorage,                          // where to store, e.g. sessionStorage\n  key: \"bootstrapLLMProvider_openaiConfig\",       // key name for storage\n  defaultBaseUrls: [\"https://api.openai.com/v1\"], // array of URL strings for user to pick from\n  baseUrls: undefined,                            // array of { url, name } objects\n  show: false,                                    // true will force prompt even if config exists\n  help: \"\",                                       // HTML rendered at top of modal\n  title: \"OpenAI API Configuration\",              // modal dialog title\n  baseUrlLabel: \"API Base URL\",                   // base URL label\n  apiKeyLabel: \"API Key\",                         // api key label\n  buttonLabel: \"Save \u0026 Test\",                     // submit button label\n})\n// Returns: { baseUrl, apiKey, models: string[] }\n```\n\n```js\nasync function geminiConfig({\n  storage: localStorage,\n  key: \"bootstrapLLMProvider_geminiConfig\",\n  defaultBaseUrls: [\n    \"https://generativelanguage.googleapis.com/v1beta\",\n    \"https://aipipe.org/geminiv1beta\",\n    \"https://llmfoundry.straive.com/gemini/v1beta\",\n    \"https://llmfoundry.straivedemo.com/gemini/v1beta\",\n  ],\n  baseUrls: undefined,\n  show: false,\n  help: \"\",\n  title: \"Google Gemini API Configuration\",\n  baseUrlLabel: \"Gemini API Base URL\",\n  apiKeyLabel: \"API Key or Token\",\n  buttonLabel: \"Save \u0026 Test\",\n})\n// Returns: { baseUrl, apiKey, models: string[] }\n```\n\n- `geminiConfig` auto-detects Google's native host vs. proxies and sends the right auth headers:\n  - `https://generativelanguage.googleapis.com` receives the `x-goog-api-key`\n  - Other\n  - the provided proxy URLs receive `Authorization: Bearer \u003ctoken\u003e`\n- Responses from `{ models: [...] }` or `{ data: [...] }` are normalized and return bare model names (with `models/` stripped)\n\n- If there's no valid config, or `show` is true, it displays a Bootstrap modal with:\n  - Base URL input with datalist of `defaultBaseUrls`, or a select of `baseUrls`\n  - API key input, may be empty, prefilled from storage if present\n  - `help` HTML inserted at the top if provided\n  - On submit, it:\n    1. Fetches `${baseUrl}/models` using the API key\n    2. On success, save `{ baseUrl, apiKey }` to storage under `key`; return `{ baseUrl, apiKey, models }`\n    3. On failure, throws an Error\n  - `baseUrls` overrides `defaultBaseUrls` if both are provided\n- If config exists, it skips the prompt, fetches models and returns\n\n## Development\n\n```bash\ngit clone https://github.com/sanand0/bootstrap-llm-provider.git\ncd bootstrap-llm-provider\n\nnpm install\nnpm run lint \u0026\u0026 npm run build \u0026\u0026 npm test\n\nnpm publish\ngit commit . -m\"$COMMIT_MSG\"; git tag $VERSION; git push --follow-tags\n```\n\n## Design decisions\n\n- Return `baseUrl` but retain `baseURL` for compatibility and popularity. [ChatGPT](https://chatgpt.com/share/68d55d4a-92fc-800c-8ff3-db5ff423797e)\n\n## Release notes\n\n- [1.4.0](https://npmjs.com/package/bootstrap-llm-provider/v/1.4.0): 25 Sep 2025. Add `geminiConfig` for Gemini endpoints\n- [1.3.1](https://npmjs.com/package/bootstrap-llm-provider/v/1.3.1): 31 Jul 2025. Standardized package.json \u0026 README.md\n- [1.2.0](https://npmjs.com/package/bootstrap-llm-provider/v/1.2.0): 28 Jul 2025. Optional `help` HTML parameter\n- [1.1.0](https://npmjs.com/package/bootstrap-llm-provider/v/1.1.0): 25 Jul 2025. Optional API key, `baseUrls` select, `baseUrl` renamed (returns `baseURL` for compatibility)\n- [1.0.0](https://npmjs.com/package/bootstrap-llm-provider/v/1.0.0): 20 Jul 2025. Initial release\n\n## License\n\n[MIT](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsanand0%2Fbootstrap-llm-provider","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsanand0%2Fbootstrap-llm-provider","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsanand0%2Fbootstrap-llm-provider/lists"}