Integrating A Frontend Library
This article will show you the steps to take to integrate a frontend library like Bootstrap 5 into your Lona project.
There are two ways to integrate a library. You can add it to your project, or you can package your library into a Python module to make it reusable (reference package)
Adding A Frontend Library To Your Project
Adding a frontend library to a Lona on a project basis works like in traditional web frameworks: You add your static files to a static directory write a custom frontend template and produce the right HTML.
your-project/static/
└── bootstrap-5.1.0-dist
├── css
│ ├── bootstrap.css
│ ├── bootstrap.css.map
│ ├── bootstrap-grid.css
│ ├── bootstrap-grid.css.map
│ ├── bootstrap-grid.min.css
│ ├── bootstrap-grid.min.css.map
│ ├── bootstrap-grid.rtl.css
│ ├── bootstrap-grid.rtl.css.map
│ ├── bootstrap-grid.rtl.min.css
│ ├── bootstrap-grid.rtl.min.css.map
│ ├── bootstrap.min.css
│ ├── bootstrap.min.css.map
│ ├── bootstrap-reboot.css
│ ├── bootstrap-reboot.css.map
│ ├── bootstrap-reboot.min.css
│ ├── bootstrap-reboot.min.css.map
│ ├── bootstrap-reboot.rtl.css
│ ├── bootstrap-reboot.rtl.css.map
│ ├── bootstrap-reboot.rtl.min.css
│ ├── bootstrap-reboot.rtl.min.css.map
│ ├── bootstrap.rtl.css
│ ├── bootstrap.rtl.css.map
│ ├── bootstrap.rtl.min.css
│ ├── bootstrap.rtl.min.css.map
│ ├── bootstrap-utilities.css
│ ├── bootstrap-utilities.css.map
│ ├── bootstrap-utilities.min.css
│ ├── bootstrap-utilities.min.css.map
│ ├── bootstrap-utilities.rtl.css
│ ├── bootstrap-utilities.rtl.css.map
│ ├── bootstrap-utilities.rtl.min.css
│ └── bootstrap-utilities.rtl.min.css.map
└── js
├── bootstrap.bundle.js
├── bootstrap.bundle.js.map
├── bootstrap.bundle.min.js
├── bootstrap.bundle.min.js.map
├── bootstrap.esm.js
├── bootstrap.esm.js.map
├── bootstrap.esm.min.js
├── bootstrap.esm.min.js.map
├── bootstrap.js
├── bootstrap.js.map
├── bootstrap.min.js
└── bootstrap.min.js.map
<!-- templates/lona/frontend.html -->
<html>
<head>
<meta charset="utf-8" />
{{ Lona.load_stylesheets() }} <!- this loads all stylsheets that are part of a Lona node class ->
<link href="{{ Lona.load_static_file('bootstrap-5.1.0-dist/css/bootstrap.min.css') }}" rel="stylesheet">
</head>
<body>
<!- add your page layout here ->
<div id="lona"></div> <!- this is the element where all Lona views are rendered in ->
<!- add your page layout here ->
{{ Lona.load_scripts() }} <!- this loads the Lona client library and all scripts that ar part of a Lona node class->
<script>
var lona_context = new Lona.LonaContext({
target: '#lona',
title: 'Lona',
update_address_bar: true,
update_title: true,
follow_redirects: true,
follow_http_redirects: true,
});
lona_context.setup();
</script>
</body>
</html>
from lona.html import HTML
from lona import LonaView
class ProgressBarView(LonaView):
def handle_request(self, request):
html = HTML("""
<h1>Bootstrap 5 Progressbar</h1>
<div class="progress">
<div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
</div>
""")
Packaging A Frontend Library
To package a frontend library with your HTML nodes, you have to register them in Node.STATIC_FILES.
This example shows how a package of Bootstrap 5 buttons would look like.
More information: Adding Javascript And CSS To HTML Nodes
lona-bootstrap-5/lona_bootstrap_5/
├── __init__.py
├── buttons.py
├── static
│ ├── bootstrap-5.1.0-dist
│ │ ├── css
│ │ │ ├── bootstrap.css
│ │ │ ├── bootstrap.css.map
│ │ │ ├── bootstrap-grid.css
│ │ │ ├── bootstrap-grid.css.map
│ │ │ ├── bootstrap-grid.min.css
│ │ │ ├── bootstrap-grid.min.css.map
│ │ │ ├── bootstrap-grid.rtl.css
│ │ │ ├── bootstrap-grid.rtl.css.map
│ │ │ ├── bootstrap-grid.rtl.min.css
│ │ │ ├── bootstrap-grid.rtl.min.css.map
│ │ │ ├── bootstrap.min.css
│ │ │ ├── bootstrap.min.css.map
│ │ │ ├── bootstrap-reboot.css
│ │ │ ├── bootstrap-reboot.css.map
│ │ │ ├── bootstrap-reboot.min.css
│ │ │ ├── bootstrap-reboot.min.css.map
│ │ │ ├── bootstrap-reboot.rtl.css
│ │ │ ├── bootstrap-reboot.rtl.css.map
│ │ │ ├── bootstrap-reboot.rtl.min.css
│ │ │ ├── bootstrap-reboot.rtl.min.css.map
│ │ │ ├── bootstrap.rtl.css
│ │ │ ├── bootstrap.rtl.css.map
│ │ │ ├── bootstrap.rtl.min.css
│ │ │ ├── bootstrap.rtl.min.css.map
│ │ │ ├── bootstrap-utilities.css
│ │ │ ├── bootstrap-utilities.css.map
│ │ │ ├── bootstrap-utilities.min.css
│ │ │ ├── bootstrap-utilities.min.css.map
│ │ │ ├── bootstrap-utilities.rtl.css
│ │ │ ├── bootstrap-utilities.rtl.css.map
│ │ │ ├── bootstrap-utilities.rtl.min.css
│ │ │ └── bootstrap-utilities.rtl.min.css.map
│ │ └── js
│ │ ├── bootstrap.bundle.js
│ │ ├── bootstrap.bundle.js.map
│ │ ├── bootstrap.bundle.min.js
│ │ ├── bootstrap.bundle.min.js.map
│ │ ├── bootstrap.esm.js
│ │ ├── bootstrap.esm.js.map
│ │ ├── bootstrap.esm.min.js
│ │ ├── bootstrap.esm.min.js.map
│ │ ├── bootstrap.js
│ │ ├── bootstrap.js.map
│ │ ├── bootstrap.min.js
│ │ └── bootstrap.min.js.map
│ └── bootstrap5-widgets.js
└── static_files.py
# lona-bootstrap-5/lona_bootstrap_5/buttons.py
from lona.static_files import StyleSheet, Script, SORT_ORDER
class Button(BaseButton):
STATIC_FILES = [
# css files
StyleSheet(
name='bootstrap5.css',
path='static/bootstrap-5.1.0-dist/css/bootstrap.min.css',
url='bootstrap5.min.css',
sort_order=SORT_ORDER.FRAMEWORK,
),
StyleSheet(
name='bootstrap5.css',
path='static/bootstrap-5.1.0-dist/css/bootstrap.min.css',
url='bootstrap5.min.css.map',
sort_order=SORT_ORDER.FRAMEWORK,
link=False,
),
# js files
Script(
name='bootstrap5.bundle.js',
path='static/bootstrap-5.1.0-dist/js/bootstrap.bundle.min.js',
url='bootstrap5.bundle.min.js',
sort_order=SORT_ORDER.FRAMEWORK,
),
Script(
name='bootstrap5.bundle.js',
path='static/bootstrap-5.1.0-dist/js/bootstrap.bundle.min.js.map',
url='bootstrap5.bundle.min.js.map',
sort_order=SORT_ORDER.FRAMEWORK,
link=False,
),
]
class PrimaryButton(Button):
CLASS_LIST = ['btn', 'btn-primary']
class SecondaryButton(Button):
CLASS_LIST = ['btn', 'btn-secondary']
class SuccessButton(Button):
CLASS_LIST = ['btn', 'btn-success']
class DangerButton(Button):
CLASS_LIST = ['btn', 'btn-danger']
class WarningButton(Button):
CLASS_LIST = ['btn', 'btn-warning']
class InfoButton(Button):
CLASS_LIST = ['btn', 'btn-info']
class LightButton(Button):
CLASS_LIST = ['btn', 'btn-light']
class DarkButton(Button):
CLASS_LIST = ['btn', 'btn-dark']
class LinkButton(Button):
CLASS_LIST = ['btn', 'btn-link']