Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

This article provides a step by step on what you need to do in both S-UI and S-API in order to deploy the UI embedded inside the S-API as a Standalone service. This means that by simply starting the S-API you are also serving the UI at the same port.

Info

This is recommended for production when you have third party tools like SAML or OIDC authentication and you're having CORS error when trying to access the callback URL.

Search UI Deployment

By default when you're building a UI in development, you assume that you're working in the root, hence you only have to access locahost:3000/ to see the home page. The same applies to the default routing of the UI. It will always assume that you're working at the root unless you indicate otherwise by code. This is the first behavior we need to change if we want to serve the UI inside search API.

Note

Search API already has an endpoint for serving the UI, then the new root we want to use is /es/ui. If you want to use a different one then you must modify the files using the path of your choise.

Modifying the href

Modify the index.html file located at the root folder to add the new base href.

Code Block
languagexml
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <base href="/es/ui/"> <======================================================================== Add this line
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="index.css" />
    <title>ESG iFAQ</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>

Modify the vite.config.ts file to add the new base href. 

Code Block
languagejs
export default defineConfig({
  plugins: [react()],
  server: {
    cors: true,
  },
  base:"/es/ui/", <=======================================================================================
  assetsInclude: 'src/assets/*',
  .
  .
  .
});

Modify the <BrowserRouter> component at src/main.tsx file to add the new base href.

Code Block
languagejs
themeMidnight
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
    <BrowserRouter basename='/es/ui/'> <======================================================================
        <Provider store={store}>
            <PersistGate loading={null} persistor={persist}>
                <App/>
            </PersistGate>
        </Provider>
    </BrowserRouter>
);

Building UI for production

Run "pnpm run build" command at the root folder. This will create a dist directory containing the files of the build. Save those for later.

Note

Make sure there are not unused files or syntax errors or it will give you an error when building.

Table of Contents

Search API Configurations

On the root folder of Search API, go to the static folder and create a new folder called "ui".

Put inside this folder the files of the build of the UI that we saved on the previous section (the ones located at the dist folder, without including the dist folder, just the files).

Edit app/webapp.py and search for "# Static Files" commented section. Look for the comments in the code below and replaced the commented area with the following code.

Code Block
languagepy
themeDJango
# TODO: UI stuff should be configurable
try:
    app.mount(f'{BASE_HREF}/ui/assets',
              StaticFiles(directory=join(dirname(__file__), '..', 'static', 'ui', 'assets')), name='assets') <================================================================
except Exception as e:
    logger.error(f'Unable to load ui {str(e)}')

# Import Router from Core API
app.include_router(api.ui_router, prefix=f'{BASE_HREF}', dependencies=[])


Info

The line of code pointed with an arrow is the path where we're going to locate the UI assets. If you didn't follow the previous steps please make sure that the files are located on the path /static/ui. If you don't want to use this folder then change the path in that line of code.

Go to app/api/ui_api.py and modify the routes that may contain html. These routes must coincide with the routes at the UI's router. For example, if you have a homepage, login, and results page the code should look like this:

Code Block
languagepy
themeDJango
from os.path import join, dirname

from fastapi import APIRouter, Request
from fastapi.responses import HTMLResponse
from starlette import status

router: APIRouter = APIRouter(prefix='/ui', redirect_slashes=True)

# These routes must match the ones in React.


@router.get('/', include_in_schema=False)
@router.get('/login', include_in_schema=False)
@router.get('/results', include_in_schema=False)
# @router.get('/{rest_of_path:path}', include_in_schema=False) <====== This line allows the browser to interpret every path as html, not recommended since resources that fail loading may not be notified.
def get_app_angular():
    '''
    Main endpoint for the UI loading, the endpoint response to *<base_url>/ui/*, the file to load is the index.html
    located in the *<root_folder>/dist/ui* folder, in order to generate this folder you need to build the
    *<root_fodler>/ui folder*

    NOTE!!! : The React UI must have the basehref in the vite.config, in the BrowserRouter and in the index.html

    For this you can execute the command `ng build` in the ui folder
    '''
    with open(join(dirname(__file__), '..', '..', 'static', 'ui', 'index.html'), 'rb') as file_index: <===============================================================
        html_content = file_index.read()

    return HTMLResponse(html_content, status_code=status.HTTP_200_OK)

Info

The line of code pointed with an arrow is the path where we're going to locate the UI assets. If you didn't follow the previous steps please make sure that the files are located on the path /static/ui. If you don't want to use this folder then change the path in that line of code.


Related articles

Content by Label
showLabelsfalse
max5
spacesSEARCHAPI
showSpacefalse
sortmodified
reversetrue
typepage
cqllabel in ("kb-how-to-article","standalone","user-interface","html","ui") and type = "page" and space = "SEARCHAPI"
labelskb-how-to-article

Page properties
hiddentrue
Related issues