10 KiB
Asteroid Radio Web Server Implementation Summary
- Project Overview
- Initial State Analysis
- Dependency Changes and Rationale
- Implementation Details
- Errors Encountered and Solutions
- Current Project Status
- Technical Lessons Learned
- File Structure Summary
- Conclusion
Project Overview
This document summarizes the implementation of a basic web server for the Asteroid Radio project, a Common Lisp-based streaming radio station for "asteroid music for hackers."
Project Context
- Fork of https://github.com/fade/asteroid
- Goal: Create streaming radio station with web interface
- Started with basic Common Lisp framework skeleton
- Implemented web server as foundation for future streaming components
Initial State Analysis
Original Dependencies (asteroid.asd)
- :RADIANCE (web framework)
- :MITO (database ORM)
- :MITO-AUTH (authentication)
- :STR (string utilities)
- :PZMQ (ZeroMQ bindings)
- :SPINNERET (HTML generation)
Original Code Structure
asteroid.lisp- Main package with placeholder-mainfunctionapp-utils.lisp- Utility functions for debugger control and cross-platform quitdesign.org- Comprehensive feature specification and MVP roadmap
Dependency Changes and Rationale
Removed Dependencies
| Dependency | Reason for Removal |
|---|---|
| :RADIANCE | Requires separate Shirakumo dist installation, switched to simpler Hunchentoot for MVP |
| :MITO | Not available in default Quicklisp, not needed for basic web server |
| :MITO-AUTH | Not available in default Quicklisp, authentication not needed for MVP |
| :STR | Not used in current implementation |
| :PZMQ | Not needed for basic web server functionality |
Final Dependencies
| Dependency | Purpose | Justification |
|---|---|---|
| :RADIANCE | Web framework | Modular web framework with subdomain routing and integrated module system |
| :SPINNERET | HTML generation | Clean DSL for generating HTML, integrates well with Common Lisp |
| :CL-JSON | JSON encoding/decoding | Standard library for API endpoints |
Migration from Hunchentoot to RADIANCE
- Initial Choice: Started with Hunchentoot for simpler MVP setup
- Discovery: RADIANCE available via Shirakumo dist: `(ql-dist:install-dist "http://dist.shirakumo.org/shirakumo.txt")`
- Migration Completed: Successfully migrated to RADIANCE framework
- Benefits: RADIANCE provides modular architecture, subdomain routing, and integrated module system
- Result: More scalable foundation for future radio station features
Implementation Details
Web Server Architecture
- Framework: RADIANCE modular web framework
- Port: 8080 (default RADIANCE configuration)
- Module: asteroid (domain: "asteroid")
- Subdomain routing: asteroid.localhost:8080
- Server management:
radiance:startup/radiance:shutdown
Route Structure (RADIANCE)
| Route | Handler | Purpose | URL |
|---|---|---|---|
| / | index |
Main page with station status | http://asteroid.localhost:8080/ |
| /admin | admin |
Admin dashboard with controls | http://asteroid.localhost:8080/admin |
| /player | player |
Web player interface | http://asteroid.localhost:8080/player |
| /api/status | api/status |
JSON API endpoint | http://asteroid.localhost:8080/api/status |
HTML Generation Strategy
- Direct use of
spinneret:with-html-stringin each handler - Consistent hacker-themed styling (green text, black background)
- Responsive design with CSS embedded in each page
Errors Encountered and Solutions
Error 1: Missing MITO Dependency
Problem
debugger invoked on a ASDF/FIND-COMPONENT:MISSING-DEPENDENCY Component :MITO not found, required by #<SYSTEM "asteroid">
Root Cause
MITO and related database dependencies not available in Quicklisp distribution.
Solution
Removed unused dependencies from asteroid.asd:
- Removed :MITO, :MITO-AUTH, :STR, :PZMQ
- Kept only essential dependencies: :HUNCHENTOOT, :SPINNERET, :CL-JSON
Error 2: RADIANCE Framework Migration
Problem
Initially avoided RADIANCE due to perceived unavailability, implemented with Hunchentoot instead.
Root Cause
RADIANCE available via Shirakumo dist: `(ql-dist:install-dist "http://dist.shirakumo.org/shirakumo.txt")` but required additional setup step.
Solution
- Successfully migrated from Hunchentoot to RADIANCE
- Installed Shirakumo distribution for RADIANCE access
- Rewrote route handlers using
define-pagesyntax - Added
define-moduledeclaration for proper RADIANCE integration - Updated server management to use
radiance:startup/radiance:shutdown
Error 3: HTML Generation Function Signature Mismatch
Problem
The function GENERATE-PAGE-HTML is called with five arguments, but wants exactly two.
Root Cause
Initial generate-page-html helper function designed for single body argument, but called with multiple arguments.
Solution
Attempted fix with &rest parameter, but Spinneret macro expansion issues persisted.
Error 4: RADIANCE Route Syntax Issues
Problem
Module #<PACKAGE "ASTEROID"> requested but while the package exists, it is not a module. The value #@"asteroid/api/status" is not of type LIST
Root Cause
- Missing
define-moduledeclaration for RADIANCE integration - Incorrect route path syntax using
asteroid/prefix instead of module-relative paths - Wrong API endpoint definition syntax
Solution
- Added
define-moduledeclaration with proper domain specification - Fixed route paths:
#@"asteroid/"→#@"/",#@"asteroid/admin"→#@"/admin" - Updated API endpoint to use
define-pageinstead ofdefine-api - Fixed parentheses syntax errors in HTML generation
Error 5: Shell History Expansion Issues
Problem
zsh: event not found: ~ zsh: event not found: \
Root Cause
Zsh history expansion interfering with command-line arguments containing special characters.
Solution
Used single quotes instead of double quotes for SBCL command-line arguments to prevent shell interpretation.
Current Project Status
✅ Completed Features
- Basic web server running on localhost:8080
- Main page with station status display
- Admin dashboard with placeholder controls
- Web player interface (UI only)
- JSON API endpoint (/api/status)
- Hacker-themed consistent styling
- Proper error handling and server management
- Git upstream remote configuration
🎯 Current Capabilities
- Web server starts/stops cleanly
- All routes functional and accessible
- HTML generation working correctly
- JSON API returning structured data
- Responsive web interface
- Server management functions exported
🚀 Running the Server
RADIANCE Setup (One-time)
sbcl --eval '(ql-dist:install-dist "http://dist.shirakumo.org/shirakumo.txt")'
Command Line (One-shot execution)
sbcl --eval '(ql:quickload (quote (:radiance :spinneret :cl-json)))' \
--eval '(load "asteroid.asd")' \
--eval '(asdf:load-system :asteroid)' \
--eval '(asteroid:start-server)' \
--eval '(format t "Server running at http://asteroid.localhost:8080/ - Press Ctrl+C to stop")'
Interactive REPL
sbcl (ql:quickload '(:radiance :spinneret :cl-json)) (load "asteroid.asd") (asdf:load-system :asteroid) (asteroid:start-server) ;; Server now running at http://asteroid.localhost:8080/ ;; To stop: (asteroid:stop-server)
Available Functions
(asteroid:start-server)- Start RADIANCE server (non-blocking)(asteroid:stop-server)- Stop RADIANCE server cleanly(asteroid:run-server)- Start server and keep running (blocking, with Ctrl+C handler)
Access URLs
- Main page: http://asteroid.localhost:8080/
- Admin dashboard: http://asteroid.localhost:8080/admin
- Web player: http://asteroid.localhost:8080/player
- API endpoint: http://asteroid.localhost:8080/api/status
- RADIANCE welcome: http://localhost:8080/
📋 Next Steps (Not Implemented)
- Database integration (when MITO alternative chosen)
- Audio streaming backend (Liquidsoap integration)
- Icecast server integration
- File upload functionality
- Authentication system
- Real-time now-playing updates
- WebSocket integration for live updates
- Completed: ✅ Successfully migrated to RADIANCE framework
Technical Lessons Learned
Dependency Management
- Always verify dependency availability in target package manager
- Prefer widely-adopted, stable libraries over newer alternatives
- Keep dependency list minimal for initial implementation
Common Lisp Web Development
- RADIANCE provides modular architecture with subdomain routing
- Spinneret works best with direct macro usage, not through helper functions
- HTML generation should be kept simple and direct
- RADIANCE modules require proper
define-moduledeclarations - Route paths in RADIANCE are module-relative (use
#@"/"not#@"asteroid/")
Error Handling Strategy
- Compilation warnings often indicate runtime issues
- Test each component incrementally
- Use REPL for interactive debugging and testing
Development Workflow
- Start with minimal working version
- Add complexity incrementally
- Test each change immediately
- Keep fallback options for critical dependencies
File Structure Summary
asteroid/ ├── asteroid.asd # System definition (minimal dependencies) ├── asteroid.lisp # Main web server implementation ├── app-utils.lisp # Utility functions ├── design.org # Original project specification ├── test-server.lisp # Server testing script ├── project-summary.org # This document ├── Makefile # Build configuration └── LICENSE # AGPL v3 license
Conclusion
Successfully implemented and migrated a functional web server foundation for the Asteroid Radio project using RADIANCE framework. The server provides a complete web interface with admin controls, player interface, and API endpoints accessible via subdomain routing at asteroid.localhost:8080.
Key achievements:
- Framework Migration: Successfully migrated from Hunchentoot to RADIANCE
- Modular Architecture: Implemented proper RADIANCE module with subdomain routing
- Complete Web Interface: Main page, admin dashboard, web player, and JSON API
- Scalable Foundation: RADIANCE provides better architecture for future radio features
The implementation demonstrates the value of exploring framework alternatives and provides a robust, modular foundation ready for the next development phase: integrating audio streaming components (Liquidsoap/Icecast) and database functionality.