An Eitri-App is an application developed using the Eitri platform. They are mini-applications that run inside host apps, allowing you to create rich and interactive experiences in a modular way.
What is an Eitri-App?¶
Eitri-Apps are applications built with React that can run inside mobile apps that integrate the Eitri platform. They offer:
- Agile development: Real-time hot-reload during development
- Componentization: Use Eitri Luminus components to create interfaces
- Access to native resources: Through Eitri Bifrost, access camera, GPS, and other resources
- Simplified publishing: Manage versions and publications through Eitri Console
Eitri-App Structure¶
my-eitri-app/
├── src/
│ ├── views/ # App screens
│ │ └── Home.jsx
│ ├── providers/ # Global Providers/Hooks
│ └── locales/ # Internationalization files
├── eitri-app.conf.js # Eitri-App configuration
└── package.json
Creating an Eitri-App¶
To create a new Eitri-App, use the Eitri CLI:
eitri create my-eitri-app
Development Cycle¶
- Create: Use
eitri createto start a new project - Develop: Use
eitri startfor development with hot-reload - Test: Scan the QR Code with Eitri Play or integrated app
- Publish: Use
eitri push-versionto send to Console - Release: Publish the version to the desired environment through Console
Creating Views and Components¶
In Eitri, all screens (views) and components are built using React functional components. Each .jsx or .js file in the src/views/ folder represents a screen in your app.
Basic View Structure¶
A view must export a function as default that receives props as a parameter:
import { Window, View, Text } from "eitri-luminus";
export default function Home(props) {
return (
<Window>
<View padding="medium">
<Text fontSize="large">Welcome to Eitri!</Text>
</View>
</Window>
);
}
Requirements:
- Files with
.jsor.jsxextension - Export the function as
default - Receive
propsas parameter to access navigation data
Complete Example with State and Requests¶
import { useEffect, useState } from "react";
import { Window, View, Text, Image } from "eitri-luminus";
import Eitri from "eitri-bifrost";
export default function Products(props) {
const [products, setProducts] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
loadProducts();
}, []);
const loadProducts = async () => {
try {
const response = await Eitri.http.get("https://api.example.com/products");
setProducts(response.data);
} catch (error) {
console.error("Error loading products:", error);
} finally {
setLoading(false);
}
};
if (loading) {
return (
<Window>
<Text>Loading...</Text>
</Window>
);
}
return (
<Window>
{products.map((product) => (
<View
key={product.id}
display="flex"
direction="column"
marginTop="medium"
padding="medium"
>
<Image src={product.imageUrl} width={320} height={320} />
<Text fontSize="large">{product.title}</Text>
<Text>{product.description}</Text>
</View>
))}
</Window>
);
}
Providers and Global State¶
Eitri does not use App.tsx. All global state must be centralized in the providers/ folder.
MainProvider¶
The file src/providers/__main__.jsx is the main provider that wraps the entire application. Use it to centralize all other providers.
File: src/providers/__main__.jsx
import { createContext } from "react";
import AuthProvider from "./Auth";
const MainContext = createContext({});
export default function MainProvider({ children }) {
return (
<MainContext.Provider value={{}}>
<AuthProvider>{children}</AuthProvider>
</MainContext.Provider>
);
}
Creating a Provider¶
To share state between multiple views, create Providers in the src/providers/ folder. The file must start with an uppercase letter and export the provider as default.
Example: src/providers/Auth.jsx
import { createContext, useContext, useState } from "react";
const AuthContext = createContext({});
export default function AuthProvider({ children }) {
const [user, setUser] = useState(null);
const login = async (credentials) => {
// Authentication logic
const userData = await authenticateUser(credentials);
setUser(userData);
};
const logout = () => {
setUser(null);
};
return (
<AuthContext.Provider value={{ user, login, logout }}>
{children}
</AuthContext.Provider>
);
}
export function useAuth() {
return useContext(AuthContext);
}
Using the Provider in a View¶
import { useAuth } from "@/providers/Auth";
export default function Profile(props) {
const { user, logout } = useAuth();
return (
<Window>
<Text>Hello, {user?.name}</Text>
<Button label="Logout" onPress={logout} />
</Window>
);
}
Import with @
Use @/ to import files from the src/ folder, regardless of your current view's depth level.
Navigation¶
Eitri uses a file-based routing system, where the folder and file structure within src/views/ automatically defines the available routes in your Eitri-App.
File-based Routing¶
Each .js or .jsx file inside the src/views/ folder automatically becomes an accessible route in your Eitri-App.
File structure:
src/views/
├── Home.jsx → /Home
├── Products.jsx → /Products
├── Product/
│ └── [id].jsx → /Product/:id
└── Settings/
├── index.jsx → /Settings
└── Profile.jsx → /Settings/Profile
Conventions:
- Files at views root: Each file becomes a route with the file name
- Folders: Create nested route segments
- index.jsx: Represents the root route of a folder
- [parameter]: Creates dynamic routes with parameters
Dynamic Routes¶
To use dynamic routes, follow the [parameter] convention in the file or folder name.
For example, for a product listing with a details page:
File structure:
src/views/
├── Product
│ └── [id].jsx
└── Products.jsx
Where id will be the dynamic parameter. To navigate to the product with id 12345, the route will be /Product/12345.
Parameter & State Retrieval¶
Data must be destructured inside the component body from the props object.
export default function ProductDetail(props) {
// URL Parameters (e.g., [id])
const { id } = props.match.params;
// Passed State (Navigation object)
const { fromSearch } = props.location.state || {};
// Logic...
}
Programmatic Navigation¶
To navigate between screens in your Eitri-App, use the Eitri.navigation.navigate method:
// Navigate to Home page
Eitri.navigation.navigate({
path: "/Home",
});
// Navigate to a specific product
Eitri.navigation.navigate({
path: "/Product/12345",
});
// Navigate with state
Eitri.navigation.navigate({
path: "/Products",
state: { category: "electronics" },
});
For more information about available navigation methods, see the Eitri Bifrost documentation.
Dependencies¶
To understand how to manage and use dependencies in your Eitri-App, refer to the Managing Dependencies in Eitri-Apps guide.