curated experiences for touch-screen installations on the stanford campus.
wallscreens uses the jekyll static site generator, which requires ruby.
after cloning the repository, install dependencies:
$ bundle install
then, you can start a local development server:
$ bundle exec jekyll serve # or with --livereload
the site should be visible at http://localhost:4000.
to build the site for production:
$ bundle exec jekyll build
this will generate HTML in a directory called _site/
.
The JavaScript tests rely on modules installed via yarn. To install these dependencies run the following before running the test suite:
$ yarn install
There is a rake task (in Rakefile
) to run the entire testing/linting suite:
$ bundle exec rake ci
You will also find tasks in Rakefile
to run each test suite/linter individually.
We use html-proofer to lint and validate the HTML generated by $ bundle exec jekyll build
. There is Rake task defined in Rakefile
that first builds and then runs html-proofer on the result:
$ bundle exec rake html_proofer
We use rubocop to lint Ruby code in the project. There is a Rake task included in Rakefile
to run rubocop on the project:
$ bundle exec rake rubocop
We use rspec to test Ruby code in the project. There is a Rake task included in Rakefile
to run the specs defined in /spec/*
:
$ bundle exec rake rspec
We use eslint to lint JavaScript code in the project. There is a Rake task included in Rakefile
to run eslint on the project:
$ bundle exec rake eslint
We use jest to test Stimulus.js code in the project. There is a Rake task included in Rakefile
to run the specs defined in /spec/javascript
:
$ bundle exec rake jest
- Pixels: 3840 x 2160
- Display Area: 56.2" x 31.6" (1428.5mm x 803.5mm)
- Aspect Ratio: 16:9
For local development it may be useful to emulate the dimensions of the wallscreens in your browser. Chrome and FireFox provide tools and documentation for developing sites for various size screens.
each wallscreen can host several experiences, and experiences can be shared across multiple wallscreens. an experience is a set of curated content, which can take the form of:
- a slideshow of many images with captions
- a guided tour that zooms in on locations in a single high-resolution image
- a video with multiple themed sections, each containing several clips
the content used in the wallscreens and experiences is stored as YAML files in the _data/
directory. text content and media links supplied by curators are defined for each experience.
the layout of experience pages is defined by the HTML templates in the _layouts/
directory. these templates have access to the "global" data in the _data/
folder via site.wallscreens
and site.experiences
. reusable HTML components are defined in the _includes/
folder.
thumbnails are displayed in the card/slide area of guided tour and oral history experiences. these images should be included in the code repository for the project and meet the following naming conventions and specifications:
- thumbnail location:
images/experiences/{EXPERIENCE_KEY}/{SLIDE_KEY OR CLIP_KEY}.png
- square aspect ratio, 200x200
slideshow and oral history experiences also use special thumbnails to populate a grid of images shown on their "attract mode" screen (see below). these images follow a similar naming convention and specification:
- attract image location:
images/experiences/{EXPERIENCE_KEY}/attract-images/{NAME}.png
- rectangular aspect ratio, 800x533
media referenced in wallscreens can be checked-in to the git repository if rights statements permit it. otherwise, files should be downloaded and stored in the local-media/
directory so that they can be referenced during the jekyll build process.
when adding media to an experience, you can use the custom file_or_link
liquid tag to insert a file from local-media/
, falling back to a supplied URL if the file isn't present locally:
<img src="{% file_or_link {{local_file}} {{image_url}} %}">
note the lack of whitespace around interpolated values ({{local_file}}
); this is necessary for the tag to parse correctly. when the path pointed to by local_file
can't be found or wasn't supplied, jekyll will issue a warning when building and use the value of image_url
instead.
you may find it useful to use a placeholder image service for image_url
when no suitable image is available or the image hasn't yet been created — for example, https://via.placeholder.com/800x533 will resolve to a blank 800x533 PNG image.
experiences are grouped by type and accessible through "index pages" on each wallscreen. these pages use the special "index page" layouts like slideshow_index
, which show a variety of content from all experiences of the same type on a single screen. the YAML front matter for the index page controls which experience content will be displayed in the "attract mode" animation for that page:
layout: slideshow_index
wallscreen: silicon-valley
attract_images:
- launching-the-newton
- sf-arcade-1
- the-newton
- asteroids-1
- adobe
- san-mateo-3
- desktop-publishing
- pier-39-3
- acrobat-and-pdf
wallscreens are designed to rotate through content continuously, in order to prevent screen burn-in and showcase the available experiences.
the oral history experience plays through its entire video if left alone; the guided tour and slideshow experiences will begin automatically cycling through content after an interval elapses where the user has not touched the wallscreen.
for testing and local development, this value can be edited (in, for example, js/controllers/slideshow.js
):
static autoplayTimeout = 5 * 60 * 1000; // 5 minutes before entering autoplay mode
after autoplay takes effect, the experience will spend some time on each slide before moving to the next. this value can also be edited:
static autoplayIntervalTime = 15 * 1000; // 15 seconds per slide/stop in autoplay mode
when changing the autoplayIntervalTime
, be sure to also update the animation timing value for the autoplay play/pause button in _scss/wallscreens/_buttons.scss
:
// animation time should match configured autoplayInterval in controller
.progress-ring circle {
animation: ringFill 15s linear infinite;
}
if an experience remains unattended, autoplay will eventually return it to its initial slide/stop. once it remains in this state for the duration of another autoplayIntervalTime
, it will return to the "index page" for its type (see above) and enter "attract mode", which cycles between the index pages for that wallscreen.
this behavior is shared between the autoplay()
method of each experience controller and the attract mode controller itself (see js/controllers/attract-mode.js
).