top of page

Build a Basic, Personalized Valentine's Day App with R/Shiny

Writer: Gigi KennethGigi Kenneth

Updated: Feb 15


Valentine's Day is a great time to create something special for a loved one, but you can equally make this sort of thing whenever you feel like it. Instead of a traditional card, let's make a simple and interactive digital love letter using R/Shiny.


This blog post will help you build this basic yet meaningful web app, even if you're new to Shiny!


What is Shiny?

Shiny logo

If you're new to Shiny, Shiny is an R package that makes it easy to build interactive web apps using only R. You don't need to know HTML, CSS, or JavaScript; Shiny takes care of most of it for you. With Shiny, you can create dynamic content, collect user input, and display results in real-time.


What This App Does

This app is a beautifully designed digital love letter with interactive elements:

  • Starts with a virtual envelope: Clicking the envelope (while it was a struggle to make this look like an envelope) opens a love letter.

  • Displays memory cards: Clicking each card reveals a special memory.

  • Rotates through love notes: A button lets you shuffle through sweet messages.

  • Has a soft and elegant design: Uses Quicksand font and smooth animations.


How to Use This Template

Step 1: Install Required Packages

Before starting, ensure you have the necessary R packages installed. Open R and run:

install.packages(c("shiny", "shinyjs", "bslib"))

Step 2: Copy and Paste the Code

Use the following code as your template. You can copy it into an R script and run it using RStudio.


library(shiny)
library(shinyjs)
library(bslib)

# Define the UI
ui <- fluidPage(
  useShinyjs(),
  
  # Custom CSS
  tags$head(
    tags$style(HTML("..."))
  ),
  
  # Theme
  theme = bs_theme(
    version = 5,
    primary = "#e53e3e",
    base_font = font_google("Playfair Display")
  ),
  
  # Main content
  div(
    class = "container",
    style = "background-color: #fff5f5; min-height: 100vh; padding: 20px;",
    
    actionButton(
      "openEnvelope",
      label = div(
        class = "envelope",
        div(class = "seal", "❤️"),
        h1("For My Love", style = "font-size: 2em; color: #702459;"),
        p("Click to open your Valentine's letter")
      ),
      style = "width: 100%; background: none; border: none; padding: 0;"
    ),
    
    hidden(
      div(
        id = "letter-content",
        class = "letter-content",
        div(
          style = "text-align: center; margin: 20px 0;",
          h1("My Dearest Valentine ✨", style = "color: #702459;"),
          div(class = "love-note",
              "Every day with you is a new adventure. Your smile brightens my world, 
              and your love makes every moment special. You're not just my partner - 
              you're my best friend, my favorite person, and my greatest love."
          )
        ),
        
        div(
          style = "margin: 20px 0;",
          h2("Our Special Memories 💝", style = "color: #702459; text-align: center;"),
          uiOutput("memoryCards")
        ),
        
        div(
          style = "text-align: center; margin: 20px 0;",
          actionButton(
            "nextNote", 
            "Read a Love Note 💌",
            class = "btn-primary",
            style = "font-size: 1.2em; background-color: #e53e3e; border: none;"
          ),
          br(),
          br(),
          uiOutput("loveNote")
        )
      )
    )
  )
)

# Define server
server <- function(input, output, session) {
  values <- reactiveValues(
    letterOpened = FALSE,
    currentNote = 1,
    revealedMemories = c()
  )
  
  memories <- list(
    list(id = 1, title = "Our First Date ☕", text = "You were wearing that blue shirt I love, and we talked for hours about our favorite books."),
    list(id = 2, title = "Late Night Calls 📱", text = "All those times we stayed up way too late talking about everything and nothing."),
    list(id = 3, title = "Movie Marathon 🎬", text = "When you insisted on watching all my favorite films, even the cheesy ones."),
    list(id = 4, title = "Your Birthday Surprise 🎉", text = "The look on your face when you saw what I planned. Your smile was everything.")
  )
  
  loveNotes <- c(
    "I love how you always know how to make me laugh 😊",
    "Your random facts are my favorite part of the day 🌟",
    "You make every ordinary moment extraordinary ✨",
    "I smile every time I get a message from you 💝",
    "Being with you feels like home 💫"
  )
  
  observeEvent(input$openEnvelope, {
    values$letterOpened <- TRUE
    hide("openEnvelope")
    show("letter-content")
  })
  
  output$memoryCards <- renderUI({
    lapply(memories, function(memory) {
      actionButton(
        inputId = paste0("memory_", memory$id),
        label = if(memory$id %in% values$revealedMemories) {
          div(h3(memory$title, style = "color: #702459;"), p(memory$text))
        } else {
          div("🔒 Click to reveal this memory")
        },
        class = "memory-card"
      )
    })
  })
  
  observe({
    lapply(memories, function(memory) {
      observeEvent(input[[paste0("memory_", memory$id)]], {
        if(!(memory$id %in% values$revealedMemories)) {
          values$revealedMemories <- c(values$revealedMemories, memory$id)
        }
      })
    })
  })
  
  observeEvent(input$nextNote, {
    values$currentNote <- (values$currentNote %% length(loveNotes)) + 1
  })
  
  output$loveNote <- renderUI({
    div(class = "love-note", loveNotes[values$currentNote])
  })
}

shinyApp(ui = ui, server = server)

Step 3: Customize the Love Letter

To personalize your message:

  • Change the h1() and p() text inside div(id = "letter-content") to write your own love letter.

  • Add your own memory cards by editing the memories list in the server function.

  • Modify love notes in the loveNotes section to include personal messages.

  • Adjust styles by modifying the CSS in tags$style(HTML(...)) to customize colors, fonts, and spacing.


Step 4: Run Your App

In RStudio, click Run App, and your interactive Valentine's message will appear in a browser.




Step 5: Share with Your Loved One


Enhancements for Beginners

  • Want to change the colors? Update the bs_theme(primary = "#ff4081") setting in the UI.

  • Need more memories? Add more elements inside memoryCards by extending the memories list.

  • Prefer a different font? Change font_google("Quicksand") to another font from Google Fonts.

  • Add a background image by modifying the background-color in the container div.

  • Incorporate animations using CSS transitions for a more interactive experience.


Conclusion

With just a few lines of code, we created a unique digital Valentine’s gift or something like that, but luckily, it doesn't take too many brain cells to create! *insert half smile*

This was meant to help beginners get started and personalize their interactive love letter. I hope you liked it or found it helpful at least. If you have any questions, please leave them in the comments.


Happy coding and lots of love. Merry Valentine's Day. ❤️



 
 

Comments


  • LinkedIn
  • Medium
  • GitHub
  • Twitter

Gigi Kenneth

Contact

Ask me anything

bottom of page