FGA Mobile Mini App Framework is a front-end product solution, implemented based on React, using the latest technology stack, built-in i18n solutions, dynamic routing, UI framework, status management, analysis tools and other rich functional components, which can quickly Help you build a Mini App product prototype.
The following external libraries are used in this framework:
- Ant Design Mobile: UI framework
- React i18n: Internationalization
- React Router: Dynamic routing
- Zusand: Status management
- React Icons: Icon library
- Tailwind CSS: CSS framework
- Floating buttons
- Popup menu
- Mini program feedback
- Mini program settings
- Mini program information
- Refresh, clear cache
- auto login
- Get user information (name, avatar, UID, Email)
- Get user token
- Support multiple languages
- Consistent with mobile language
- Based on Ant Design Mobile
- Built-in react-icons
- Built-in Tailwind CSS
*Built with Vite
- Built-in React and React Router
- Built-in Zustand state management
Before starting development, please fill out this form to request development resources: https://forms.gle/YLqFg3hJepD34TFA8
After successful application, you will get a Mini App config json file, which contains
- Github Repo
- Database
- Miniapp package information
example:
{
"github_repo": {
"repo_url": "https://github.com/fgacyc/app1",
"repo_invite": "https://github.com/fgacyc/app1/invitations"
},
"database": {
"username": "fgacyc.official",
"password": "Basdas32543oeAW",
"host": "ep-raspy-sun-45651351.ap-southeast-1.aws.neon.tech",
"port": "5432",
"database": "test",
"connect_string": "postgresql://fgacyc.official:Basdas32543oeAW@ep-raspy-sun-45651351.ap-southeast-1.aws.neon.tech:5432/test"
},
"package": {
"name": "app1",
"author": "FGACYC",
"version": "0.0.1",
"private": true,
"app_id": "6d4a87d19be141c881ed",
"shared": false,
"instagram": "https://www.instagram.com/fgacyc/",
"github": "https://github.com/fgacyc/",
"type": "module"
}
}Package parameter explanation:
- package.name: project name -> (1)
- package.version: author -> (2)
- package.author: version number -> (3)
- package.instagram: Author Instagram address -> (4)
- package.github: Author Github address/Project Repo address -> (5)
- package.shared: whether the application address can be copied for sharing -> (6)
Open the FGA Mobile Mini App Framework project: https://github.com/fgacyc/miniapp-framework-react Then create a new repository using the project target, and then clone the new repository locally.
- Create a project using a template
- Create a new repository
- Download the framework code
$ git clone <your-repo-url>Install dependencies
$ yarn installRun
$ yarn devIf you are using VSCode, it is recommended to install ESLint
Src
├── assets
├── components
├── locales
│ └── translation
├── pages
├── routes
└── store
- assets: store static resources
- components: stores shared components
- locales: used for internationalization configuration, translation files are stored in translation
- pages: store pages
- routes: store routes
- store: storage status management
Routes are located in src/routes/routes.tsx
export default function MainRoutes(){
return (
<Routes>
<Route path="/:UID" element={<Index />} />
<Route path="/" element={<Index />} />
<Route path="/about" element={<About />} />
<Route path="/settings" element={<Settings />} />
</Routes>
)
}6.1 Get URL parameters
https://example.com/room/123
<Route path="/room/:UID" element={<Room />} />import { useParams } from 'react-router-dom';
export default function Index(){
let { UID } = useParams();
return (
<div>
{UID}
</div>
)
}6.2 Obtain query parameters
https://example.com/room?name=fga
<Route path="/room" element={<Room />} />import { useLocation } from 'react-router-dom';
export default function Index(){
const [searchParams] = useSearchParams();
return (
<div>
{searchParams.get('name')}
</div>
)
}import NavBar from "@/components/nav-bar.jsx";
export default function About(){
return (
<div>
<NavBar ifShowBackArrow={true} url="">{t("About")}</NavBar ifShowBackArrow={true} url="">
</div>
)
}API: ifShowBackArrow: Whether to display the back button url: Back button jump address!
Visit: https://mobile.ant.design/zh/components/button
import { DemoBlock } from 'demos'
export default function Home() {
return (
<div>
<Button color='primary' fill='solid'>
Click me
</Button>
</div>
)
}See @page/framework/settings.js for more Ant Design Mobile UI components and usage examples.
The Mini App icon is located in public/app_icon.png and can be replaced with your own icon.
Icon requirements: 1024x1024, PNG format, non-transparent background, non-white background. Examples are as follows:
In this framework, we use the React Icons icon library You can find all the icons here, then click on the icon, copy the icon's code, and then paste it into your code to use.
import { RiCodeView } from "react-icons/ri";
export default function Index(){
return (
<div>
<RiCodeView />
</div>
)
}In Mini App, we use Zusand to implement state management, which can be achieved through simple configuration.
// store/index.js
import create from 'zustand';
export const useStore = create((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
decrement: () => set((state) => ({ count:state.count - 1 })),
}));// components/Counter.js
import { useStore } from './store';
export default function Counter() {
const count = useStore((state) => state.count);
const increment = useStore((state) => state.increment);
const decrement = useStore((state) => state.decrement);
return (
<div>
<h1>{count}</h1>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
</div>
);
}When opening the Mini App, user information, including name, avatar, UID (sub), email, etc., will be automatically obtained through the Token passed in by Mobile. It can be read in the following way
import { useUserStore } from './store';
export default function UserInfo() {
const user = useUserStore((state) => state.user);
return (
<div>
<h1>{user.name}</h1>
<img src={user.picture} alt="avatar" />
<p>{user.email}</p>
<p>{user.sub}</p>
</div>
);
}In the Mini App, we will need to use the user's identity information, such as which church the user is in, which group they are in, group role, service position, etc. At this time, we can obtain the user's identity information by calling the API.
- The API address is: https://identity.development.fgacyc.com
- API documentation address is: https://identity.development.fgacyc.com/docs
- In FGA Mobile App, enter the Mini App page and click Webview Tools
- In Webview Tools, copy Token
- Configure Bearer Token in API documentation
- View the interface in the API document
- View the returned results in the API documentation
The API is used to obtain user information through Bearer Token, for example:
const url = 'https://identity.development.fgacyc.com/connect-groups';
const token = 'YOUR_BEARER_TOKEN_HERE'; // Replace with your actual Bearer token
fetch(url, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
})
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return response.json();
})
.then(data => {
console.log('Data received:', data);
})
.catch(error => {
console.error('Error fetching data:', error);
});In Mini App, we use React i18n to achieve internationalization, and multi-language switching can be achieved through simple configuration. When the Mini App is opened, it will automatically switch the language according to Mobile's language settings. If the corresponding language is not found, English will be used by default.
Store the translated content in src/locales/translation, and you can define different translation content in different language files.
// src/locales/translation/en.json
{
"hello": "Hello",
"world": "World"
}// src/locales/translation/zh.json
{
"hello": "Hello",
"world": "world"
}import { useTranslation } from 'react-i18next';
export default function Index(){
const { t } = useTranslation();
return (
<div>
{t('hello')} {t('world')}
</div>
)
}Because the language is set according to Mobile's language setting by default, the language will be automatically switched when the Mini App is opened, so there is no need to switch manually. But if under special circumstances, you need to switch the language manually, you can do it in the following way.
import { useTranslation } from 'react-i18next';
export default function Index(){
const { i18n,t } = useTranslation();
return (
<div>
<div>
{t('hello')} {t('world')}
</div>
<button onClick={() => i18n.changeLanguage('en')}>English</button>
<button onClick={() => i18n.changeLanguage('zh')}>中文</button>
</div>
)
}In the FGA IT system, we use the PostgreSQL database uniformly. You can connect to the database through the provided database information and perform data reading and writing operations. In the Mini App config json file, the connection information of the database is provided.
{
"database": {
"username": "fgacyc.official",
"password": "Basdas32543oeAW",
"host": "ep-raspy-sun-45651351.ap-southeast-1.aws.neon.tech",
"port": "5432",
"database": "test",
"connect_string": "postgresql://fgacyc.official:Basdas32543oeAW@ep-raspy-sun-45651351.ap-southeast-1.aws.neon.tech:5432/test"
}
}You can connect to and operate the database through the following PostgreSQL GUI tools:
The bottom menu is a function provided by Mini App. It is located in src/components/action-sheet-menu.jsx. Some functions can be implemented through the bottom menu.
For example, refreshing, clearing cache, applet information, etc. can be configured to achieve different functions.
const buttonsData = [
{
text: 'Refresh',
icon: <ReloadOutlined />,
onClick: () => {
window.location.reload();
},
},
{
text: 'Clear Cache',
icon: <DeleteOutlined />,
onClick: () => {
localStorage.clear();
window.location.reload();
},
},
{
text: 'Settings',
icon: <SettingOutlined />,
onClick: () => {
navigate('/settings');
},
},
// ...
];You can turn off a function by commenting out unnecessary buttons. In particular, please do not turn on the development tool button in a production environment, as this will expose some sensitive information.
{
// ...
// title: "Dev",
// icon: <GoTools className={buttonStyle}/>,
// onClick: () => {
// setDevModal(true);
// setShowMenu(false);
// }
}Because in the Webview environment where Mini App is located, the navigation bar and debugging tools are hidden, so we need Some tools to help us develop. We can click the DEV button in the bottom menu to open the development tools
Currently, in the development tools, you can view the UID of the current user, the current language, the URL of the current Mini App, and the Local URL used for local development.
After the development is completed, the PM of Mini App will arrange the deployment. The deployment method is implemented through Cloudflare, so before submitting the code,
- Please ensure that the code can run normally.
- Ensure that all configuration items (such as PI Host, Database config, etc.) use environment variables and do not contain sensitive information.
- Make sure the code follows the team’s coding standards: https://airbnb.io/javascript/react/
After deployment, you will get a URL through which you can access the Mini App, but do not share this URL.
All Mini Apps run in Mobile Webview, so they have a certain degree of security. However, exposure to the browser environment may cause some security issues, such as user information leakage, API exposure, etc. So the URL of the Mini app is private, Only developers and testers have access in a browser environment.
After deployment is complete, you will get a JS snippet like the following:
<!-- Cloudflare Web Analytics --><script defer src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "a3aa602564655049c2a6ed65f"}'> </script><!-- End Cloudflare Web Analytics -->
Please add this snippet to the index.html of your Mini App so that you can view the access status of your Mini App in Cloudflare's monitoring platform.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/app_icon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>MiniApp + React</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
<!-- Cloudflare Web Analytics -->
<script defer src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "a3aa602564655049c2a6ed65f"}'></script>
<!-- End Cloudflare Web Analytics -->
</body>
</html>In Mini App, we provide a settings page src/pages/settings.jsx, through which you can set some Mini App configurations.
And there is a global state useSettingsStore to store these configurations (located in src/store/settings-store.js), and the configuration can be read and modified through this state.
To prevent accidentally leaking env variables to the client, only variables prefixed with VITE_ are exposed
VITE_SOME_KEY=123
console.log(import.meta.env.VITE_SOME_KEY) // "123"













