Shiny Project

Data 309 - Fall 2026

Published

November 9, 2026

Overview

Build a Shiny app around a dataset you import yourself, choose the inputs and outputs that fit your data and your question, and publish the app to the class GitHub repository with a README.md that explains it. You will also present your app and walk us through one piece of code in detail.

The test for this project is simple: I will clone the repo, open your app.R, and click Run App. If it runs on my computer, without me changing anything, and it helps someone explore your question, you’re most of the way there.

Data Options

You may not use data that comes built into R or an R package: no mtcars, iris, penguins, diamonds, gapminder, nycflights13, and so on. Your app must import its data from a file or a URL.

Some places to look:

Pick data that suits interactivity: something with categories to filter, a range of numbers or dates to slide through, or places to map. Before you start, check the Question → Tool cheat sheet.

Requirements

Data import and cleaning

  • Import the data in code, with readr::read_csv(), readr::read_rds(), readxl::read_excel(), etc.
  • Read the data from one of these:
    • a file inside your project folder, read with a relative path like read_csv("data/my-data.csv"). Never use C:/Users/... or /Users/..., because nobody else has your computer.
    • a URL, so the app downloads the data itself.
  • Keep data files small enough for GitHub: under 25 MB. If yours is bigger, filter it down to what the app needs and save that smaller file.
  • Clean variable names (janitor::clean_names()), check variable types, and handle missing values.
  • Do the cleaning once, outside the server function, not inside a render*() function that re-runs on every click.

The Shiny app

  • A layout from bslib: page_sidebar(), page_fillable() + layout_sidebar(), or page_navbar().
  • At least three inputs, of at least two different types (e.g. a selectInput() and a sliderInput()).
  • At least three outputs, of at least two different types (e.g. a plot, a table, and a value_box()).
  • Every input must change at least one output. No decorative inputs.
  • At least one shared reactive() (or eventReactive()) that two or more outputs use.
  • Informative titles, axis labels and legends on every plot, using labs() and readable scales.
  • Tools that fit the data. Line plots for change over time, bars for comparing groups, maps for places, and so on. In your README, explain why you chose your main inputs and outputs.
  • Optional/encouraged:
    • value_box()
    • plot click or brush
    • a DT table
    • a map
    • downloadHandler()
    • tabs
    • validate(need()) for empty results
    • a theme
    Draw a few cards from the Feature Relay app for ideas.

GitHub: your project folder

Put your project in a subfolder of your own folder in the class repo:

shiny-collab/
└── students/
    └── <your-username>/
        └── shiny-project/
            ├── app.R          ← the app
            ├── README.md      ← explains the app (see below)
            ├── data/
            │   └── my-data.csv
            └── screenshot.png ← optional, but nice
  • The folder is named shiny-project, and the app is in app.R.
  • Everything the app needs is in that folder: code and data.
  • Commit as you go. I will look at your commit history, so I expect several commits with messages that say what changed, not one giant commit the night before it’s due.
  • Only git add files inside your own folder:
git pull
git add students/<your-username>/shiny-project
git commit -m "add species filter and summary table"
git push

README.md

Your README.md is the front page of your project on GitHub. It should include:

  1. Title and author
  2. The question your app helps someone explore, in one or two sentences
  3. The data:
    • where it came from, with a link
    • what one row represents
    • which variables you use
    • any cleaning you did
  4. How to run it:
    • the packages to install, e.g. install.packages(c("shiny", "bslib", "tidyverse"))
    • then: open app.R and click Run App
  5. What the app does: the inputs and outputs, and why you chose them for this data and this question
  6. One thing you learned: something you discovered by exploring your own app
  7. Limitations: what the data or the app can’t tell you
  8. Optional: a screenshot, ![screenshot of my app](screenshot.png)

Making a README.md in Positron

  1. In Positron’s Explorer panel, right-click your shiny-project folder and choose New File….
  2. Name it exactly README.md, with capital README and lowercase .md. GitHub automatically shows a file with this name on your folder’s page.
  3. Write it, then save.
  4. To see it formatted, open the Command Palette (Ctrl + Shift + P, or Cmd + Shift + P on a Mac) and run Markdown: Open Preview to the Side. The preview updates as you type.

It’s the same Markdown you already write in .qmd files

A .qmd file is Markdown plus a few Quarto extras. The text parts of your Quarto documents (headings, lists, bold, links, images) are written exactly the same way in a README:

you want write same as in a .qmd?
a heading # Title, ## Section yes
a bulleted / numbered list - item, 1. item yes
bold, italic, code **bold**, *italic*, `code` yes
a link [Kaggle](https://www.kaggle.com) yes
an image ![my app](screenshot.png) yes

What’s different about a README:

  • No YAML header. Don’t start it with a --- block. A # Title line is enough.
  • Code doesn’t run. A ```r block in a README just displays code; there are no {r} chunks and nothing executes.
  • No rendering. You never click Render: GitHub formats the file for you when you push.

Here’s a starter you can copy into your README.md and fill in:

# <Your App's Title>

**Author:** <your name>

## The question
<One or two sentences: what can someone explore with this app?>

## The data
- **Source:** [<dataset name>](<link>)
- **One row is:** <e.g. one county in one year>
- **Variables I use:** <list them>
- **Cleaning:** <what you changed and why>

## How to run it
1. Install the packages: `install.packages(c("shiny", "bslib", "tidyverse"))`
2. Open `app.R` in Positron and click **Run App**.

## What the app does
- **Inputs:** <each input, and why it fits this data>
- **Outputs:** <each output, and why it fits this question>

## One thing I learned
<Something you discovered by using your own app.>

## Limitations
<What the data or the app can't tell you.>

![screenshot of my app](screenshot.png)

Code quality

  • Good, brief comments explaining why, not narrating what.
  • Use the base pipe |> consistently.
  • Use meaningful names: county_votes, not df2 or data.
  • Delete leftovers: unused libraries, commented-out experiments, print() debugging.
  • It runs from a fresh R session. Restart R and click Run App before you push.

Presentation

  • 5 minutes: your dataset, your question, and a live demo of the app.
  • Describe in detail one piece of code: what it does, line by line, and why you wrote it that way. A reactive() or eventReactive() is a great choice.
  • Show us one thing you learned by using your app.

Rubric

Category Points Full credit
Data import and cleaning 15 Imported from a file or URL (not built-in); relative paths; names, types and missing values handled; cleaning done outside server
Inputs and outputs 20 At least 3 inputs and 3 outputs, of at least 2 types each; every input changes an output; bslib layout
Reactivity 15 At least one shared reactive() / eventReactive() used by multiple outputs; app updates correctly with no errors
Choosing the right tools 15 Chart types and inputs fit the data and the question; plots labeled and readable; choices explained in the README
GitHub and README 15 Correct folder; app runs after a fresh clone; several meaningful commits; README covers all required parts
Code quality 10 Clear, consistent style; useful comments; no leftovers; runs from a fresh session
Presentation 10 Clear and on time; live demo; one piece of code explained in detail
Total 100

Performance levels (per category)

Level Share of points Description
Excellent 90-100% Complete, correct, and thoughtful; goes beyond the minimum
Proficient 75-89% Meets requirements with minor errors or gaps
Developing 50-74% Some requirements missing or incorrect
Incomplete < 50% Major requirements missing, or the app does not run

Before you submit: checklist

Submission

  • Push your shiny-project folder to the class repo. Your last push before the deadline is your submission.
  • Due date: Thursday, Nov. 12.