Last Updated: 2026-02-24 Version: 5.32.0 (in development) Purpose: Comprehensive guide for AI assistants working with the Swagger UI codebase
- Repository Overview
- Project Architecture
- Development Setup
- Build System
- Testing Infrastructure
- Code Style & Conventions
- Git Workflow
- Plugin Architecture
- Key Files & Directories
- Common Workflows
- Important Guidelines
Swagger UI is a tool that allows developers to visualize and interact with API resources without having implementation logic in place. It's automatically generated from OpenAPI (formerly Swagger) Specification documents.
This repository publishes three different npm packages:
-
swagger-ui (main package)
- Traditional npm module for single-page applications
- Entry:
dist/swagger-ui.js - ES Module:
dist/swagger-ui-es-bundle-core.js - Includes dependency resolution via Webpack/Browserify
-
swagger-ui-dist (distribution package)
- Dependency-free module for server-side projects
- Published separately via GitHub workflow
- Template location:
swagger-ui-dist-package/
-
swagger-ui-react (React component)
- React wrapper component
- Location:
flavors/swagger-ui-react/ - Uses React hooks
- Released separately via GitHub workflow
- Current Support: OpenAPI 2.0, 3.0.x, 3.1.x
- Latest Version: v5.31.0 (supports up to OpenAPI 3.1.2)
Apache 2.0 - See LICENSE and NOTICE files for details.
Core Framework:
- React 18 (>=16.8.0 <20) - UI components
- Redux 5.0.1 - State management
- Redux Immutable 4.0.0 - Immutable state
- Immutable.js 3.x - Immutable data structures
- React Redux 9.2.0 - React-Redux bindings
API & Schema Processing:
- swagger-client 3.36.0 - OpenAPI client
- js-yaml 4.1.1 - YAML parsing
- remarkable 2.0.1 - Markdown rendering
Security:
- DOMPurify 3.2.6 - HTML sanitization (CRITICAL for XSS prevention)
- serialize-error 8.1.0 - Error serialization
Build Tools:
- Webpack 5.97.1 - Module bundling
- Babel 7.26.x - JavaScript transpilation
- sass-embedded 1.86.0 - SCSS compilation
- PostCSS - CSS processing
Testing:
- Jest 29.7.0 - Unit testing
- Cypress 14.2.0 - E2E testing
- Enzyme 3.11.0 - React component testing
Development:
- ESLint 8.57.0 - JavaScript linting
- Prettier 3.5.3 - Code formatting
- Stylelint 16.19.1 - CSS linting
- Husky 9.1.7 - Git hooks
- lint-staged 15.5.0 - Pre-commit linting
Swagger UI uses a sophisticated plugin system powered by Redux. The core system (src/core/system.js) manages:
- Plugin registration and lifecycle
- Redux store creation and middleware
- State plugin combination
- Action/selector binding
- Configuration management
26 Core Plugins (in src/core/plugins/):
auth- Authentication handlingconfigs- Configuration managementdeep-linking- URL-based navigationdownload-url- Spec downloadingerr- Error handling and transformationfilter- API filteringicons- Icon componentsjson-schema-2020-12- JSON Schema 2020-12 supportjson-schema-2020-12-samples- Sample generationjson-schema-5- JSON Schema Draft 5 supportjson-schema-5-samples- Sample generation for Draft 5layout- Layout systemlogs- Loggingoas3- OpenAPI 3.0.x supportoas31- OpenAPI 3.1.x supportoas32- OpenAPI 3.2.x supporton-complete- Completion callbacksrequest-snippets- Code snippet generationsafe-render- Safe component renderingspec- Specification handlingswagger-client- API client integrationsyntax-highlighting- Code highlightingutil- Utilitiesversions- Version detectionview- View renderingview-legacy- Legacy view support
- Node.js: >=22.11.0 (Node 20.x recommended, as defined in
.nvmrc) - npm: >=10.9.0
- Git: Any version
- JDK 7+: Required for Nightwatch.js integration tests
# Clone the repository
git clone https://github.com/swagger-api/swagger-ui.git
cd swagger-ui
# Install dependencies
npm install
# Initialize Husky (optional, for git hooks)
npx husky init
# Start development server
npm run dev
# Open http://localhost:3200/The npm run dev command starts a hot-reloading Webpack dev server on port 3200.
Edit dev-helpers/dev-helper-initializer.js to change the spec URL:
// Replace
url: "https://petstore.swagger.io/v2/swagger.json",
// With
url: "./examples/your-local-api-definition.yaml",Important: Local files must be in the dev-helpers/ directory or subdirectory. Use dev-helpers/examples/ (already in .gitignore).
Three Babel environments configured in babel.config.js:
- development/production - Browser builds with
modules: "auto" - commonjs - CommonJS modules with
modules: "commonjs"for Node.js - esm - ES modules with
modules: falsefor modern bundlers
{
root: ".",
core: "./src/core"
}Defined in .browserslistrc:
[browser-production]- Production browser targets[browser-development]- Latest Chrome, Firefox, Safari[isomorphic-production]- Browser + Node targets[node-production]- Maintained Node versions[node-development]- Node 22
# Full build (stylesheets + all bundles)
npm run build
# Individual builds
npm run build:core # Core bundle (browser)
npm run build:bundle # Isomorphic bundle
npm run build:standalone # Standalone preset
npm run build:es:bundle # ES module bundle
npm run build:es:bundle:core # ES module core
npm run build-stylesheets # CSS only
# Clean build artifacts
npm run cleanswagger-ui.js- Core bundle (CommonJS)swagger-ui.css- Compiled stylesswagger-ui-bundle.js- Isomorphic bundleswagger-ui-standalone-preset.js- Standalone presetswagger-ui-es-bundle.js- ES module bundleswagger-ui-es-bundle-core.js- ES module coreoauth2-redirect.html- OAuth2 redirect page
Located in webpack/ directory:
_config-builder.js- Base configurationcore.js- Core buildbundle.js- Bundle buildstandalone.js- Standalone buildes-bundle.js- ES bundlees-bundle-core.js- ES core bundlestylesheets.js- CSS builddev.js- Development serverdev-e2e.js- E2E testing server
Configuration: config/jest/jest.unit.config.js
Environment: jsdom (simulates browser environment)
Location: test/unit/
Command:
npm run test:unitKey Features:
- 37 unit test files
- Tests for core plugins, components, system
- XSS security tests
- Silent mode enabled by default (set to
falsefor console output) - Module name mapper for SVG and standalone imports
- Transform ignore patterns for node_modules exceptions
Setup Files:
test/unit/jest-shim.js- Polyfills and shimstest/unit/setup.js- Test environment setup
Configuration: cypress.config.js
Location: test/e2e-cypress/
Base URL: http://localhost:3230/
Commands:
# Run all E2E tests
npm run cy:ci
# Interactive Cypress runner
npm run cy:dev
# Headless run
npm run cy:run
# Start servers and run tests
npm run cy:start # Starts webpack + mock APIStructure:
test/e2e-cypress/e2e/- Test specs (99 test files)test/e2e-cypress/static/- Test fixtures and documentstest/e2e-cypress/support/- Test helpers and commands
Test Categories:
a11y/**/*cy.js- Accessibility testssecurity/**/*cy.js- Security testsbugs/**/*cy.js- Bug regression testsfeatures/**/*cy.js- Feature tests
Mock API Server:
npm run cy:mock-api # JSON Server on port 3204Configuration: config/jest/jest.artifact.config.js
Purpose: Verify build artifacts export correctly
Command:
npm run test:artifactnpm test # Runs: lint-errors + test:unit + cy:ciGitHub Actions Workflow: .github/workflows/nodejs.yml
Two Jobs:
- build - Lint, unit tests, build, artifact tests
- e2e-tests - Cypress tests (matrix strategy with 3 containers)
Branches: master, next
File: .eslintrc.js
Parser: @babel/eslint-parser
Key Rules:
semi: [2, "never"]- No semicolonsquotes: [2, "double"]- Double quotes (allow template literals)no-unused-vars: 2- Error on unused variablescamelcase: ["error"]- Enforce camelCase (with exceptions for UNSAFE_, request generators, etc.)no-console: [2, {allow: ["warn", "error"]}]- Onlyconsole.warnandconsole.errorallowedreact/jsx-no-bind: 1- Warning for JSX bindreact/jsx-filename-extension: 2- JSX only in.jsxfilesimport/no-extraneous-dependencies: 2- Error on extraneous dependencies
Extends:
eslint:recommendedplugin:react/recommendedplugin:prettier/recommended
File: .prettierrc.yaml
Settings:
semi: false # No semicolons
trailingComma: es5 # ES5 trailing commas
endOfLine: lf # Unix line endings
requirePragma: true # Require @prettier pragma
insertPragma: true # Insert @prettier pragmaIMPORTANT: Prettier requires @prettier pragma comment at the top of files:
/**
* @prettier
*/File: stylelint.config.js
Custom Syntax: postcss-scss
Rules:
- Uses
stylelint-prettierplugin - Prettier integration without pragma requirement
Husky: .husky/pre-commit runs npx lint-staged
Lint-staged Configuration: .lintstagedrc
{
"*.{js,jsx}": ["eslint --max-warnings 0"],
"*.scss": ["stylelint '**/*.scss'"]
}Critical: All staged JS/JSX/SCSS files are linted with zero warnings tolerance.
Components:
- Location:
src/core/components/ - Extension:
.jsx(React components) - Format: PascalCase for component names
Styles:
- Location:
src/style/ - Extension:
.scss - Format: SCSS with PostCSS processing
- Dark mode:
_dark-mode.scss
Tests:
- Unit:
test/unit/(mirrors source structure) - E2E:
test/e2e-cypress/e2e/ - Naming:
*.test.js,*.spec.js,*.cy.js(Cypress)
Main Branches:
master- Production releasesnext- Next version development
Feature Branches:
- Should branch from
masterornext - Use descriptive names
Format: Conventional Commits (enforced by commitlint)
Structure:
<type>(<scope>): <subject>
<body>
<footer>
Types:
feat- New featurefix- Bug fixdocs- Documentation changesstyle- Code style changes (formatting)refactor- Code refactoringtest- Test additions/changeschore- Build/tooling changesperf- Performance improvements
Example:
feat(oas3): add support for OpenAPI 3.1.1 callbacks
Implement callback rendering for OAS 3.1.1 specifications
with proper schema resolution and example generation.
Fixes #12345
Template: .github/pull_request_template.md
Required Sections:
- Description - Detailed change description
- Motivation and Context - Why the change is needed
- How Has This Been Tested? - Manual testing details
- Screenshots - If UI changes
Checklist:
- Code type (no code/dependencies/bug fix/improvement/feature)
- Breaking changes identification
- Documentation updates
- Test coverage
- All tests passing
CI Checks:
- ESLint (error-only mode)
- Unit tests (Jest)
- Build verification
- Artifact tests
- E2E tests (Cypress)
Tool: release-it with conventional-changelog
Command:
npm run automated-releaseWorkflows:
.github/workflows/release-swagger-ui.yml.github/workflows/release-swagger-ui-dist.yml.github/workflows/release-swagger-ui-react.yml.github/workflows/release-swagger-ui-packagist.yml
The plugin system is the heart of Swagger UI. It uses Redux for state management with a custom plugin registration system.
Each plugin is a JavaScript object/function that returns:
{
statePlugins: {
[pluginName]: {
actions: {}, // Redux actions
reducers: {}, // Redux reducers
selectors: {}, // Reselect selectors
wrapActions: {}, // Action middleware
wrapSelectors: {} // Selector middleware
}
},
components: {}, // React components
fn: {}, // Utility functions
rootInjects: {}, // Root-level injections
afterLoad: Function // Lifecycle hook
}Core Plugins: src/core/plugins/
Each plugin has:
index.js- Main exportactions.js- Redux actionsreducers.js- Redux reducersselectors.js- State selectorswrap-actions.js- Action middlewarewrap-selectors.js- Selector middleware- Component files (
.jsx)
See documentation: docs/customization/plugin-api.md
IMPORTANT: Avoid cross-plugin imports to maintain plugin independence and modularity.
Pattern to Follow:
- Each plugin should be self-contained with its own components, utilities, and functions
- When OAS version plugins (oas3, oas31, oas32) need similar functionality, create self-contained copies within each plugin
- Wrap components should import from their own plugin's components, not from other plugins
Example Structure:
src/core/plugins/oas32/
├── json-schema-2020-12-extensions/
│ ├── components/ # Self-contained components
│ │ └── keywords/
│ │ ├── Description.jsx
│ │ └── Properties.jsx
│ ├── wrap-components/ # Wrappers for components
│ │ └── keywords/
│ │ ├── Description.jsx # Imports from ../../components/
│ │ └── Properties.jsx # Not from ../../../../oas31/
│ └── fn.js # Self-contained utilities
Why This Matters:
- Prevents tight coupling between plugins
- Makes plugins easier to test in isolation
- Allows independent versioning and updates
- Reduces risk of breaking changes across plugins
- Improves code maintainability
Exceptions:
- Shared core utilities in
src/core/utils/are acceptable - System-level functions in
src/core/system.jsare acceptable - Base components in
src/core/components/are acceptable
Base Preset: src/core/presets/base.js
Standalone Preset: src/standalone/presets/standalone.js
Presets are collections of plugins bundled together for specific use cases.
src/
├── core/
│ ├── system.js # Plugin system & Redux store
│ ├── components/ # 59 React components
│ ├── plugins/ # 26 core plugins
│ ├── presets/ # Preset configurations
│ ├── utils/ # Utility functions
│ └── config/ # Configuration system
├── standalone/
│ ├── plugins/ # TopBar, StandaloneLayout
│ └── presets/ # Standalone preset
├── style/ # SCSS stylesheets
│ ├── _dark-mode.scss # Dark mode styles
│ └── main.scss # Main stylesheet entry
└── index.js # Main package entry
.
├── package.json # Dependencies & scripts
├── babel.config.js # Babel configuration
├── .eslintrc.js # ESLint rules
├── .prettierrc.yaml # Prettier settings
├── stylelint.config.js # Stylelint rules
├── .browserslistrc # Browser targets
├── .nvmrc # Node version (20.x)
├── .lintstagedrc # Pre-commit linting
└── cypress.config.js # Cypress E2E config
webpack/
├── _config-builder.js # Base Webpack config
├── core.js # Core build
├── bundle.js # Bundle build
├── standalone.js # Standalone build
├── es-bundle.js # ES bundle build
├── es-bundle-core.js # ES core bundle
├── stylesheets.js # CSS compilation
├── dev.js # Dev server
└── dev-e2e.js # E2E dev server
config/jest/
├── jest.unit.config.js # Unit test config
└── jest.artifact.config.js # Artifact test config
docs/
├── usage/
│ ├── installation.md
│ ├── configuration.md
│ ├── cors.md
│ ├── oauth2.md
│ ├── deep-linking.md
│ ├── version-detection.md
│ └── limitations.md
├── customization/
│ ├── overview.md
│ ├── plugin-api.md
│ └── custom-layout.md
└── development/
├── setting-up.md
└── scripts.md
test/
├── unit/ # Jest unit tests (37 files)
│ ├── setup.js # Test environment setup
│ └── jest-shim.js # Polyfills
├── e2e-cypress/ # Cypress E2E tests (99 files)
│ ├── e2e/ # Test specs
│ ├── static/ # Fixtures
│ └── support/ # Helpers
└── e2e-selenium/ # Legacy Selenium tests
flavors/
└── swagger-ui-react/ # React component wrapper
swagger-ui-dist-package/ # Template for dist package
dist/ # Build output (generated)
├── swagger-ui.js
├── swagger-ui.css
├── swagger-ui-bundle.js
├── swagger-ui-standalone-preset.js
├── swagger-ui-es-bundle.js
├── swagger-ui-es-bundle-core.js
└── oauth2-redirect.html
-
Read before modifying:
# ALWAYS read files before editing them # Understand the existing code structure
-
Follow the style guide:
- Use double quotes
- No semicolons
- Add
@prettierpragma to new files - Use
.jsxextension for React components
-
Run linters:
npm run lint # Check for errors and warnings npm run lint-fix # Auto-fix JavaScript issues npm run lint-styles # Check SCSS npm run lint-styles-fix # Auto-fix SCSS
-
Test your changes:
npm run test:unit # Run unit tests npm run cy:dev # Interactive E2E testing npm run build # Verify build works npm run test:artifact # Verify artifacts
- Create component in
src/core/components/or appropriate plugin directory - Use
.jsxextension - Add
@prettierpragma - Follow React best practices (functional components, hooks)
- Add PropTypes validation
- Create corresponding test in
test/unit/ - Export from plugin's
index.jsif needed
- Create directory in
src/core/plugins/[plugin-name]/ - Create
index.jswith plugin structure - Add actions, reducers, selectors as needed
- Register plugin in preset (e.g.,
src/core/presets/base.js) - Add tests in
test/unit/core/plugins/[plugin-name]/ - Document the plugin
-
Reproduce the bug:
- Add a failing test in
test/unit/ortest/e2e-cypress/ - Document reproduction steps
- Add a failing test in
-
Fix the issue:
- Make minimal changes to fix the bug
- Avoid refactoring unless necessary
- Ensure the test now passes
-
Verify:
npm run test:unit npm run build npm run test:artifact
-
Create PR:
- Reference the issue number
- Include before/after behavior
- Add screenshots if UI-related
-
Plan the feature:
- Review existing architecture
- Identify affected plugins/components
- Consider OpenAPI spec compatibility
-
Implement:
- Follow plugin architecture patterns
- Add configuration options if needed
- Update presets if necessary
-
Test thoroughly:
- Unit tests for logic
- Component tests for UI
- E2E tests for integration
- Test with various OpenAPI specs
-
Document:
- Update
docs/if user-facing - Add JSDoc comments for APIs
- Update README if needed
- Update
-
XSS Prevention:
- ALWAYS use DOMPurify for user-provided HTML
- Sanitize all external input
- Review
test/unit/xss/for examples - Never use
dangerouslySetInnerHTMLwithout sanitization
-
Input Validation:
- Validate API responses
- Handle malformed OpenAPI specs gracefully
- Check for prototype pollution
-
Dependency Security:
npm run security-audit # Run security audit
Testing Different Versions:
- OAS 2.0: Use
src/core/plugins/swagger-client/ - OAS 3.0.x: Use
src/core/plugins/oas3/ - OAS 3.1.x: Use
src/core/plugins/oas31/ - OAS 3.2.x: Use
src/core/plugins/oas32/
Adding Test Specs:
- Add to
test/e2e-cypress/static/documents/ - Reference in E2E tests
- Always read files before modifying them
- Follow the no-semicolon convention
- Use double quotes for strings
- Add
@prettierpragma to all new files - Use
.jsxextension for React components - Write tests for new features and bug fixes
- Run linters before committing (automatic via husky)
- Use DOMPurify for HTML sanitization
- Follow conventional commit format
- Update documentation for user-facing changes
- Test with multiple OpenAPI spec versions
- Check browser compatibility (see
.browserslistrc) - Use the plugin architecture - don't modify core unnecessarily
- Preserve backward compatibility unless explicitly breaking
- Run full test suite before submitting PR
- Keep plugins self-contained - avoid cross-plugin imports (see Cross-Plugin Import Guidelines)
- Don't use semicolons - project convention
- Don't use single quotes - use double quotes
- Don't skip the @prettier pragma - required for formatting
- Don't put React in
.jsfiles - use.jsx - Don't commit files in
dev-helpers/(except core files) - Don't commit build artifacts (
dist/is gitignored) - Don't skip tests - they run in CI
- Don't bypass ESLint - pre-commit hook enforces
- Don't use
console.log- onlyconsole.warnandconsole.error - Don't render unsanitized HTML - XSS vulnerability
- Don't modify
package-lock.jsonmanually - Don't push directly to
masterornext - Don't ignore Cypress test failures
- Don't add dependencies without justification
- Don't break the build - verify with
npm run build - Don't import from other plugins - create self-contained copies instead (e.g., don't import from
oas31inoas32)
Before Making Changes:
- Read the affected files completely
- Understand the plugin architecture
- Check for existing tests
- Review related documentation
During Development:
- Make minimal, focused changes
- Follow existing patterns in the codebase
- Add tests alongside code changes
- Run linters frequently
After Changes:
- Verify all tests pass
- Check build completes successfully
- Test artifact exports
- Review for security issues
- Update relevant documentation
Communication:
- Be explicit about file locations
- Use line number references (e.g.,
src/core/system.js:96) - Provide context for changes
- Mention any breaking changes clearly
-
Immutable.js:
- Use Immutable data structures for state
- Use
.toJS()sparingly (expensive) - Prefer Immutable operations
-
React:
- Use React.memo for pure components
- Implement shouldComponentUpdate for class components
- Avoid inline function definitions in render
-
Redux:
- Use reselect for memoized selectors
- Keep reducers pure and fast
- Avoid large state trees
-
Bundle Size:
- Check bundle size with
npm run deps-size - Review dependency licenses with
npm run deps-license - Consider code splitting for large features
- Check bundle size with
Development Server:
npm run dev
# Open http://localhost:3200/
# Hot reload enabled
# Unminified stack tracesRedux DevTools:
- Extension supported
- State inspection available
- Time-travel debugging
Cypress Interactive Mode:
npm run cy:dev
# Visual test runner
# Step-through debugging
# Network inspectionJest Watch Mode:
npm run test:unit -- --watch
# Re-run on file changes
# Filter by file name or test nameSource Maps:
- Generated for all builds
- Enable in browser DevTools
- Original source debugging
# Development
npm run dev # Start dev server (port 3200)
npm start # Static file server (port 3002)
# Building
npm run build # Full production build
npm run clean # Remove dist/
# Testing
npm test # Full test suite (lint + unit + E2E)
npm run test:unit # Jest unit tests
npm run cy:dev # Cypress interactive
npm run cy:ci # Cypress CI mode
npm run test:artifact # Artifact verification
# Linting
npm run lint # ESLint (errors + warnings)
npm run lint-errors # ESLint (errors only)
npm run lint-fix # Auto-fix ESLint issues
npm run lint-styles # Stylelint
npm run lint-styles-fix # Auto-fix Stylelint issues
# Security
npm run security-audit # Run npm audit
# Dependencies
npm run deps-check # Size and license reportCore System: src/core/system.js
Main Entry: src/index.js
React Entry: flavors/swagger-ui-react/index.jsx
Components: src/core/components/
Plugins: src/core/plugins/
Styles: src/style/
Tests (Unit): test/unit/
Tests (E2E): test/e2e-cypress/e2e/
Build Output: dist/
- 3200 - Development server (webpack-dev-server)
- 3002 - Static file server (local-web-server)
- 3204 - Mock API server (json-server)
- 3230 - E2E test server (webpack-dev-server)
- Setup Guide:
docs/development/setting-up.md - Scripts Reference:
docs/development/scripts.md - Plugin API:
docs/customization/plugin-api.md - Configuration:
docs/usage/configuration.md - OAuth2 Setup:
docs/usage/oauth2.md
- Homepage: https://swagger.io/tools/swagger-ui/
- Repository: https://github.com/swagger-api/swagger-ui
- npm (main): https://www.npmjs.com/package/swagger-ui
- npm (dist): https://www.npmjs.com/package/swagger-ui-dist
- npm (react): https://www.npmjs.com/package/swagger-ui-react
- OpenAPI Spec: https://spec.openapis.org/
- Issues: https://github.com/swagger-api/swagger-ui/issues
- Good First Issues: https://github.com/swagger-api/swagger-ui/issues?q=is%3Aissue+is%3Aopen+label%3A%22Good+first+issue%22
- Security: security@swagger.io
- Contributing: https://github.com/swagger-api/.github/blob/HEAD/CONTRIBUTING.md
Note: This document should be updated whenever major architectural changes, new conventions, or significant workflows are introduced to the codebase.