Nyota Digital (Swahili for Star) is a modern, self-hosted digital distribution engine designed for creators. It empowers photographers, musicians, designers, educators, and any digital producer to sell their work directly to their audience with radical simplicity.
The core philosophy of Nyota is to eliminate friction for both the creator and their customers. It features secure, passwordless authentication (TOTP for creators) and instant, verified access for buyers via phone + purchase date. This project is built to empower modern digital creators with a tool that is both powerful and beautiful.
- Self-Hosted & Sovereign: You own your platform, your data, and your customer relationships. No third-party commissions.
- Secure Admin Access: Passwordless 2FA using Time-based One-Time Passwords (TOTP) for creators.
- Intuitive Asset Management: Multi-step wizard for creating and managing:
- One-time purchases (e-books, photo packs, templates)
- Subscriptions (video courses, newsletters)
- Event tickets and webinar access
- Real-time Analytics: Track sales, revenue, and customer engagement
- Multi-Language Support: Built-in internationalization (i18n) for English and Swahili
- No Accounts Required: Buyers access their library using their phone number + purchase date - no passwords to remember
- Resilient Payment Verification:
- Real-time updates via Server-Sent Events (SSE)
- Database polling fallback for reliability
- Works even if browser is closed during payment
- 90-Day Sessions: Secure, long-lasting sessions with HTTPONLY and SAMESITE protection
- Account Switching: Easy profile display with ability to switch between purchases
- Rate-Limited Access: Aggressive throttling (3 attempts/15min) prevents unauthorized access
- UZA Callback Protection: Webhook verification with configurable secret keys
- Session Security: HTTPONLY cookies, SAMESITE protection, 90-day lifetime
- Rate Limiting: IP-based throttling prevents brute force attacks
- Audit Logging: All access attempts tracked in
AccessAttempttable - Payment Resilience: Dual-track verification (SSE + HTTP polling) ensures no missed payments
- Backend: Python 3.9+, Flask, SQLAlchemy, Gunicorn
- Database: SQLite (development), PostgreSQL-ready
- Frontend: HTML5, Tailwind CSS, Alpine.js
- Containerization: Docker, Docker Compose
- Payment Gateway: UZA Payments integration
- Asynchronous: Server-Sent Events (SSE) for real-time updates
.
βββ locales/ # Language files (en.json, sw.json)
βββ migrations/ # Database migration scripts
βββ models/
β βββ nyota.py # All SQLAlchemy models (including AccessAttempt)
βββ static/
β βββ css/
β βββ js/ # main.js (customer), admin_main.js (creator)
βββ templates/
β βββ admin/ # Templates for Creator Hub
β βββ user/ # Public storefront templates
βββ utils/
β βββ security.py # Authentication helpers (TOTP, decorators)
β βββ translator.py # Backend translation utility
βββ .env.sample # Environment variable template
βββ config.py # Flask configuration (session security, paths)
βββ docker-compose.yml # Docker service definitions
βββ Dockerfile # Application container definition
βββ main.py # Flask application factory
βββ Makefile # Developer command shortcuts
βββ mock_data.py # Mock data for development
βββ requirements.txt # Python dependencies
βββ routes.py # All Flask routes
βββ wsgi.py # WSGI entry point for Gunicorn
- Docker & Docker Compose
-
Clone the Repository
git clone <your-repository-url> cd nyota-digital
-
Create Environment File
cp .env.sample .env
-
Build and Start
make up
-
Run Database Migrations
docker-compose exec app flask db upgrade -
Access the Application
- Storefront: http://localhost:5000
- Creator Hub: http://localhost:5000/admin
make up- Build and start containers in backgroundmake start- Start with live logsmake stop- Stop and remove containersmake logs- View application logsmake shell- Open shell in app container
After modifying models/nyota.py:
# Generate migration
docker-compose exec app flask db migrate -m "Description of changes"
# Apply migration
docker-compose exec app flask db upgrade- Go to Admin > Settings > Integrations > UZA Payments
- Set a strong Callback Secret
- Update your UZA dashboard webhook URL:
https://your-domain.com/api/uza-callback?secret=YOUR_SECRET
In production, set these environment variables:
SECRET_KEY=your-strong-secret-key
SESSION_COOKIE_SECURE=True # Requires HTTPS- Visit
/adminand create a username - Scan QR code with authenticator app (Google Authenticator, Authy)
- Verify with 6-digit code
- Log in anytime using username + authenticator code
- Create and manage digital assets via intuitive wizard
- Discover asset on social media
- Click "Purchase" and enter phone number
- Complete payment via USSD push
- Access library instantly (or anytime later)
- To access again: Enter phone number + purchase date
- Switch between accounts easily from profile display
Ensures payment confirmation even in adverse network conditions:
- Primary: Server-Sent Events (SSE) for instant updates
- Fallback: HTTP polling every 5 seconds to
/api/check-payment-status - Persistence: Database-backed status survives server restarts
No session? No problem:
- Enter phone number + purchase date
- System verifies against completed purchases
- Rate limiting prevents abuse (3 attempts = 15min lockout)
- All attempts logged for security monitoring
Built-in support for multiple languages:
locales/en.json- Englishlocales/sw.json- Swahili
Template usage:
{{ translate('key_name') }}Backend usage:
from utils.translator import translate
message = translate('key_name')- Alpine.js for reactive components
- Tailwind CSS for styling
- Server-Sent Events for real-time updates
- Mobile-first responsive design
creator- Admin accountscreator_setting- Key-value configuration storedigital_asset- Products/contentcustomer- Buyers (phone-based)purchase- Transaction recordsaccess_attempt- Rate limiting & security audit
AccessAttemptmodel for tracking library access attempts- Enhanced session security configuration
- Payment status check endpoint
This project follows modern Flask best practices:
- Blueprint-based routing
- Application factory pattern
- Database migrations with Alembic
- Environment-based configuration
Built with β€οΈ for digital creators everywhere