- Overview
- Directory Structure
- Manifest Format
- Configuration System
- Discovery and Activation
- Requirements System
- Configuration Overrides
- Game Access
- Integration with BBS Features
- Examples
- Installation
- Best Practices
- Security Considerations
- Troubleshooting
WebDoors is BinktermPHP's system for integrating external web-based games, applications, and terminal connections into the BBS. Each WebDoor is a self-contained application with its own manifest file that describes its capabilities, requirements, and configuration options.
WebDoors are displayed to users through the /games interface and can integrate with BBS features like storage, leaderboards, and the credits system.
WebDoors are installed in the public_html/webdoors/ directory. Each WebDoor resides in its own subdirectory:
public_html/webdoors/
├── blackjack/
│ ├── webdoor.json # Required manifest file
│ ├── index.php # Entry point
│ ├── icon.svg # Game icon
│ └── assets/ # Game assets
├── hangman/
│ ├── webdoor.json
│ ├── index.html
│ └── ...
└── revpol/
├── webdoor.json
├── index.php
└── ...
Each WebDoor must include a webdoor.json manifest file in its root directory. The manifest describes the game's metadata, requirements, and default configuration.
{
"webdoor_version": "1.0",
"game": {
"id": "unique-game-id",
"name": "Display Name",
"version": "1.0.0",
"author": "Author Name",
"description": "Brief description of the game",
"entry_point": "index.html",
"icon": "icon.svg",
"screenshots": []
},
"requirements": {
"min_host_version": "1.0",
"features": ["storage", "leaderboard", "credits"],
"permissions": ["user_display_name"]
},
"storage": {
"max_size_kb": 256,
"save_slots": 1
},
"multiplayer": {
"enabled": false
},
"config": {
"comment": "This is a comment that is for informational use only",
"custom_setting": "default_value"
}
}Version of the WebDoor specification. Current version is "1.0".
Core game metadata displayed to users.
id(string, required): Unique identifier for the game. Used in configuration and API calls.name(string, required): Display name shown in the games list.version(string, required): Game version (semantic versioning recommended).author(string, required): Creator or developer name.description(string, required): Brief description shown in the games list.entry_point(string, required): Entry file relative to the WebDoor directory (e.g.,"index.html","index.php").icon(string, optional): Icon filename relative to the WebDoor directory. Defaults to"icon.png".screenshots(array, optional): Array of screenshot filenames for future use.
Declares features and permissions the WebDoor needs.
min_host_version(string): Minimum BinktermPHP version required.features(array): List of BBS features the game requires:"storage": Persistent storage API"leaderboard": Leaderboard/high score API"credits": BBS credits system integration
permissions(array): User data the game needs access to:"user_display_name": Access to user's display name
Storage requirements for games that save user data.
max_size_kb(integer): Maximum storage size per user in kilobytes.save_slots(integer): Number of save slots per user.
Multiplayer capabilities (reserved for future use).
enabled(boolean): Whether the game supports multiplayer.
Default configuration values. These serve as defaults and can be overridden by the sysop in config/webdoors.json.
Common configuration keys:
comment: An informational comment for someone editing the JSONdisplay_name: Override the game's display namedisplay_description: Override the game's description- Game-specific settings (varies by WebDoor)
WebDoors are configured through the config/webdoors.json file. This file controls which games are enabled and allows sysops to customize game settings.
config/webdoors.json
{
"blackjack": {
"enabled": true,
"start_bet": 10,
"display_name": "21 Blackjack"
},
"hangman": {
"enabled": true
},
"revpol": {
"enabled": true,
"display_name": "Reverse Polarity BBS",
"display_description": "Connect to the Reverse Polarity BBS",
"host": "revpol.lovelybits.org",
"port": "22",
"proto": "ssh"
}
}enabled(boolean, required): Whether the game is active and visible to users.- Custom settings: Any settings defined in the manifest's
configsection can be overridden here. display_name(string, optional): Override the game's display name in the games list.display_description(string, optional): Override the game's description.
- Sysop Configuration (highest priority): Values in
config/webdoors.json - Manifest Defaults (fallback): Values in the WebDoor's
webdoor.jsonconfig section - Code Defaults (lowest priority): Hardcoded defaults in the WebDoor's code
The system automatically discovers WebDoors by:
- Scanning
public_html/webdoors/for subdirectories - Looking for
webdoor.jsonin each subdirectory - Parsing valid manifests and registering the WebDoor
WebDoors are activated by:
- Creating or editing
config/webdoors.json - Adding an entry for the game with
"enabled": true - The game immediately becomes available at
/games
Sysops can manage WebDoors through the admin interface at /admin/webdoors-config, which provides:
- List of discovered WebDoors
- JSON editor for
config/webdoors.json - Enable/disable controls
The requirements system ensures games only run when their dependencies are met.
Games can require BBS features:
"requirements": {
"features": ["storage", "leaderboard", "credits"]
}If a required feature is not available, the game is not shown in the games list.
Games can request access to user data:
"requirements": {
"permissions": ["user_display_name"]
}This declares what user information the game needs.
The system validates requirements before displaying games:
function checkManifestRequirements($manifest) {
$requirements = $manifest['requirements'] ?? [];
$features = $requirements['features'] ?? [];
// Check each required feature
foreach ($features as $feature) {
if (!isFeatureAvailable($feature)) {
return false;
}
}
return true;
}Sysops can customize how games appear to users:
In manifest (public_html/webdoors/blackjack/webdoor.json):
{
"game": {
"name": "Blackjack"
}
}In configuration (config/webdoors.json):
{
"blackjack": {
"enabled": true,
"display_name": "21 Card Game"
}
}Users will see "21 Card Game" instead of "Blackjack" in the games list.
Similarly, descriptions can be customized:
{
"blackjack": {
"enabled": true,
"display_description": "Classic card game - try to beat the dealer!"
}
}Game-specific settings from the manifest's config section can be overridden:
Manifest default:
{
"config": {
"start_bet": 10
}
}Sysop override:
{
"blackjack": {
"enabled": true,
"start_bet": 25
}
}Games are accessed through standardized URLs:
- Game list:
/games - Play game:
/games/{game-id}
Where {game-id} is the directory name of the WebDoor (e.g., /games/blackjack).
When a user accesses /games/blackjack, the system:
- Loads the WebDoor's manifest
- Applies any configuration overrides
- Serves the file specified in
entry_point - Injects BBS context (user info, session, etc.)
WebDoors run within authenticated user sessions. Games can access:
- Username
- Display name (with permission)
- User ID
- Session token
Games requiring persistent storage use the BBS storage API to save/load user data.
Games can submit high scores to the BBS leaderboard system for display on the main games page.
Games can integrate with the BBS credits/economy system to charge for plays or award winnings.
{
"webdoor_version": "1.0",
"game": {
"id": "mygame",
"name": "My Game",
"version": "1.0.0",
"author": "Your Name",
"description": "A simple HTML5 game",
"entry_point": "index.html",
"icon": "icon.png"
},
"requirements": {
"min_host_version": "1.0",
"features": ["leaderboard"]
}
}{
"webdoor_version": "1.0",
"game": {
"id": "phpapp",
"name": "PHP Application",
"version": "1.0.0",
"author": "Your Name",
"description": "Server-side PHP application",
"entry_point": "index.php",
"icon": "icon.svg"
},
"requirements": {
"min_host_version": "1.0",
"features": ["storage", "leaderboard", "credits"],
"permissions": ["user_display_name"]
},
"storage": {
"max_size_kb": 100,
"save_slots": 3
},
"config": {
"difficulty": "normal",
"max_players": 10
}
}{
"webdoor_version": "1.0",
"game": {
"id": "mybbs",
"name": "My BBS",
"version": "1.0.0",
"author": "Your Name",
"description": "Connect to my text-based BBS",
"entry_point": "index.php",
"icon": "icon.svg"
},
"requirements": {
"min_host_version": "1.0",
"permissions": ["user_display_name"]
},
"config": {
"display_name": "My BBS",
"display_description": "Connect to My BBS via telnet",
"host": "mybbs.example.com",
"port": "23",
"proto": "telnet"
}
}Sysop configuration (config/webdoors.json):
{
"mybbs": {
"enabled": true,
"display_name": "Community BBS",
"host": "bbs.example.org",
"port": "23",
"proto": "telnet"
}
}To install a new WebDoor:
-
Copy the WebDoor directory to
public_html/webdoors/:cp -r mygame/ public_html/webdoors/
-
Verify the manifest exists and is valid:
cat public_html/webdoors/mygame/webdoor.json
-
Enable the game in
config/webdoors.json:{ "mygame": { "enabled": true } } -
Access the game at
/gamesor directly at/games/mygame
- Use semantic versioning for game versions
- Provide meaningful descriptions that help users understand what the game does
- Declare all requirements your game needs
- Include an icon (SVG or PNG) for better visual presentation
- Test with configuration overrides to ensure defaults work
- Document custom config options in your game's README
- Keep entry points simple - use
index.htmlorindex.php - Use unique game IDs that won't conflict with other WebDoors
- User input validation: Always validate and sanitize user input
- Path traversal: Don't allow users to specify file paths
- SQL injection: Use prepared statements for database queries
- XSS protection: Escape output when displaying user-generated content
- Authentication: WebDoors run in authenticated sessions - verify the user
- File permissions: Ensure game files are readable but not writable by web server
- Configuration validation: Validate configuration values from
config/webdoors.json
- Verify
webdoor.jsonexists and is valid JSON - Check that the game is enabled in
config/webdoors.json - Ensure requirements are met (features, permissions)
- Check file permissions on the WebDoor directory
- Verify
config/webdoors.jsonsyntax - Check that configuration keys match those in the manifest
- Restart PHP-FPM if using opcache
- Clear browser cache
- Verify
entry_pointpath is correct relative to WebDoor directory - Check file permissions on the entry point file
- Look for PHP errors in web server error log