Project Structure¶
Understanding the Tinko project organization is essential for effective development.
Directory Overview¶
edu-pi/
├── config/ # Django project configuration
│ ├── __init__.py
│ ├── settings.py # Main settings with plugin discovery
│ ├── urls.py # URL routing
│ ├── asgi.py # ASGI application (WebSocket)
│ └── wsgi.py # WSGI application
├── core/ # Core functionality
│ ├── edupi_core/ # Main Django app
│ │ ├── views.py # Dashboard views
│ │ ├── urls.py # App URLs
│ │ └── templates/ # Core templates
│ └── plugin_system/ # Plugin framework (IMPORTANT!)
│ ├── __init__.py
│ ├── base.py # PluginBase class
│ ├── manager.py # PluginManager
│ ├── models.py # Plugin models
│ ├── admin.py # Admin interfaces
│ └── views.py # Plugin management views
├── plugins/ # Plugin directory (auto-discovered)
│ ├── __init__.py
│ └── edupi/ # Built-in plugins
│ ├── activity_timer/
│ ├── noise_monitor/
│ ├── routines/
│ └── touch_piano/
├── templates/ # Global HTML templates
│ ├── base.html # Base template
│ ├── home.html # Dashboard
│ └── ...
├── static/ # Static assets (CSS/JS/images)
│ ├── css/
│ ├── js/
│ └── images/
├── locale/ # Translation files
│ ├── en/
│ └── ro/
├── tests/ # Test suite
│ ├── __init__.py
│ └── conftest.py # pytest fixtures
├── docs/ # Documentation
│ └── ...
├── scripts/ # Utility scripts
│ └── compile_translations.py
├── manage.py # Django management script
├── pyproject.toml # Project configuration
├── uv.lock # Dependency lock file
└── .env # Environment variables
Key Components¶
config/ Directory¶
Contains Django project configuration:
- settings.py: Main configuration with plugin auto-discovery
- urls.py: Root URL routing
- asgi.py: ASGI application for WebSocket support
- wsgi.py: Traditional WSGI application
core/ Directory¶
core/edupi_core/¶
The main Django application:
- views.py: Dashboard and home page views
- urls.py: URL routes for core functionality
- templates/: Global templates (base.html, home.html)
core/plugin_system/ (CRITICAL!)¶
The plugin framework - this is where plugin magic happens:
base.py
Contains the PluginBase class that all plugins must inherit:
class PluginBase:
def boot(self): ...
def register(self): ...
def uninstall(self): ...
def register_gpio_pins(self, pins): ...
def register_setting(self, key, label, **kwargs): ...
manager.py
PluginManager handles plugin loading and lifecycle:
class PluginManager:
def discover_plugins(self): ...
def load_plugin(self, path): ...
def enable_plugin(self, name): ...
def disable_plugin(self, name): ...
models.py
Database models for plugin system:
Plugin: Plugin metadata and statusPluginSetting: Plugin configuration storageGPIOPin: GPIO pin allocation tracking
plugins/ Directory¶
All plugins live here. The structure is:
plugins/
└── {author}/ # e.g., edupi, acme, etc.
└── {plugin_name}/ # e.g., activity_timer
├── __init__.py # Required: imports Plugin class
├── plugin.py # Required: Plugin registration
├── models.py # Optional: Django models
├── views.py # Optional: Views
├── urls.py # Optional: URL routes
├── forms.py # Optional: Forms
├── consumers.py # Optional: WebSocket consumers
├── routing.py # Optional: WebSocket routing
├── static/ # Optional: CSS/JS
├── templates/ # Optional: HTML templates
└── migrations/ # Auto-created: Database migrations
Built-in Plugins (plugins/edupi/)¶
- activity_timer/: Countdown timer with LED feedback
- noise_monitor/: Noise monitoring with dual RGB LEDs
- routines/: Text-to-speech routines with presenter support
- touch_piano/: Capacitive touch piano
templates/ Directory¶
Django template files:
- base.html: Master template with navigation, footer
- home.html: Dashboard showing all plugins
- Admin templates in
admin/
Templates use the Django template language with Tailwind CSS classes.
static/ Directory¶
Static assets served directly:
- css/: Stylesheets (Tailwind + custom)
- js/: JavaScript files
- images/: Logo, icons, etc.
Static files are collected with:
locale/ Directory¶
Translation files for internationalization:
locale/
├── en/
│ └── LC_MESSAGES/
│ └── django.po # English translations
└── ro/
└── LC_MESSAGES/
└── django.po # Romanian translations
tests/ Directory¶
Test suite using pytest:
- conftest.py: pytest configuration and fixtures
- Test files named
test_*.py
Auto-Discovery Mechanism¶
The plugin system automatically discovers plugins from plugins/:
- Scanning:
discover_plugin_apps()scansplugins/*/*/ - Detection: Directories with
__init__.pyare registered - Loading: Plugins added to Django's
INSTALLED_APPS - Boot: Plugin
boot()methods called - Register: Plugin
register()methods called
This happens in config/settings.py:
# Auto-discover plugins
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
# ...
] + discover_plugin_apps() # Automatically adds plugins
Plugin Namespace¶
Plugins are identified by namespace: {author}.{plugin_name}
Examples:
- edupi.activity_timer
- edupi.noise_monitor
- acme.weather_station
Import Paths¶
When importing within plugins, use full Python paths:
# From a plugin
from core.plugin_system.base import PluginBase
from plugins.edupi.activity_timer.models import TimerSession
# Django models
from django.db import models
Configuration Files¶
pyproject.toml¶
Project configuration including dependencies:
[project]
name = "edu-pi"
dependencies = [
"Django>=4.2",
"gpiozero>=2.0",
# ...
]
[project.optional-dependencies]
pi = [
"RPi.GPIO>=0.7.1",
"lgpio>=0.2",
]
uv.lock¶
Locked dependency versions - commit this file to ensure reproducible builds.
.env¶
Environment-specific settings (don't commit this!):
Development Guidelines¶
Adding a New File¶
- Determine the appropriate directory
- Follow naming conventions (snake_case)
- Update imports if needed
- Run tests to verify
Modifying Core Files¶
Be careful when modifying:
core/plugin_system/base.py- Affects all pluginsconfig/settings.py- Affects entire applicationconfig/urls.py- Affects URL routing
Always test thoroughly after changes.
Creating Plugins¶
See Plugin Tutorial for detailed instructions.
Next Steps¶
- Hardware Requirements - Connect GPIO components
- Plugin Tutorial - Create your first plugin
- Plugin API - Complete API reference
- GPIO Pins - Pin allocation reference