node.jsexpressswaggeropenapiswagger-ui-express

How to style Swagger API docs with custom CSS in Node.js?


I'm trying to style my Node.js Swagger API docs and despite reading resources I cannot seem to make it work. Originally I stuck to official documentation from npm and some earlier discussions in here but still no help.

App is written in TypeScript and in backend root server.ts:

const swaggerDefinition = yaml.load(path.join(__dirname, "..", "swagger.yaml"));
app.use(
  "/docs",
  swaggerUi.serve,
  swaggerUi.setup(swaggerDefinition, { customCss: "../swagger.css" })
);

I also tried:

const options = {
  customCss: "../swagger.css",
};
const swaggerDefinition = yaml.load(path.join(__dirname, "..", "swagger.yaml"));
app.use("/docs", swaggerUi.serve, swaggerUi.setup(swaggerDefinition, options));

and inline CSS:

const options = {
  customCss: ".swagger-ui .topbar { display: none !important; }",
};

Solution

  • here's a working example

    index.js

    const express = require('express')
    const swaggerUI = require('swagger-ui-express')
    
    
    const app = express()
    app.use(express.json())
    app.use(express.static(__dirname))
    const PORT = process.env.PORT || 3000
    
    const options = {
        customCssUrl: '/custom.css'
    };
    
    const OASdescription = {
    
        openapi: "3.1.0",
        info: {
            title: "test api for stack",
            version: "1.0.0"
        },
        servers: [
            {
                "url": "https://localhost.com:3000/v1"
            }
        ],
        tags: [{
            "name": "test api",
            "description": "test api description"
        }],
        paths: {
            "/hello": {
                "get": {
                    "description": "description",
                    "tags": ["test api"],
                    "operationId": "sayHello",
                    "parameters": [
                        {
                            "$ref": "#/components/parameters/header_accept-language"
                        }
                    ],
                    "responses": {
                        "200": {
                            "description": "response",
                            "content": {
                                "application/json": {
                                    "schema": {
                                        "type": "string"
    
                                    }
                                }
                            }
                        },
                        "400": {
                            "$ref": "#/components/responses/400"
                        }
                    }
                }
            }
        },
        components: {
            "parameters": {
                "header_accept-language": {
                    "name": "accept-language",
                    "in": "header",
                    "schema": {
                        "type": "string",
                        "enum": ["en-US"],
                        "default": "en-US"
                    }
                }
            },
            "responses": {
                "400": {
                    "description": "Bad Request",
                    "content": {
                        "application/problem+json": {
                            "schema": {
                                "description": "Problem JSON as defined in RFC9457",
                                "type": "object",
                                "properties": {
                                    "type": {
                                        "description": "The \"type\" member is a JSON string containing a URI reference [URI] that identifies the problem type",
                                        "type": "string",
                                        "format": "uri-reference"
                                    },
                                    "status": {
                                        "description": "The \"status\" member is a JSON number indicating the HTTP status code ([HTTP], <a href=\"https://www.rfc-editor.org/rfc/rfc9110#section-15\">Section 15</a>) generated by the origin server for this occurrence of the problem.",
                                        "type": "number"
                                    },
                                    "title": {
                                        "description": "The \"title\" member is a JSON string containing a short, human-readable summary of the problem type.",
                                        "type": "string"
                                    },
                                    "detail": {
                                        "description": "The \"detail\" member is a JSON string containing a human-readable explanation specific to this occurrence of the problem.",
                                        "type": "string"
                                    },
                                    "instance": {
                                        "description": "The \"instance\" member is a JSON string containing a URI reference that identifies the specific occurrence of the problem.",
                                        "type": "string",
                                        "format": "uri-reference"
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    
    
    app.use('/docs', swaggerUI.serve, swaggerUI.setup(OASdescription, options))
    
    
    app.listen(PORT, () => console.log(`listening on port ${PORT}`))
    
    

    custom.css

    .swagger-ui .topbar {
        background-color: blue;
    }
    

    package.json

    {
        "dependencies": {
            "swagger-ui-express": "^5.0.0",
            "express": "^4.18.2"
        }
    }