Define multipage apps with Jt.page
and Jt.navigation
This page assumes you understand the Page terminology presented in the overview.
App structure
When using Jt.navigation
, your entrypoint file acts like a page router. Each page is an app executed from your
entrypoint file. You can define a page from a Java class . If you include
elements or widgets in your entrypoint file, they become common elements between your pages. In this case, you can
think of your entrypoint file like a picture frame around each of your pages.
You can only call Jt.navigation
once per app run and you must call it from your entrypoint file. When a user selects
a page in navigation (or is routed through a command like Jt.switchPage
), Jt.navigation
returns the selected page.
You must manually execute that page with the .run()
method. The following example is a two-page app where each page
is defined by a Java class.
Directory structure:
your-repository/
├── Page1.java
├── Page2.java
└── App.java
App.java
:
import io.jeamlit.core.Jt;
import io.jeamlit.core.JtPage;
public class App {
public static void main(String[] args) {
JtPage currentPage = Jt.navigation(
Jt.page(Page1.class), Jt.page(Page2.class)).use();
}
}
Defining pages
Jt.page
lets you define a page builder. The first and only required argument defines your page class .
Pass the page builders to Jt.navigation
to register them as pages in your app.
If you don't define your page title or URL pathname, Jeamlit will infer them from the Class name name as described in
the multipage apps Overview.
However, Jt.page
lets you configure them manually. See Jt.page API reference.
Customizing navigation
You can display your navigation menu in the sidebar or along the top of your app using the position
parameter in Jt.navigation
.
If you want to group your pages into sections, Jt.navigation
lets you insert headers in the sidebar navigation or
drop-down groups in the top navigation. Alternatively, you can disable the default navigation widget and build a
custom navigation menu with Jt.pageLink
.
Additionally, you can dynamically change which pages you pass to Jt.navigation
. However, only the page
returned by Jt.navigation
accepts the .run()
method. If a user enters a URL with a pathname, and that pathname is
not associated to a page in Jt.navigation
, Jeamlit will return a "Page not found" page.
Adding section headers
The simplest way to customize your navigation menu is to organize the pages within Jt.navigation
. You can sort or group
pages, as well as remove any pages you don't want the user to access. This is a convenient way to handle user permissions.
However, you can't hide a page in navigation while keeping it accessible through a direct URL. If you need to hide a page
while keeping it accessible, you'll need to hide the default navigation menu and build a navigation menu with commands like Jt.pageLink
.
The following example creates a login wall. When a user starts a new session, they are not logged in. In this case, the only available page is the login page. If a user tries to access another page by URL, it will create a new session and Jeamlit will not recognize the page. The user will be diverted to the login page. However, after a user logs in, they will see a navigation menu with different pages and be directed to the dashboard as the app's default page (i.e. homepage).
App.java
:
import io.jeamlit.core.Jt;
public class App {
public static void main(String[] args) {
boolean loggedIn = Jt.sessionState().computeIfAbsentBoolean("logged_in", k -> false);
if (!loggedIn) {
var currentPage = Jt.navigation(Jt.page(LoginPage.class)).hidden().use();
currentPage.run();
} else {
var currentPage = Jt.navigation(Jt.page(DashboardPage.class).home(), Jt.page(LogoutPage.class)).use();
currentPage.run();
}
}
public class LoginPage {
public static void main(String[] args) {
if (Jt.button("Log in").use()) {
Jt.sessionState().put("logged_in", Boolean.TRUE);
Jt.rerun(true);
}
}
}
public class LogoutPage {
public static void main(String[] args) {
if (Jt.button("Log out").use()) {
Jt.sessionState().put("logged_in", Boolean.FALSE);
Jt.rerun(true);
}
}
}
public class DashboardPage {
public static void main(String[] args) {
Jt.title("The dashboards").use();
Jt.text("This dashboard page is only available if the user is logged in.").use();
Jt.markdown("*the dashboard is not implemented, this is for example purpose*").use();
}
}
}
Note: in a real project, the LoginPage
, LogoutPage
and DashboardPage
classes would be written to dedicated files
and imported by the entrypoint App
class.
You can try this app with:
jeamlit run https://raw.githubusercontent.com/jeamlit/jeamlit/refs/heads/main/examples/login/App.java
Dynamically changing the available pages
You can change what pages are available to a user by updating the list of pages in Jt.navigation
. This is a convenient
way to handle role-based or user-based access to certain pages.
Building a custom navigation menu
If you want more control over your navigation menu, you can hide the default navigation and build your own.
You can hide the default navigation by chaining hidden()"
to your Jt.navigation()
call.
If you want a page to be available to a user without showing it in the navigation menu, you must use this method.
A user can't be routed to a page if the page isn't included in Jt.navigation
. This applies to navigation by URL as
well as commands like Jt.switchPage
and Jt.pageLink
.
Still have questions?
Go to our discussions forum for helpful information and advice from Jeamlit experts.