11 KiB

name version description trigger_conditions
web-application-spec 1.0.0 Standardized specification for web applications built with bricks frontend, ahserver backend framework, and apppublic/sqlor foundation modules.
User requests to create a new web application following the specified architecture
Task involves setting up application structure with ahserver, bricks, apppublic, sqlor
Development follows the documented directory structure and dependency requirements

Web Application Specification

Overview

This specification defines the standard architecture for web applications built using:

  • Frontend: bricks framework
  • Backend: ahserver application framework
  • Foundation: apppublic and sqlor modules
  • Optional Modules: appbase, rbac, and other developed modules

All web applications must follow this exact structure and configuration pattern.

Required Dependencies

Core Dependencies (Mandatory)

pip install git+https://git.opencomputing.cn/yumoqing/apppublic 
pip install git+https://git.opencomputing.cn/yumoqing/sqlor 
pip install git+https://git.opencomputing.cn/yumoqing/ahserver

Database Web Application Dependencies (If using database)

pip install git+https://git.opencomputing.cn/yumoqing/appbase
pip install git+https://git.opencomputing.cn/yumoqing/rbac

Application Directory Structure

${appname}/
├── app/
│   └── ${appname}.py              # Main application entry point
├── conf/
│   └── config.json                # Application configuration
├── files/                         # File storage directory
├── logs/                          # Log files directory
├── wwwroot/
│   ├── imgs/                      # SVG and image files
│   └── bricks/                    # Bricks framework distribution
├── build.sh                       # Initialization and deployment script
└── .env                           # Environment variables

File Specifications

app/${appname}.py (Main Application)

from ahserver.webapp import webapp
from ahserver.serverenv import ServerEnv

import bricks_for_python                          # registers bui processor
from bricks_for_python.init import load_pybricks  # registers UiWindow etc.
from appbase.init import load_appbase
from rbac.init import load_rbac

def get_module_dbname(m):
    return 'dbname'

def password_encode(s):
    if s is None:
        return ''
    from ahserver.globalEnv import password_encode as _orig
    return _orig(s)

def init():
    env = ServerEnv()                    # ← MUST be before load_rbac
    env.get_module_dbname = get_module_dbname
    env.password_encode = password_encode
    load_appbase()
    load_rbac()
    load_pybricks()

if __name__ == '__main__':
    webapp(init)

conf/config.json (Configuration)

Must include the following sections:

  • password_key: System encryption key
  • logger: Logging configuration with name, level, and file path
  • filesroot: File storage root path using $[workdir]$ placeholder
  • databases: Database connection configurations with driver and kwargs
  • website: Web server configuration including paths, processors, session settings

Key Configuration Patterns:

  • Use $[workdir]$ placeholder for work directory references
  • Database names in databases section must match get_module_name() return values
  • Critical: processors must include .tmpl → tmpl. The BricksUIProcessor (handler for .ui files) internally loads /bricks/header.tmpl and other templates. Without [".tmpl", "tmpl"], the app returns 500 'NoneType' has no attribute 'be_call' on / and /index.ui:
    "processors": [
        [".tmpl", "tmpl"],
        [".ui", "bui"],
        [".dspy", "dspy"]
    ]
    
  • Website processors must include .ui → bui and .dspy → dspy mappings
  • Website indexes: Must include "index.ui" for bricks-based apps. Without it, visiting / or /module/ returns 500 "invalid path" because ahserver cannot resolve directory URLs:
    "indexes": ["index.ui", "index.html"]
    
  • WebSocket support: Must include [".wss", "ws"] in processors list, otherwise .wss files are served as static files and WebSocket connections fail. Nginx /wss/ block strips the prefix via proxy_pass, so the backend receives the path without /wss (e.g., /module/file.wss).

WebSocket Configuration Details

When adding WebSocket (.wss) endpoints to a module:

  1. Backend config.json: Add [".wss", "ws"] to website.processors:

    "processors": [
        [".wss", "ws"],
        [".ws", "ws"],
        [".ui", "bui"],
        [".dspy", "dspy"]
    ]
    
  2. Nginx: The /wss/ location block handles WebSocket upgrade and strips the prefix:

    location /wss/ {
        proxy_pass http://localhost:9180/;   # strips /wss prefix
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }
    
  3. Frontend: Connect to /wss/module/file.wss (with /wss prefix):

    var url = protocol + '//' + host + '/wss/module/file.wss';
    var ws = new WebSocket(url);  // browser auto-sends cookie
    
  4. RBAC permissions: Register paths without /wss prefix (nginx strips it):

    python set_role_perm.py "logined" "/module/file.wss"
    
  5. Common pitfall: If ahserver logs handle as a normal file for a .wss request, the [".wss","ws"] processor mapping is missing from config.json. ahserver only recognizes extensions explicitly listed in processors.

build.sh (Deployment Script)

The build script must perform these operations in order:

A) Module Dependencies Setup

  1. Install xls2ddl tool: After creating virtual environment, install xls2ddl first:
    pip install xls2ddl
    
  2. Module Installation: Clone and pip install all required modules
  3. Database DDL Generation: For modules with models/ directory:
    • If models contain .xlsx files:
      cd models/
      xls2ddl mysql . > mysql.ddl.sql
      mysql -h db -u[user] -p[password] [dbname] < mysql.ddl.sql
      
    • If models contain .json files:
      cd models/
      json2ddl mysql . > mysql.ddl.sql
      mysql -h db -u[user] -p[password] [dbname] < mysql.ddl.sql
      
  4. Initial Data Import: For modules with data/ directory:
    dbloader $cdir [dbname] data.xlsx
    
  5. CRUD Generation: For modules with json/ directory:
    cd json/
    xls2ui -m ../models -o ../wwwroot ${modulename} *.json
    
  6. wwwroot Symlinking: Create symbolic links for each module:
    ln -s $cdir/pkgs/$m/wwwroot $cdir/wwwroot/$m
    

B) Bricks Framework Setup

  • Execute bricks build.sh and symlink dist directory:
    ln -s $cdir/pkgs/bricks/dist $cdir/wwwroot/bricks
    

C) System Service Configuration

  • Create systemd service file with proper user/group context
  • Generate start.sh and stop.sh scripts with environment loading
  • Enable and start the service on system boot

D) Cron Job Management

  • Add application-specific cron jobs without duplication

.env (Environment Variables)

  • Export all runtime environment variables required by the application
  • Include database credentials, API keys, and system paths

Build Script Requirements

Directory Creation

  • Create pkgs/ directory for module clones
  • Create logs/ directory for application logging

Module Processing Order

  1. Install foundation modules (apppublic, sqlor, ahserver, bricks)
  2. Clone and process database modules (appbase, rbac):
    • Clone from Git repositories to pkgs/ directory
    • Install via pip
    • Generate DDL from models/ directory (.xlsx or .json files)
    • Generate CRUD UI from json/ directory using xls2ui
  3. Install business modules (accounting, pricing, contract_management, etc.) following the same pattern as database modules

Database Operations

  • Process all modules that have models/, json/, or data/ directories (including appbase and rbac)
  • Use proper error handling for database operations
  • Maintain database isolation per module when configured
  • All module wwwroot directories must be symlinked to application wwwroot
  • Bricks dist directory must be symlinked to wwwroot/bricks

Service Management

  • Create proper systemd service with logging redirection
  • Implement graceful start/stop scripts
  • Set appropriate file permissions (chmod +x for scripts)

Bricks UI Development Pitfalls

See references/ragserver-pitfalls.md for complete debugging recipes. See references/sage-module-pitfalls.md for SQL column names, params_kw=None, deployment, and error investigation rules.

  • Widget id at top level (NOT in options)
  • DOM order for app.<id> resolution
  • .tmpl processor required in config
  • bricks_for_python import + load_pybricks() call
  • DataViewer response format ({status, data:{rows,total}})
  • Menu widget target pattern
  • Float model fields needing length + dec

Widget id at Top Level (Not in options)

// CORRECT
{"widgettype":"VBox","id":"main_content","options":{"css":"filler"}}
// WRONG — id inside options is ignored
{"widgettype":"VBox","options":{"id":"main_content","css":"filler"}}

DOM Order Affects app.<id> Resolution

Put the content area BEFORE the sidebar in subwidgets. Bricks initializes widgets left-to-right.

Configuration Best Practices

Security

  • Store sensitive data (passwords, keys) in encrypted form in config.json
  • Use environment variables for runtime secrets via .env file
  • Implement proper file permissions for logs and files directories

Performance

  • Configure appropriate client_max_size for file uploads
  • Set optimal session timeout values (session_max_time, session_issue_time)
  • Use Redis for session storage in production

Maintainability

  • Use consistent naming patterns across all configuration sections
  • Document custom processor mappings in website.processors
  • Maintain clear separation between development and production configurations

Verification Checklist

  • .tmpl → tmpl processor in website.processors (required for bricks UI, or / returns 500)
  • bricks_for_python imported and load_pybricks() called in init()
  • ServerEnv initialized BEFORE load_rbac() / load_appbase()
  • Website indexes config includes "index.ui" (required for directory URL resolution)
  • session_max_time and session_issue_time in config for Redis session persistence (restart won't lose login)
  • All required dependencies are installed from correct Git repositories
  • Application directory structure matches specification exactly
  • Main application file includes proper module loading pattern
  • Configuration file uses correct placeholders and structure
  • Build script handles all module types (foundation, database, business)
  • Database DDL generation works for all modules with models/
  • CRUD generation executes for all modules with json/
  • Initial data loads correctly for modules with data/
  • All wwwroot symlinks are created properly
  • Bricks framework is built and linked correctly
  • System service starts and stops gracefully
  • Environment variables are loaded from .env file
  • Application runs with proper logging and error handling