DEV Community

Cover image for How we streamlined frontend development with OpenAPI ๐Ÿš€
Dmitrii Zakharov
Dmitrii Zakharov

Posted on • Edited on

How we streamlined frontend development with OpenAPI ๐Ÿš€

Many of you have probably used OpenAPI in your projects, or at least heard of it. But from my regular conversations with developers, Iโ€™ve noticed something surprising: a lot of frontend developers still donโ€™t fully take advantage of it.

This article is about how using OpenAPI has helped us speed up development, improve code consistency, and eliminate entire categories of errors. I'll also walk you through how to set it up and integrate it into a TypeScript project.


๐Ÿงฉ What Is OpenAPI, really?

At its core, OpenAPI is a tool that takes your Swagger definitions and generates a full API client, including:

  • A wrapper for all your endpoints
  • Typed models and DTOs (based on Swagger schema)
  • Methods that handle requests for you (like axios or fetch) with built-in type safety

In short: no more manually writing interfaces and HTTP calls. You get a fully typed, ready-to-use client thatโ€™s always in sync with the backend.


๐Ÿ’ก Why OpenAPI matters

Here are some of the biggest benefits weโ€™ve seen:

  • Type safety out of the box: All request and response models are generated from Swagger. You no longer need to manually define interfaces or worry about mismatches.
  • No more manual fetch/axios calls: All endpoints come with pre-written request methods.
  • Consistency between backend and frontend: When something changes on the backend (e.g., a route is renamed or a payload changes), you just re-generate the schema and catch issues during compile time.
  • Zero maintenance: Once configured, itโ€™s basically plug-and-play โ€” just update the schema when needed.

๐Ÿ›  Setting up OpenAPI in your project

To get started, install the OpenAPI generator:

yarn add @openapitools/openapi-generator-cli
Enter fullscreen mode Exit fullscreen mode

Create a config file openapi/apiConfig.json with the following:

{
  "prefixParameterInterfaces": true,
  "supportsES6": true,
  "typescriptThreePlus": true
}
Enter fullscreen mode Exit fullscreen mode

Now, add scripts to your package.json:

"scripts": {
  "openapi": "yarn openapi:download && yarn openapi:generate",
  "openapi:download": "curl https://yourserver.com/api/docs-json > ./openapi/openapi.json",
  "openapi:generate": "openapi-generator-cli validate -i ./openapi/openapi.json && rm -rf src/openapi/api && openapi-generator-cli generate -i ./openapi/openapi.json -c ./openapi/apiConfig.json -g typescript-fetch -o src/openapi/api"
}
Enter fullscreen mode Exit fullscreen mode

โš ๏ธ Note: You may need to install JRE (Java Runtime Environment) for the generator to work.


๐Ÿ“ฆ Building the API Client

After running yarn openapi, youโ€™ll get a fully generated src/openapi folder with models, APIs, and types.

To simplify usage, letโ€™s build a centralized API client:

import {
  BonusApi,
  ChatApi,
  Configuration,
  ServiceApi,
  UserAccessApi,
  UserInfoApi,
  UsersApi,
  UserTasksApi,
  UserUtilsApi,
} from './api';

const configuration = new Configuration({
  accessToken() {
    return 'ACCESS_TOKEN';
  },
  get headers() {
    return {
      'x-language': 'en',
    };
  },
});

export const ApiClient = {
  chat: new ChatApi(configuration),
  service: new ServiceApi(configuration),
  user: {
    access: new UserAccessApi(configuration),
    info: new UserInfoApi(configuration),
    tasks: new UserTasksApi(configuration),
    utils: new UserUtilsApi(configuration),
  },
  users: new UsersApi(configuration),
};
Enter fullscreen mode Exit fullscreen mode

Now calling an API is as simple as:

const { accessToken } = await ApiClient.user.access.login({
  appLoginPayloadDto: payload,
});
Enter fullscreen mode Exit fullscreen mode

๐Ÿ” Whatโ€™s under the hood?

Letโ€™s take a look at the actual implementation of the login method:

async loginRaw(
  requestParameters: UserAccessApiLoginRequest,
  initOverrides?: RequestInit | runtime.InitOverrideFunction
): Promise<runtime.ApiResponse<AppAccessUserTokenDto>> {
  if (requestParameters['appLoginPayloadDto'] == null) {
    throw new runtime.RequiredError('appLoginPayloadDto', 'Required parameter is missing.');
  }

  const headerParameters: runtime.HTTPHeaders = {
    'Content-Type': 'application/json',
  };

  const response = await this.request({
    path: `/app/user/access/login`,
    method: 'POST',
    headers: headerParameters,
    body: AppLoginPayloadDtoToJSON(requestParameters['appLoginPayloadDto']),
  }, initOverrides);

  return new runtime.JSONApiResponse(response, (jsonValue) => AppAccessUserTokenDtoFromJSON(jsonValue));
}

async login(
  requestParameters: UserAccessApiLoginRequest,
  initOverrides?: RequestInit | runtime.InitOverrideFunction
): Promise<AppAccessUserTokenDto> {
  const response = await this.loginRaw(requestParameters, initOverrides);
  return await response.value();
}
Enter fullscreen mode Exit fullscreen mode

You can see that everything is strictly typed โ€” parameters, return values, and even runtime checks are in place.


โš ๏ธ Limitations (for now)

There are still some things OpenAPI doesnโ€™t support out of the box, such as:

  • WebSockets
  • Some custom middleware logic

These require custom solutions for now. But the OpenAPI ecosystem is rapidly evolving, and we expect more features to be supported over time.

See you in the comments โ€” and thanks for reading! ๐Ÿš€

Top comments (3)

Collapse
 
nevodavid profile image
Nevo David

Nice, makes me want to go clean up my own mess of HTTP calls tbh.

Collapse
 
vidakhoshpey22 profile image
Vida Khoshpey

The problem is that , openai is very expensive, my country is under embargo and I can't even use it for a month for free. Ready-made models are the only way. Do you have any suggestions for me in this regard?

Collapse
 
senior-debugger profile image
Dmitrii Zakharov

You probably got it mixed up; it's not OpenAI, but OpenAPI, and it's available for all regions worldwide via npm storage.

Have a good day!)