Project Structure¶
This document provides a detailed overview of Trunk8's project structure and file organization.
Directory Overview¶
trunk8/
├── app/ # Main application package
├── debug/ # Debug utilities (optional)
├── docs/ # MkDocs documentation
├── tests/ # Test suite
├── users/ # Multi-user data storage (NEW)
│ ├── users.toml # User management data
│ ├── admin/ # Admin user data
│ │ ├── links.toml # Admin's links
│ │ └── assets/ # Admin's files
│ └── {username}/ # Other users' data
│ ├── links.toml # User's links
│ └── assets/ # User's files
├── config/
│ ├── config.toml # Application configuration
│ └── themes.toml # Available themes
├── Dockerfile # Docker configuration
├── LICENSE # MIT license
├── mkdocs.yml # Documentation config
├── pyproject.toml # Project metadata
├── pytest.ini # Pytest configuration
├── README.md # Project readme
├── run.py # Application entry point
├── TODO.md # Development tasks
└── uv.lock # Dependency lock file
Core Application (app/
)¶
Application Package Structure¶
app/
├── __init__.py # Application factory
├── auth/ # Authentication blueprint
│ ├── __init__.py # Blueprint registration
│ ├── decorators.py # Login required decorator
│ └── routes.py # Login/logout routes
├── links/ # Links management blueprint
│ ├── __init__.py # Blueprint registration
│ ├── models.py # Link data model
│ ├── routes.py # CRUD routes
│ └── utils.py # Helper functions
├── main/ # Main routes blueprint
│ ├── __init__.py # Blueprint registration
│ └── routes.py # Home, settings routes
├── utils/ # Shared utilities
│ ├── __init__.py # Module init
│ └── config_loader.py # Configuration management
├── static/ # Static assets
│ ├── css/ # Stylesheets
│ ├── img/ # Images
│ └── js/ # JavaScript
└── templates/ # Jinja2 templates
Key Files Explained¶
app/__init__.py
¶
The application factory that:
- Creates Flask instance
- Registers blueprints
- Sets up configuration
- Defines template filters
- Handles request hooks
def create_app() -> Flask:
"""Application factory pattern."""
app = Flask(__name__)
# Configuration and setup...
return app
app/auth/
¶
Authentication module handling:
- User login/logout
- Session management
- Access control decorators
Key components:
decorators.py
:@login_required
decoratorroutes.py
:/auth/login
and/auth/logout
endpoints
app/links/
¶
Core functionality for link management:
models.py
:Link
class for data representationroutes.py
: CRUD operations for linksutils.py
: File handling, expiration checks
app/main/
¶
General application routes:
- Home page (
/
) - Settings page (
/settings
) - Context processors
app/utils/
¶
Shared utilities:
config_loader.py
: TOML configuration management- Automatic reloading
- Default value creation
- Multi-file support
Static Assets (app/static/
)¶
static/
├── css/
│ └── style.css # Custom styles
├── img/
│ └── trunk8_logo.png # Application logo
└── js/
└── main.js # Custom JavaScript
Asset Organization¶
- CSS: Custom styles supplementing Bootstrap
- Images: Logo and UI assets
- JavaScript: Interactive features
Templates (app/templates/
)¶
templates/
├── base.html # Base template with layout
├── index.html # Home page
├── login.html # Login form
├── add_link.html # Add link form
├── edit_link.html # Edit link form
├── list_links.html # Links listing
├── link_created.html # Success message
├── link_not_found.html # 404 page
├── markdown_render.html # Markdown display
└── settings.html # Settings interface
Template Hierarchy¶
base.html
: Master template with navbar and layout- Other templates extend base using Jinja2 inheritance
- Consistent Bootstrap styling throughout
Configuration Files¶
config/config.toml
¶
Application settings:
[app]
theme = "cerulean"
markdown_theme = "cerulean"
max_file_size_mb = 100
[session]
permanent_lifetime_days = 30
User Data Storage (users/
)¶
Multi-user data organization:
users/users.toml
- User management:
[users.admin]
password_hash = "hashed_password"
is_admin = true
display_name = "Administrator"
created_at = "2024-01-01T00:00:00"
users/{username}/links.toml
- Per-user links:
[links.example]
type = "redirect"
url = "https://example.com"
expiration_date = "2024-12-31T23:59:59"
Note: Each user has isolated data storage in their own directory.
config/themes.toml
¶
Available themes catalog:
Test Suite (tests/
)¶
tests/
├── __init__.py # Test package
├── conftest.py # Pytest fixtures
├── test_auth.py # Auth tests
├── test_config_loader.py # Config tests
├── test_integration.py # E2E tests
├── test_links.py # Links tests
├── test_main.py # Main routes tests
├── test_models.py # Model tests
├── README.md # Test documentation
└── TEST_RESULTS.md # Test outcomes
Test Organization¶
- Unit tests for individual components
- Integration tests for workflows
- Fixtures in
conftest.py
for reusability - Clear naming convention:
test_*.py
Documentation (docs/
)¶
docs/
├── index.md # Documentation home
├── getting-started/ # Installation guides
├── user-guide/ # User documentation
├── configuration/ # Config reference
├── development/ # Developer guides
├── api/ # API documentation
├── deployment/ # Deployment guides
└── reference/ # Additional resources
Documentation Structure¶
- Getting Started: Quick installation and setup
- User Guide: Feature documentation
- Configuration: Detailed config options
- Development: Contributing guidelines
- API Reference: Code documentation
- Deployment: Production guides
Project Files¶
run.py
¶
Application entry point:
from app import create_app
app = create_app()
if __name__ == "__main__":
# Get port from environment variable, default to 5001
port = int(os.environ.get("TRUNK8_PORT", 5001))
app.run(
debug=True, host="0.0.0.0", port=port
)
pyproject.toml
¶
Project metadata and dependencies:
[project]
name = "trunk8"
version = "0.2.0"
dependencies = [
"flask>=3.1.1",
"gunicorn>=23.0.0",
# ...
]
Dockerfile
¶
Container configuration:
FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim
# Application setup...
CMD ["gunicorn", "run:app"]
mkdocs.yml
¶
Documentation configuration:
File Naming Conventions¶
Python Files¶
- Snake_case:
config_loader.py
- Descriptive names:
routes.py
,models.py
- Test prefix:
test_*.py
Templates¶
- Snake_case:
add_link.html
- Action-based:
edit_link.html
- State-based:
link_created.html
Static Assets¶
- Lowercase:
style.css
,main.js
- Descriptive:
trunk8_logo.png
Import Structure¶
Absolute Imports¶
from app import create_app
from app.auth.decorators import login_required
from app.links.models import Link
Relative Imports (within package)¶
Adding New Features¶
Creating a New Blueprint¶
- Create directory:
app/feature/
-
Add
__init__.py
: -
Create
routes.py
- Register in
app/__init__.py
Adding Templates¶
- Create template in
app/templates/
- Extend base template
- Use consistent styling
Adding Static Files¶
- Place in appropriate
static/
subdirectory - Reference using
url_for('static', filename='...')
Build and Deployment¶
Local Development¶
Production¶
Docker¶
Security Considerations¶
Sensitive Files¶
- Never commit
.env
files - Keep
config/config.toml
secure - Protect
links.toml
data
File Permissions¶
Maintenance¶
Regular Tasks¶
- Clear old files from
assets/
- Backup
*.toml
files - Update dependencies
- Review security
Monitoring¶
- Check
assets/
disk usage - Monitor log files
- Track configuration changes
Future Structure Changes¶
Planned Additions¶
app/api/
- REST API endpointsmigrations/
- Database migrationsapp/models/
- Shared data modelsscripts/
- Utility scripts
Development Tips¶
Finding Files¶
# Find all route files
find . -name "routes.py"
# Find templates
find . -name "*.html"
# Search in code
grep -r "login_required" app/
Making Changes¶
- Identify affected components
- Update code and tests
- Update documentation
- Test thoroughly
Conclusion¶
This structure provides: - Clear separation of concerns - Easy navigation - Scalable architecture - Maintainable codebase
Follow the established patterns when adding new features to maintain consistency.