Create an app without a backend
An ActivityPods app doesn’t always need a backend. If it only reads and writes the data of the logged-in user, a frontend is enough: its description and its access needs can be served as static files.
This guide shows you how to generate these files with @activitypods/app-manifest. The frontend-only example app is a complete example of the result.
Is it the right choice ?
Without a backend, your app can’t:
- Do anything when the user is not using it, such as sending notifications or reacting to activities.
- Access the data other users have shared, as this requires signing requests.
- Store data of its own, outside of the Pods of its users.
If you need any of these, follow the guide Create your first social app instead.
Set up the manifest
This guide assumes you have a Refine app using Vite. See the frontend introduction to install the Refine packages.
In your frontend directory, run:
npx @activitypods/app-manifest initIt asks for the name and the description of your app, creates an app-manifest.json file and installs the package.
Then add the plugin to your Vite configuration:
import { defineConfig } from 'vite';import react from '@vitejs/plugin-react';import { appManifest } from '@activitypods/app-manifest/vite';
export default defineConfig({ plugins: [react(), appManifest()]});If you use TypeScript, add this line to your vite-env.d.ts file:
/// <reference types="@activitypods/app-manifest/client" />Configure the auth provider
The plugin provides the client ID of your app, so you don’t have to write its URL:
import { authProvider as apAuthProvider } from '@activitypods/refine-providers';import { clientId } from 'virtual:app-manifest';
export const authProvider = apAuthProvider({ clientId, // Already done by the BackgroundChecks component appStatusCheckInterval: false});Use the BackgroundChecks component around your authenticated routes. It sends the user to the authorization screen as soon as they open the app, if its access needs have changed:
import { Authenticated } from '@refinedev/core';import { ThemedLayout } from '@refinedev/antd';import { CatchAllNavigate } from '@refinedev/react-router';import { Outlet } from 'react-router';import { BackgroundChecks } from '@activitypods/refine-antd';
<Authenticated key="authenticated-routes" fallback={<CatchAllNavigate to="/login" />}> <ThemedLayout> <BackgroundChecks> <Outlet /> </BackgroundChecks> </ThemedLayout></Authenticated>;Mount the LoginPage component on the /login route, as explained on the auth provider page. The generated documents use this route to bring the user back to your app.
Declare the access needs
To say which data your app needs, run:
npx app-manifest addThe command lists the shapes of the shape repository, with the number of apps using them, as well as the special rights. You can filter them by typing a word after the command:
npx app-manifest add messageIt then asks if the access is required, and if your app needs to read or also to write the data. To skip the questions, for example in a script, use the options:
npx app-manifest add as/Note --write --requirednpx app-manifest add apods:ReadInbox --optionalThe result is written to app-manifest.json, which you can also edit by hand. Use npx app-manifest list to see what is declared, and npx app-manifest check to verify that the shape trees exist.
If you can’t find the right shape, you can create your own shape tree, or propose one on the shape repository. To add a shape tree hosted elsewhere, pass its URI to npx app-manifest add.
The data provider must know which shape tree each resource uses:
import { dataProvider as apDataProvider } from '@activitypods/refine-providers';
export const dataProvider = apDataProvider({ authProvider, resources: { posts: { shapeTreeUri: 'https://shapes.activitypods.org/shapetrees/as/Note' } }});Run the app
Start your app with yarn dev, then log in with an account on a Pod provider. The Pod provider must be able to reach your app: in development, it must run on the same machine.
The frontend-only example app includes a docker-compose.yml file to run a local Pod provider. You should see the authorization screen, with the access needs you declared.
Change the access needs
Users are asked for their consent again when the access needs of your app change. You only have to edit the manifest and deploy your app.
| Change | What the user sees |
|---|---|
| New required access need or special right | The authorization screen, with only what is new |
| New optional access need | The authorization screen, where they can refuse it |
| Access need or special right removed | Nothing: the upgrade is done automatically |
| Fewer access modes on an access need | Nothing: the upgrade is done automatically |
| Other changes, such as the name of the app | Nothing |
With BackgroundChecks, the check is done when the app is opened, then every two minutes and each time the user comes back to the tab.
Deploy to production
Set PUBLIC_URL to the URL of your app when building:
PUBLIC_URL=https://example.app yarn buildThen serve the output directory with any static web server, with two conditions:
-
The JSON documents must be served with the header
Access-Control-Allow-Origin: *. Otherwise, the authorization screen can’t read your access needs. For example,serveneeds an option:Terminal window serve -s dist --cors -
The URL of your app must not change. It identifies your app in the Pods of your users: with a new URL, they would have to register the app again.