BFF Mode Guide
This guide explains what BFF mode means in Teleforge and how to turn the generated scaffold into something useful.
What BFF Mode Is
In Teleforge, BFF mode means:
- the Mini App still lives in
apps/web - the project also owns a Telegram-aware backend layer
- that backend can validate Telegram launch context, enforce auth and launch-mode rules, and talk to downstream services
Use BFF mode when the Mini App should not talk directly to every backend service by itself.
What the Scaffold Gives You
The generated BFF scaffold gives you:
apps/webwith Next.jsapps/apiwith placeholder route objectsteleforge.app.jsonwithruntime.mode: "bff"andruntime.apiRoutes
Important: the generated apps/api routes are placeholders, not a fully wired production server.
They show where your backend logic can live, but you still need to connect those routes to a real HTTP runtime.
The Practical Mental Model
Think of BFF mode as three layers:
- web UI in
apps/web - BFF route definitions in your server layer
- adapters/services that talk to your actual backend systems
Teleforge’s BFF package helps with layer 2.
Smallest Useful Route
At the package level, the core pattern is:
import { createBffConfig, defineBffRoute } from "@teleforgex/bff";
const config = createBffConfig({
botToken: process.env.BOT_TOKEN,
features: {
sessions: false
},
identity: {
adapter: myIdentityAdapter
}
});
const router = config.createRouter();
router.add(
defineBffRoute({
auth: "public",
async handler(_context, input: { message: string }) {
return {
message: input.message.toUpperCase()
};
},
method: "POST",
path: "/echo"
})
);
That route can then be exposed through the HTTP adapter you choose.
How apps/api Fits In
For generated projects, apps/api is the natural place to keep:
- route definitions
- adapter setup
- webhook entry points
- shared backend wiring
A practical structure is:
apps/api/src/routes/*.tsfor route definitionsapps/api/src/index.tsfor creating the configured router and HTTP handler
The generated health.ts and webhook.ts files are there to make that structure obvious, not to claim the BFF is already complete.
Service-Backed Routes
Use service-backed routes when the BFF should call a downstream API instead of implementing business logic inline.
defineBffRoute({
auth: "required",
method: "POST",
path: "/users/lookup",
service: {
name: "users",
operation: "lookup"
}
});
This is the right fit when your BFF is mainly an integration layer.
Session Exchange
If you enable sessions and provide the required adapters and JWT config, createBffConfig() can mount built-in session routes.
That is how you get routes such as:
/exchange/refresh/revoke
These are useful when Telegram identity needs to be turned into an app session.
What to Build First in BFF Mode
The highest-value first steps are:
- add one handler-backed route
- expose it through your server runtime
- validate Telegram launch/auth context on that route
- add one service-backed route when you need a downstream integration
Do not try to build the whole backend surface at once.