{"id":50686741,"url":"https://github.com/t1/openapi-ui-next","last_synced_at":"2026-06-08T23:32:36.071Z","repository":{"id":347319756,"uuid":"1193528439","full_name":"t1/openapi-ui-next","owner":"t1","description":"Generates static, keyboard-navigable HTML UIs from OpenAPI specifications","archived":false,"fork":false,"pushed_at":"2026-05-27T08:50:33.000Z","size":1688,"stargazers_count":4,"open_issues_count":15,"forks_count":0,"subscribers_count":0,"default_branch":"trunk","last_synced_at":"2026-05-27T10:24:25.194Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/t1.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":"2026-03-27T10:19:32.000Z","updated_at":"2026-05-12T07:01:08.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/t1/openapi-ui-next","commit_stats":null,"previous_names":["t1/openapi-ui-next"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/t1/openapi-ui-next","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/t1%2Fopenapi-ui-next","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/t1%2Fopenapi-ui-next/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/t1%2Fopenapi-ui-next/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/t1%2Fopenapi-ui-next/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/t1","download_url":"https://codeload.github.com/t1/openapi-ui-next/tar.gz/refs/heads/trunk","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/t1%2Fopenapi-ui-next/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34085321,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-08T02:00:07.615Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":[],"created_at":"2026-06-08T23:32:29.487Z","updated_at":"2026-06-08T23:32:31.087Z","avatar_url":"https://github.com/t1.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# OpenAPI UI Next\n\n[![Java CI](https://github.com/t1/openapi-ui-next/actions/workflows/maven.yml/badge.svg)](https://github.com/t1/openapi-ui-next/actions/workflows/maven.yml)\n[![Maven Central](https://img.shields.io/maven-central/v/com.github.t1/openapi-ui)](https://central.sonatype.com/artifact/com.github.t1/openapi-ui)\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n\nGenerates static, keyboard-navigable HTML UIs from OpenAPI specifications; via CLI, Maven plugin, or Quarkus extension.\n\n![OpenAPI UI Next: light](docs/screenshots/hero.png#gh-light-mode-only)\n![OpenAPI UI Next: dark](docs/screenshots/hero-dark.png#gh-dark-mode-only)\n\n## Why?\n\nWhen Swagger came out, I loved it! Esp. the \"Try it out\" was a real game changer. But APIs keep getting bigger and\nmore complex, yet Swagger didn't grow alongside UX-wise. I absolutely need to be able to quickly navigate APIs with the\nkeyboard and have not only a nice-looking, but a clear and poweruser-oriented view on the API.\n\nIn contrast, Swagger tends to show everything at once: `curl` commands you didn't ask for, response schemas that look\njust like actual responses, and deeply nested sections that bury the information you need, while schema objects are\ncluttered at the end. So I often find myself scrolling up and down (with the mouse!), carefully reading where I am,\nand copying ids from here to there and back. _OpenAPI UI Next_ keeps the UI clean by showing details on demand: schema\ndocumentation, response types, code snippets, etc. it's there when you want them, but hidden when you don't.\n\nWith big schemas, performance is also an issue: The OpenAPI UI tools I know (Swagger UI, Redoc (even the generated\nvariant), Rapidoc) are slow by design: they are JavaScript-heavy SPAs that parse the spec at runtime in the browser.\nThis means slow initial loads on large specs. _OpenAPI UI Next_ takes a different approach: it generates plain HTML +\nCSS at build time. The result is a set of static files that can be served from any web server or embedded in any\nbackend, so they load instantly. The dynamic UX is provided mainly by HTMX, e.g. loading method fragments on click.\n\n\u003e This is also my playground for learning how to vibe-code at the Harness Engineering level.\n\n## Key Features\n\n**Navigation \u0026 Layout**\n\n- Path-based or tag-based tree views with method badges\n- Method tabs for switching operations on the same path\n- Keyboard navigation: cursor keys for spacial navigation in addition to Tab/Shift+Tab\n- Pin values, so you don't have to repeat them everywhere, quickly with Ctrl+P (Alt on Linux and Windows);\n- URL hash navigation: bookmarkable deep links (`#pets/GET`, `#[billing]invoices/GET`)\n- Responsive layout (desktop: side-by-side; mobile: stacked)\n- Automatic dark mode support (uses system setting)\n\n\u003cdetails\u003e\n\u003csummary\u003eTag-based tree view\u003c/summary\u003e\n\n![Tag view: light](docs/screenshots/tag-view.png#gh-light-mode-only)\n![Tag view: dark](docs/screenshots/tag-view-dark.png#gh-dark-mode-only)\n\u003c/details\u003e\n\n**API Documentation**\n\n- Operation summary, description, deprecated badge, tags, external docs\n- Parameter inputs with type (path/query/header) and required badges\n- Request body editor with JSON skeleton and schema documentation\n- Response schema with status code tabs, property types, required markers, and examples\n- Collapsible nested object and array properties in schema views\n- `x-links` extension for array item links: when a response embeds an array of sub-resources\n  (e.g., a pet's visits), `x-links` lets you declare per-item links using `[*]` as an array\n  wildcard in the parameter expression (e.g., `$response.body#/visits[*]/id`). These render\n  as clickable badges on each array element in the response body, and as link rows in the\n  schema view: same visual treatment as standard OpenAPI Links.\n- Accept header select for multi-content-type endpoints\n- Boolean parameters rendered as checkboxes (two-state: omit or send `true`; explicitly\n  sending `false` is not supported -- a three-state control would add UX complexity for a\n  rare need, since most boolean query params are opt-in flags with a `false` default)\n\n\u003cdetails\u003e\n\u003csummary\u003eParameter inputs\u003c/summary\u003e\n\n![Parameters filled: light](docs/screenshots/params-filled.png#gh-light-mode-only)\n![Parameters filled: dark](docs/screenshots/params-filled-dark.png#gh-dark-mode-only)\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eResponse schema tabs\u003c/summary\u003e\n\n![Response schema tabs: light](docs/screenshots/response-schema-tabs.png#gh-light-mode-only)\n![Response schema tabs: dark](docs/screenshots/response-schema-tabs-dark.png#gh-dark-mode-only)\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eNested schema expanded\u003c/summary\u003e\n\n![Nested schema expanded: light](docs/screenshots/nested-schema-expanded.png#gh-light-mode-only)\n![Nested schema expanded: dark](docs/screenshots/nested-schema-expanded-dark.png#gh-dark-mode-only)\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003ex-links for array items\u003c/summary\u003e\n\nStandard OpenAPI Links can't express \"for each item in an array, link to its detail operation\"\nbecause JSON Pointer has no wildcard syntax. The `x-links` extension uses the same Link Object\nstructure but supports `[*]` in body expressions:\n\n```yaml\nresponses:\n  200:\n    links:\n      GetOwner:\n        operationId: getOwner\n        parameters:\n          ownerId: $response.body#/owner/id\n    x-links:\n      GetVisit:\n        operationId: getVisit\n        parameters:\n          visitId: $response.body#/visits[*]/id\n```\n\nAfter \"Try it out\", each visit's `id` in the response body gets a clickable `→ GetVisit` badge\nthat navigates to the target operation and fills in the parameter. Multiple `[*]` segments are\nsupported for nested arrays (e.g., `$response.body#/visits[*]/treatments[*]/id`).\n\u003c/details\u003e\n\n**Request Headers**\n\n- Custom headers with globe toggle: add headers per operation or make them global with one click\n  - Operation-specific by default (gray globe icon)\n  - Click globe to make header global across all operations (blue globe icon)\n  - Global headers automatically sync values across operations\n  - Pin headers to persist across page reloads\n\n**Try It Out**\n\n- Three modes: Try (fetch), httpie, curl; switch at any time with Ctrl+1/2/3 (Alt on Linux and Windows)\n- Response rendering with syntax highlighting (JSON, HTML, XML, YAML)\n- Collapsible response headers display with spec documentation: documented headers show descriptions,\n  deprecated indicators, and required-but-missing warnings; undocumented headers are hidden behind\n  a \"Show all\" button when documented headers exist; auto-expands on first send when documented headers are present\n\n\u003cdetails\u003e\n\u003csummary\u003eTry mode with JSON response\u003c/summary\u003e\n\n![Try mode: light](docs/screenshots/try-mode-json-response.png#gh-light-mode-only)\n![Try mode: dark](docs/screenshots/try-mode-json-response-dark.png#gh-dark-mode-only)\n\u003c/details\u003e\n\n## Usage\n\n### CLI\n\n```bash\njbang openapi-ui@t1/openapi-ui-next \u003cspec-file\u003e \u003coutput-dir\u003e\n```\n\nOr install it as a command:\n\n```bash\njbang app install openapi-ui@t1/openapi-ui-next\nopenapi-ui \u003cspec-file\u003e \u003coutput-dir\u003e\n```\n\nOr build and run it locally:\n\n```bash\nmvn -pl cli package\n./cli/target/openapi-ui \u003cspec-file\u003e \u003coutput-dir\u003e\n```\n\nUse `--verbose` for debug logging and full stack traces on errors.\n\nTo preview the result locally:\n\n```bash\npython3 -m http.server 8000 -d \u003coutput-dir\u003e\n```\n\nThen open http://localhost:8000.\n\n### Maven Plugin\n\n```xml\n\n\u003cplugin\u003e\n    \u003cgroupId\u003ecom.github.t1\u003c/groupId\u003e\n    \u003cartifactId\u003eopenapi-ui-maven-plugin\u003c/artifactId\u003e\n    \u003cversion\u003e${project.version}\u003c/version\u003e\n    \u003cexecutions\u003e\n        \u003cexecution\u003e\n            \u003cphase\u003eprocess-classes\u003c/phase\u003e\n            \u003cgoals\u003e\n                \u003cgoal\u003egenerate\u003c/goal\u003e\n            \u003c/goals\u003e\n            \u003cconfiguration\u003e\n                \u003cspecFile\u003e${project.build.directory}/generated/openapi.yaml\u003c/specFile\u003e\n                \u003coutputDirectory\u003e${project.build.directory}/classes/META-INF/resources/openapi-ui\u003c/outputDirectory\u003e\n            \u003c/configuration\u003e\n        \u003c/execution\u003e\n    \u003c/executions\u003e\n\u003c/plugin\u003e\n```\n\n### Demo App\n\nA Quarkus petstore app that uses the Quarkus extension to generate and serve the UI,\neven in dev mode, so changes to the app source immediately show up in the UI.\n\nBuild only the demo app and necessary modules:\n\n```bash\nmvn -DskipTests -pl core,demo -am\n```\n\nRun app:\n\n```bash\njava -jar demo/target/quarkus-app/quarkus-run.jar\n```\n\nOr dev mode (in the `demo` dir):\n\n```bash\nmvn quarkus:dev\n```\n\nThen open http://localhost:8080/openapi-ui/index.html.\n\n## Modules\n\n| Module              | Description                                                  |\n|---------------------|--------------------------------------------------------------|\n| `core`              | Generator library: parses specs and produces HTML + CSS + JS |\n| `cli`               | Command-line tool: executable fat jar with shell header      |\n| `maven-plugin`      | Maven plugin: integrates generation into build pipelines     |\n| `quarkus-extension` | Quarkus extension: dev-mode integration with auto-refresh    |\n| `demo`              | Quarkus petstore app: exercises the plugin end-to-end        |\n\n## Tech Stack\n\n**Build-time** (generator + tests):\n\n- Java 21+, Maven\n- [swagger-parser](https://github.com/swagger-api/swagger-parser) for OpenAPI parsing\n- [bulma-java](https://github.com/t1/bulma-java) for HTML generation\n- [Playwright](https://playwright.dev/) for browser integration tests\n\n**Runtime** (generated output, served as static files):\n\n- [Bulma](https://bulma.io/) CSS framework\n- [HTMX](https://htmx.org/) for dynamic fragment loading\n- [highlight.js](https://highlightjs.org/) for response syntax highlighting\n- [Font Awesome](https://fontawesome.com/) for icons\n\n## Example Output (Petstore)\n\n```\noutput/\n├── index.html          # Layout + keyboard navigation\n├── path-tree.html      # Path-based tree view\n├── tag-tree.html       # Tag-based tree view\n├── openapi-ui.css\n├── vendor/             # Third-party libraries (from webjars)\n│   ├── bulma.min.css\n│   ├── htmx.min.js\n│   ├── highlight.min.js\n│   ├── css/\n│   │   ├── fontawesome.min.css  # Font Awesome core\n│   │   └── solid.min.css       # Font Awesome solid icons\n│   └── webfonts/\n│       └── fa-solid-900.woff2\n├── owners/\n│   ├── index.html       # Path fragment: tab bar + first method\n│   ├── GET.html         # Fragment for GET /owners\n│   └── {id}/\n│       ├── index.html\n│       ├── GET.html     # Fragment for GET /owners/{id}\n│       └── pets/\n│           ├── index.html\n│           └── GET.html # Fragment for GET /owners/{ownerId}/pets\n└── pets/\n    ├── index.html       # Path fragment: tab bar + first method\n    ├── GET.html         # Fragment for GET /pets\n    ├── POST.html        # Fragment for POST /pets\n    └── {id}/\n        ├── index.html\n        ├── GET.html     # Fragment for GET /pets/{id}\n        ├── DELETE.html  # Fragment for DELETE /pets/{id}\n        └── visits/\n            ├── index.html\n            ├── GET.html     # Fragment for GET /pets/{petId}/visits\n            └── {visitId}/\n                ├── index.html\n                └── GET.html # Fragment for GET /pets/{petId}/visits/{visitId}\n```\n\n## Release Notes\n\nWe use [semantic versioning](https://semver.org), so 1.0.x versions are pure bugfix releases\n(expept for 1.0.3, which was a mistake ;-).\n\n### 1.0 - 2026-04-04\n\nInitial MVP release\n\n### 1.1 - 2026-04-10\n\n- **Response links**: schema view shows link annotations with click-to-navigate;\n  response bodies get named badges that fill parameters in the target operation;\n  `x-links` extension for array items; keyboard-focusable\n  ([#4](https://github.com/t1/openapi-ui-next/issues/4))\n- **httpie defaults**: `GET` default method, `http://localhost` default base URL\n  ([#5](https://github.com/t1/openapi-ui-next/issues/5))\n- **Quarkus extension**: dev-mode integration: change JAX-RS code, browser auto-refreshes UI\n  ([#26](https://github.com/t1/openapi-ui-next/issues/26))\n- **Bug fixes**:\n    - request body toggle without schema ([#6](https://github.com/t1/openapi-ui-next/issues/6))\n    - textarea auto-grow ([#8](https://github.com/t1/openapi-ui-next/issues/8))\n    - keyboard\n      navigation ([#21](https://github.com/t1/openapi-ui-next/issues/21), [#23](https://github.com/t1/openapi-ui-next/issues/23))\n\n### 1.2 - 2026-04-16\n\n- **Security schemes**: apiKey, http bearer, and info-only rows for browser-handled\n  auth ([#34](https://github.com/t1/openapi-ui-next/issues/34), [#35](https://github.com/t1/openapi-ui-next/issues/35), [#36](https://github.com/t1/openapi-ui-next/issues/36), [#37](https://github.com/t1/openapi-ui-next/issues/37))\n- **Server selector**: dropdown in the header with server items, template variable presets, custom URLs,\n  per-operation overrides, and localStorage\n  persistence ([#39](https://github.com/t1/openapi-ui-next/issues/39), [#41](https://github.com/t1/openapi-ui-next/issues/41), [#42](https://github.com/t1/openapi-ui-next/issues/42), [#44](https://github.com/t1/openapi-ui-next/issues/44), [#45](https://github.com/t1/openapi-ui-next/issues/45), [#46](https://github.com/t1/openapi-ui-next/issues/46))\n- **Cross-origin security**: auto-show/hide security inputs based on server origin\n  ([#43](https://github.com/t1/openapi-ui-next/issues/43))\n- **Tag filtering**: pill-based filter panel with keyboard navigation and localStorage\n  persistence ([#47](https://github.com/t1/openapi-ui-next/issues/47), [#48](https://github.com/t1/openapi-ui-next/issues/48), [#49](https://github.com/t1/openapi-ui-next/issues/49))\n- **Code generators**: scalable mode selector with 10 generators — curl, HTTPie, JS fetch,\n  Java HttpClient, JAX-RS, Python requests, Go net/http, MP Rest Client, Spring WebClient,\n  Spring\n  RestTemplate ([#50](https://github.com/t1/openapi-ui-next/issues/50), [#51](https://github.com/t1/openapi-ui-next/issues/51), [#52](https://github.com/t1/openapi-ui-next/issues/52), [#53](https://github.com/t1/openapi-ui-next/issues/53), [#54](https://github.com/t1/openapi-ui-next/issues/54), [#55](https://github.com/t1/openapi-ui-next/issues/55))\n- **Form-encoded request bodies**: individual input fields for\n  `application/x-www-form-urlencoded` ([#7](https://github.com/t1/openapi-ui-next/issues/7))\n- **Globe toggle for custom headers**: in-place controls to make headers operation-specific or global\n  across all operations with visual state indicators (gray/blue badge)\n- **Bug fixes**:\n    - request body schema tree not showing when using `$ref`\n    - double-submit on Send button\n    - Enter/Space on custom header delete\n    - focus restore races after HTMX swaps\n\n## Contributing\n\nEven just using the project and leaving a star helps a lot -- it shows there's interest\nand keeps the momentum going. Bug reports and feature ideas are equally welcome.\n\n### Prerequisites\n\n- Java 21+\n- Maven 3.9+\n\n### Build\n\njust:\n\n```bash\nmvn\n```\n\nBrowser tests run in Chromium by default. To test with WebKit (Safari) or Firefox:\n\n```bash\nmvn test -pl core -Dplaywright.browser=webkit\nmvn test -pl core -Dplaywright.browser=firefox\n```\n\n## License\n\n[Apache License 2.0](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ft1%2Fopenapi-ui-next","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ft1%2Fopenapi-ui-next","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ft1%2Fopenapi-ui-next/lists"}