This is a template for creating apps for the TT-BBS system. It demonstrates how to build BBS apps that leverage the platform's data services.
- MongoDB Integration: Uses the platform's data services to store and retrieve data without direct database access
- Service-Based Architecture: Works with the BBS platform's service injection pattern
- User Data Storage: Demonstrates how to store and retrieve user-specific data
- Persistent App State: Shows how to maintain app state across sessions
- Clean Command Handling: Structured approach to handling user commands
The TT-BBS platform uses a service-based architecture that allows apps to access the MongoDB database through controlled interfaces. This template demonstrates the recommended patterns for working with these services.
In the production environment, the BBS platform will inject service objects into your app during initialization. These services provide controlled access to:
- General app storage
- User-specific storage
- Session management
- User information
- Utility functions
The platform provides three types of key-value storage:
-
App Storage: For app-wide data (accessible via
services.storage
) -
User Storage: For user-specific data (accessible via
services.getUserStorage(userId)
) -
Namespaced Storage: For categorized data (accessible via
services.getNamespacedStorage(namespace)
)
While the BBS app interface requires synchronous methods, this template demonstrates how to perform asynchronous operations in the background while providing immediate responses to users.
To create your own app based on this template:
- Copy this template
- Modify the app metadata (id, name, version, etc.)
- Implement your custom commands in the
handleCommand
method - Define your screens and navigation flow
- Don't Access MongoDB Directly: Always use the provided service methods to interact with the database
- Handle Service Availability: Check if services are available before using them
- Background Processing: Perform time-consuming operations in the background
- Immediate Responses: Always provide immediate feedback to users, even if data is still loading
- Error Handling: Implement proper error handling for service operations
// Example of using the storage service
function incrementCounter() {
if (!appServices) return;
appServices.storage.getData('counter')
.then(counter => {
const newValue = (counter || 0) + 1;
return appServices.storage.setData('counter', newValue);
})
.then(() => {
console.log('Counter incremented successfully');
})
.catch(error => {
console.error('Error incrementing counter:', error);
});
}
// Example of using user-specific storage
function saveUserPreference(userId, preference, value) {
if (!appServices) return;
const userStorage = appServices.getUserStorage(userId);
userStorage.getData('preferences')
.then(preferences => {
const updatedPreferences = { ...(preferences || {}), [preference]: value };
return userStorage.setData('preferences', updatedPreferences);
})
.then(() => {
console.log(`User preference '${preference}' saved`);
})
.catch(error => {
console.error('Error saving user preference:', error);
});
}
All data stored through the services is automatically persisted in MongoDB. The platform handles all database connectivity, allowing app developers to focus on creating great user experiences.
- Clone this template or create a new project with it.
- Update the package.json with your app information.
- Implement your app in src/index.ts.
- Build and publish your app to npm.
Your app must implement the BbsApp
interface:
interface BbsApp {
id: string; // Unique identifier for the app
name: string; // Display name for the app
version: string; // App version
description: string; // App description
author: string; // App author
// Core methods that must be implemented
getWelcomeScreen: () => string;
handleCommand: (screenId: string | null, command: string, session: any) => CommandResult;
getHelp: (screenId: string | null) => string;
// Optional lifecycle hooks
onInit?: () => void;
onUserEnter?: (userId: string, session: any) => void;
onUserExit?: (userId: string, session: any) => void;
}
interface CommandResult {
screen: string | null; // Screen to display (null means exit the app)
response: string; // Text response to display
refresh: boolean; // Whether to refresh the whole screen
data?: any; // Optional data to pass back to the client
}
- Loading: The BBS finds and loads your app when it starts.
-
Initialization: The
onInit
method is called. -
User Entry: When a user selects your app from the main menu, the system calls
getWelcomeScreen
. -
Command Handling: All user input is routed to your
handleCommand
method. -
Help: When a user types HELP, the system calls your
getHelp
method. -
Exit: When your app returns a CommandResult with
screen: null
, the user exits to the main menu.
Your app can have multiple screens, identified by string IDs. The system tracks the current screen in the format appId:screenId
.
The default screen is 'home', which is set when a user first enters your app.
Your app can define any commands it wants. The convention is to use uppercase for command names, but this is up to you. Commands are typically parsed in the handleCommand
method.
Common patterns:
- Return to the main screen: Set
screen: 'home'
- Exit the app: Set
screen: null
- Navigate to another screen: Set
screen: 'another-screen'
-
Update your app information:
npm init
-
Build your app:
npm run build
-
Publish to npm:
npm publish
Check out the src/index.ts file for a basic example app that demonstrates the core concepts.
MIT