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.”
- 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
- :RADIANCE (web framework)
- :MITO (database ORM)
- :MITO-AUTH (authentication)
- :STR (string utilities)
- :PZMQ (ZeroMQ bindings)
- :SPINNERET (HTML generation)
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 | 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 |
| 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 |
- **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
- 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 | 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 |
- 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
debugger invoked on a ASDF/FIND-COMPONENT:MISSING-DEPENDENCY Component :MITO not found, required by #<SYSTEM "asteroid">
MITO and related database dependencies not available in Quicklisp distribution.
Removed unused dependencies from asteroid.asd:
- Removed :MITO, :MITO-AUTH, :STR, :PZMQ
- Kept only essential dependencies: :HUNCHENTOOT, :SPINNERET, :CL-JSON
Initially avoided RADIANCE due to perceived unavailability, implemented with Hunchentoot instead.
RADIANCE available via Shirakumo dist: `(ql-dist:install-dist “http://dist.shirakumo.org/shirakumo.txt”)` but required additional setup step.
- 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
The function GENERATE-PAGE-HTML is called with five arguments, but wants exactly two.
Initial generate-page-html helper function designed for single body argument, but called with multiple arguments.
Attempted fix with &rest parameter, but Spinneret macro expansion issues persisted.
Module #<PACKAGE "ASTEROID"> requested but while the package exists, it is not a module. The value #@"asteroid/api/status" is not of type LIST
- Missing
define-moduledeclaration for RADIANCE integration - Incorrect route path syntax using
asteroid/prefix instead of module-relative paths - Wrong API endpoint definition syntax
- 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
zsh: event not found: ~ zsh: event not found: \
Zsh history expansion interfering with command-line arguments containing special characters.
Used single quotes instead of double quotes for SBCL command-line arguments to prevent shell interpretation.
- [X] Basic web server running on localhost:8080
- [X] Main page with station status display
- [X] Admin dashboard with placeholder controls
- [X] Web player interface (UI only)
- [X] JSON API endpoint (/api/status)
- [X] Hacker-themed consistent styling
- [X] Proper error handling and server management
- [X] Git upstream remote configuration
- 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
sbcl --eval '(ql-dist:install-dist "http://dist.shirakumo.org/shirakumo.txt")'
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")'
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)
(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)
- **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/
- 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
- Always verify dependency availability in target package manager
- Prefer widely-adopted, stable libraries over newer alternatives
- Keep dependency list minimal for initial implementation
- 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/")
- Compilation warnings often indicate runtime issues
- Test each component incrementally
- Use REPL for interactive debugging and testing
- Start with minimal working version
- Add complexity incrementally
- Test each change immediately
- Keep fallback options for critical dependencies
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
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.