This is the complete code for UCLA Radio's website, Node.js server and API. We also have an open-source iOS app and an Android app in development.
UCLA Radio is a completely student-run organization offering cultural content created by 100+ DJs. Let us know if you have any suggestions! All of the software here is written by students.
How to run locally:
- Ensure you have Mongo installed and a Mongo db instance is running
- Mac: run
setup.sh
on your Mac with homebrew installed to set up node and MongoDB automatically
- Mac: run
- In the project root directory, run
npm install
to install dependencies (may need sudo) - Run
node bin/www
to start the server for development - Point your browser to
http://localhost:3000/
😍
To run on the server:
- Make sure all packages are installed with
npm install
- Run
node bin/www prod
to start the server for production (will require HTTPS and listen on port 80)
./routes
: url handlers (e.g. what happens when you load uclaradio.com/calendar
)
./database
: data models and functions we use in the routes to do things like create a new show
./public
: everything we have public on the site. For your images, JavaScript, CSS, HTML and what have you
./views
: Jade templates. Right now many front-end pages are in Jade, hopefully we will redesign them in Javascript soon
./react
: React front-end pages. Reusable components like UI elements are in /react/components
This segment from ./routes/api.js
is a good example of how routes and data models work:
var shows = require('../database/shows');
// ...
// uclaradio.com/api/schedule -> JSON
router.get('/schedule', function(req, res) {
shows.getAllShows(function(err, results) {
if (results) {
res.json({shows: results.filter(checkPublic)});
} else {
// something went wrong
res.status(400).send(err);
}
});
});
React files must be compiled to actual javascript before a browser can use them, because they do things like this:
var djs = {'Toad', 'Squirrel', 'Camel'};
return <p>UCLA Radio is a student-run organization with {djs.length} student DJs. </p>;
Do so with Grunt, which automates Webpack:
- install grunt-client with npm:
npm install -g grunt-cli
- run
grunt
to compile .jsx files in./react
and put minified versions in./public/build
- run
grunt watch
to automatically recompile whenever you hit save!
- run
- add
.../build/[x].min.js
as a script in your HTML files
We prefer using a front-end web app and an API over static templates, because apps can be interactive. Our internal staff panel / content management system works this way:
/***** User Home Page *****/
// Front-end: provide HTML file to logged in users, redirect everyone else
// uclaradio.com/panel/home -> HTML
router.get('/home', function(req, res) {
if (req.session.user == null) {
// not logged in, redirect to log in page
res.redirect('/panel');
} else {
var path = require('path');
res.sendFile(path.resolve('public/panel/panel.html'));
}
});
// API: Return current logged-in user's shows as a JSON file which can be parsed by React, or 400 error
// uclaradio.com/panel/api/shows -> JSON
router.get('/api/shows', function(req, res) {
if (req.session.user == null) {
res.status(400).send();
} else {
var user = req.session.user;
shows.getShowsForUser(user.username, function(err, userShows) {
if (userShows) {
res.json({'shows': userShows});
} else {
res.status(400).send();
}
});
}
});
As a student-run organization, UCLA Radio is especially liable to technical debt. We have some goals for cleaning up our codebase in the future, but most importantly new code should:
- Have data models written with SQL (PostgreSQL) instead of MongoDB because we've had problems with Mongo and it's not what students are taught at UCLA
- Have new front-end pages in React. We prefer using a front-end framework with an API to complicated templates
- Delete files that are not used anymore. It's okay, get rid of clutter
- Follow an organized structure. Put things in the right directories