Ultimate Guide to TaiPy GUI

Ishmam Fardin
9 min readJun 9, 2024

--

Taipy is an open-source Python library for easy, end-to-end application development, featuring what-if analyses, smart pipeline execution, built-in scheduling, and deployment tools.

Prologue

Roughly 2–3 weeks ago, I attended a data science hackathon at Georgia Institue of Technology called Hacklytics. My team and I chose the sports track and had plans to have graphs/visualizations that were interactive and Machine Learning technologies to output relevant information.

Given this was a data science hackathon, we didn’t want emphasis on the frontend, however, we also wanted it to look somewhat appealing. One of the prizes was “Best Use of TaiPy” and at a glance it seemed similar to a technology we were familiar with, Streamlit. We believed it would be a good chance to try out a new technology, wouldn’t be too hard to implement, and we have more chances at winning.

We were wrong on the second part, the technology was new (so less help available), documentation was difficult to navigate, and unlike streamlit, it wasn’t as intuitive. Hence the motivation to write this article.

Configuration

Installation

Downloading TaiPy is simple, run the command pip install taipy and it should be within your environment.

In main.py, you should add the following imports:

from taipy.gui import Gui
import taipy as tp

Themes

light_theme = {
"palette": {
"background": {
"default": "#d580ff"
},
"primary": {"main": "#ffffff"}
}
}

dark_theme = {
"palette": {
"background": {
"default": "#471061"
},
"primary": {"main": "#000000"}
}
}

TaiPy uses other libraries out there for their own configurations. For themes, they follow Material UI’s practices. These two variables are the parameters for light and dark mode. Background sets the color of the whole background while primary is meant for the text color. I am not too familiar with the Material UI library but for simple cases you can look at this part of the TaiPy github to change the theme as you see fit. It gives you a good sense of what you can change and update.

Initializing

app = Gui()

if __name__ == '__main__':

app.run(title="SoccerStatusTech", use_reloader=True, port=3636, light_theme=light_theme, dark_theme=dark_theme)

The first line creates the GUI instance. app.run() tells the program to run TaiPy (it seems to be built on top of flask). Title sets the name of the site at the top for your browser, use_reloader doesn’t require you to refresh the page manually when you make changes, then the rest is configuring your theme and port.

Multi-Page Functionality

The intriguing part about TaiPy is how it reads instructions through markdown. It’s not the typical markdown where you’re bolding with astrics or highlighting code with backticks, but a different syntax within a markdown file that TaiPy reads and outputs on the frontend.

In your repository, create a directory called pages . Within this directory, create the following: root.py root.md and directories for all your pages

Repository
-> main.py
-> pages
-> root.py
-> root.md
-> directories for each page

Here’s how our group structured ours:

You might be thinking that root.py is the home page, but it’s actually what’s consistent throughout all the pages, like a navbar for instance. I initially neglected the root files but it ended up creating weird user experiences when navigating through the pages.

Within root.py , add the following:

from taipy.gui import Markdown

root = Markdown('root.md')

Markdown essentially reads the instructions from the markdown file. For all your pages, you should have a python file and a markdown file.

For example, for home page, I have a home.py file and a home.md file. In each python file for each page, you should have a the code you put for the root.py file but different variable names and accessing the associated markdown. In home.py , I would have

from taipy.gui import Markdown

home_md = Markdown('home.md')

Finally now to connect all your pages, go to your main.py file add/update the following:

from pages.home.home import home_md
from pages.prediction.predictions import predictions_md
from pages.charts.charts import charts_md
from pages.root import root

pages = {
'/':root,
'home':home_md,
"statistics":charts_md,
"predictions":predictions_md,
}

app = Gui(pages=pages)

# I added in the variables we created from the python files in pages
# directory, as well as, the pages dictionary to map endpoints to
# associated GUI instructions.

First you should access all the variables you created in your python files in pages.

Like most web apps, I thought the the slash would signify that as being the homepage. To reiterate, it isn’t. Create a pages dictionary, the slash should map to root, the other endpoints naming convention is up to you. Each endpoint should map to their corresponding page / variable.

The last part is to update the initialization of GUI, set pages parameter to your pages dictionary.

Markdown Syntax & More

So far we’ve covered only configuration. We will now touch upon the weird syntax that’s used within markdown.

Navbar & Darkmode

<br/>
<|layout|columns=1fr auto 1fr|class_name=container align_columns_center|
<|part|
**<|SoccerStatusTech|text|height=50px|width=50px|style="font-size: 50px;"|>**
|>
<|part|class_name=align_item_stretch|
<|navbar|class_name=fullheight|>
|>
<|part|class_name=text_right|
<|toggle|theme|>
|>
|>

We used this piece of code in root.md. It’s a mix of XML, HTML/CSS, markdown, and probably some other syntax I don’t know.

  • <br/> does a line break
  • <|layout|> structures how you want things to be placed. It’s similar to a div or span in css where you have multiple parts and want them in the same row
  • similar to html, you want the parts to be within the closed brackets. Weirdly, if you have stuff within setting the element type, you have to end it with |> and not just >
  • <|part|> lets the interface know it’s an element of a layout
  • columns=1fr auto 1fr|class_name=container align_columns_center is setting css rules for the layout. 1fr means the first part takes up one fraction of available space, and auto adjusts based off content.
  • class_name=align_item_stretch and other css properties don’t have dashes, instead it uses underscores.
  • For text, <|"your text without quotes go here" |text|height=50px|width=50px|style=”font-size: 50px;”|> , for other configurations you can check documentation
  • For navbar, <|navbar|> uses the endpoints from your main.py
  • For darkmode/lightmode functionality, <|toggle|theme|> creates a toggle with an icon for dark and light theme
  • Make sure you close each property properly

Drop Down, Cards, and Buttons

<|text-center|
<br/>
<|card|
<h3>Choose your team</h3>
<|layout|gap=10px|class_name=container align_center|
<center>
<|{value1}|selector|lov=Arsenal;Aston Villa;Bournemouth;Brentford;Burnley;Wolverhampton;Brighton Hove;Chelsea;Crystal Palace;Everton;Fulham;Liverpool;Luton Town;Man City;Man United;Newcastle;Nottingham;Sheffield Utd;Tottenham;West Ham|dropdown|label=Team 1|>
</center>

<center>
<|{value2}|selector|lov=Arsenal;Aston Villa;Bournemouth;Brentford;Burnley;Wolverhampton;Brighton Hove;Chelsea;Crystal Palace;Everton;Fulham;Liverpool;Luton Town;Man City;Man United;Newcastle;Nottingham;Sheffield Utd;Tottenham;West Ham|dropdown|label=Team 2|>
</center>
|>
<|Generate|button|on_action=button_pressed|class_name=button|
|>

The following code was used in home.md which is the landing page we want users to see, and where we get inputs.

  • a card is essentially just a square box that you can place information in. You create a card by having a <|card| at the start and then place the parts within it, ending with |> .
  • Dropdown menus are bit more complex where the first value is the name you want to set the selector as so you can access it in your python file. Essentially, your identifier, letting you access the user input from the state. The second value is justselector letting Taipy know it’s a drop down selection, and the third part is your options. lov stands for list of values and you just state the options separated by semi colons. Finally the last part is your label, which is essentially what the user sees before selecting an option.
  • Buttons are pretty simple, You start with the button name, in my case, it’s generate . You can have submit, update, add, etc. depending on what your button does and what you want the user to see. Second part is just button letting Taipy know it’s a button, and the third part is on_action which will set off the events you want. You can set on_action equal to anything, like “clicked_button” or “submit”, but in your python file, you’d need a function that starts with the same name.

Graphs, Charts, & Toggles

<|part|render={showToggles}|
<center>
<|{selected_team}|toggle|lov={values}|on_change=toggle_choice|>
</center>
|>
<br/>
<|layout|column=1 1|
<|part|render={showGraphs}|
<|{data}|chart|type=pie|values=Count|labels=Country|title=Percentage of Players by Nationality|>
|>
<|part|render={showGraphs}|
<|{dataframe}|chart|type=bar|x=Season|y[1]=W|y[2]=L|layout={layout}|>
|>
|>
<|part|render={showGraphs}|
<|{allFrame}|chart|mode=lines|x=Season|y[1]=Goals Scored|y[2]=Goals Conceded|y[3]=Points|>
|>
  • In the following markdown, I started with a toggle button. First section is the label, basically the text the user sees on the toggle itself. Next is toggle to let the user know that it’s a toggle, and right after is the list of the values (lov). The last section is the on_change.
  • The values within curly braces are the names of variables within the state that holds certain information. values is a list that holds two items, team 1 and team 2, selected_team is a new variable defined in the markdown that allows us to access which team was clicked on in python file.

All the charts follow a similar pattern, each one are in a part where they have a parameter called render which lets us know whether to show graph or not. showGraphs is initially False but when a user clicks on a team on the toggle, it’s set to True.

The first section on the chart is the data itself, which could be a dataframe (pandas) or a dictionary with values that are lists. Second section is chart to let Taipy know it’s a chart, third section is the type of chart, so in this instance (below), it’s a pie chart. values , labels, and title are self explanatory.

<|part|render={showGraphs}| <|{data}|chart|type=pie|values=Count|labels=Country|title=Percentage of Players by Nationality|> |>

Other charts follow a similar pattern, though for bar and line graphs you’d have to specify x and y and optionally, label that is defined in python file.

State

I probably should’ve covered this first given how prevalent it is in the code. State is how you get the information from the user interactions on the frontend. When creating a function for an on_change the function has a parameter called state allowing you to access inputs or modifying values.

If you want to define variables in curly brackets , you’d create a variable in the python file and access it in the markdown with curly braces.

Here is the python code for the markdown we looked at earlier.

layout = {
"yaxis": {
"side": "left",
"title": "Games"
},
"title": {
"text" : "Win vs Losses Throughout the Season(s)"
}
}

dataframe = {"Season":[], "W":[], "L":[]}
allFrame = {"Season":[], "Goals Scored":[], "Goals Conceded":[], "Points":[]}

data = {"Country":[], "Count":[]}
logo = ''
selected_team = ''
def toggle_choice(state):

state.logo, countries = nationalityChart(state.selected_team, state.response)

state.data = {
"Country": list(countries.keys()),
"Count": list(countries.values())
}

state.dataframe = df[df['Team']==state.selected_team].copy()
state.allFrame = df[df['Team']==state.selected_team].copy()
state.showGraphs = True

The layout was defined in python , and was able to get accessed in the markdown within the curly braces.

Within the def toggle_choice(state), we were able to change the interface logic, such as showing data only for the team that was selected, setting a logo for the team, and rendering all the graphs by setting showGraphs to true.

State seems to be something that you can only access within on_change functions , though at the start before you run your application , you’re able to add values to the state so you can access in other pages.

You do so by using GUI.add_shared_variables which allow you to access variables and data across other pages. It’s not technically using state here , since there isn’t anything changing, but makes states easier to manage when user interactions occur.

response = requests.get(API_URL, headers=headers)

value1="select a team"
value2="select a team"

showToggles = False

app = Gui(pages=pages)

values = ['team1','team2']

Gui.add_shared_variables(values, showToggles, response)

Conclusion and Source Code

What we thought would be an easy tool to use , turned out to be difficult and took a long time to figure out how to put it together. The most difficult part was sharing data across multiple pages, such as knowing whether the generate button was pressed or not, which teams were selected, etc. We had to learn the technology as well as build our application at the same time within a constrained amount of time.

For full transparency, I feel that there’s still a lot of gaps in what I know about the library, but I hope what I shared provides some insights or guidance on helping you build your Taipy project.

Github: https://github.com/IshmamF/SoccerStatusTech
Project Showcase: https://devfolio.co/projects/soccerstatustech-fde8

Thank you for reading!

--

--

Ishmam Fardin

Computer Science Student, Graduating 2025 | No man can walk out on his own story - Rango