---
title: "Reference Guide"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Reference Guide}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

# Reference for `shinyseo`

This package generates metadata for a Shiny app and returns HTML tags for `<head>`.

It is useful when you want the page to look right in shares on Facebook, LinkedIn, X, Slack, and other services that read Open Graph or Twitter Card metadata.

## Main flow

1. Pass a YAML file or a named list to `social_meta()` in the UI.
2. `social_meta()` reads the data, fills in defaults, validates required fields, and builds a `tags$head()` block with metadata and a JavaScript handler.
3. Optionally call `update_meta()` in the server to update one or more fields reactively without a page reload.

## Inputs

`social_meta(meta)` accepts:

- a string containing a path to YAML
- or a named list

### Required fields

These must always exist:

- `title`
- `description`
- `url`
- `image`

If one is missing, the function stops with an error.

## Defaults

If you do not set them yourself, these defaults are used:

- `locale = "en_US"`
- `robots = "index,follow,max-image-preview:large,max-snippet:-1,max-video-preview:-1"`
- `twitter_card = "summary_large_image"`
- `bing_site_verification = Sys.getenv("SHINYSEO_BING_SITE_VERIFICATION")` when present
- `twitter_site = Sys.getenv("SHINYSEO_TWITTER_SITE")` when present
- `twitter_creator = Sys.getenv("SHINYSEO_TWITTER_CREATOR")` when present
- `schema_type = "WebApplication"`
- `operating_system = "Any"`
- `author_type = "Person"`
- `publisher_type = "Organization"`
- `in_language = locale`

## What tags are created

The function builds:

- `<link rel="canonical">`
- `meta name="description"`
- `meta name="robots"`
- `meta property="og:*"`
- `meta name="twitter:*"`
- `meta name="msvalidate.01"` when Bing verification is set or when `SHINYSEO_BING_SITE_VERIFICATION` is present
- `meta name="google-site-verification"` when Google verification is set
- `meta name="yandex-verification"` when Yandex verification is set
- `meta name="baidu-site-verification"` when Baidu verification is set
- `meta name="naver-site-verification"` when Naver verification is set
- `meta name="facebook-domain-verification"` when Facebook domain verification is set
- `meta name="p:domain_verify"` when Pinterest domain verification is set
- `<script type="application/ld+json">` for schema.org
- no `<title>` tag; set the title in the app UI instead

## Open Graph

These fields are used directly in Open Graph:

- `title`
- `description`
- `url`
- `image`
- `site_name`
- `locale`
- `image_width`
- `image_height`
- `image_type`
- `image_alt`

## Twitter Card

These fields are used directly in Twitter Card:

- `twitter_card`
- `twitter_site` with fallback to `SHINYSEO_TWITTER_SITE`
- `twitter_creator` with fallback to `SHINYSEO_TWITTER_CREATOR`
- `twitter_image_alt`

## Bing verification

Bing verification is used directly when the following is set:

- `bing_site_verification`

If that field is missing, `SHINYSEO_BING_SITE_VERIFICATION` is used when
present.

## Schema.org JSON-LD

JSON-LD is created with these base fields:

- `@context = "https://schema.org"`
- `@type = schema_type`
- `name = title`
- `description = description`
- `url = url`
- `inLanguage = in_language`

Additional fields may be included:

- `application_category`
- `operating_system`
- `educational_use`
- `is_accessible_for_free`
- `disclaimer`
- `author_name`
- `publisher_name`

If you set `schema = FALSE`, JSON-LD is omitted entirely.

## Custom meta tags

The `custom` field accepts a list of lists.  Each inner list becomes one
`<meta>` tag; its names map directly to HTML attributes.

```r
custom = list(
  list(name     = "viewport",  content = "width=device-width, initial-scale=1"),
  list(property = "og:video",  content = "https://example.no/video.mp4"),
  list(name     = "x-app-env", content = "production")
)
```

Use `name` for standard meta tags and `property` for Open Graph-style tags.
Any other valid HTML attribute is also accepted.

## Practical example

```r
ui <- shiny::fluidPage(
  shinyseo::social_meta(list(
    title = "Calculator",
    description = "A simple app for calculating things.",
    url = "https://example.no",
    image = "https://example.no/preview.png",
    twitter_site = "@example",
    twitter_creator = "@example",
    schema = TRUE
  )),
  shiny::h1("Calculator")
)
```

## Favicon and web app manifest

Add favicon and PWA support by setting optional fields in the same metadata object:

```r
# global.R
shinyseo::write_manifest(list(
  title            = "My App",
  short_name       = "MyApp",
  description      = "A Shiny web app.",
  theme_color      = "#1a73e8",
  favicon          = "/favicon.png",
  apple_touch_icon = "/apple-touch-icon.png"
))
```

```r
# ui.R
shinyseo::social_meta(list(
  title            = "My App",
  description      = "A Shiny web app.",
  url              = "https://example.no",
  image            = "https://example.no/share.png",
  favicon          = "/favicon.png",
  apple_touch_icon = "/apple-touch-icon.png",
  theme_color      = "#1a73e8",
  manifest         = "/manifest.json"
))
```

Place `favicon.png` and `apple-touch-icon.png` in the `www/` folder of the app.  `write_manifest()` writes `www/manifest.json` automatically.

The MIME type for `favicon` is inferred from the file extension.  Supported: `.ico`, `.png`, `.svg`, `.webp`, `.gif`.  Override with `favicon_type` if needed.

## Reactive metadata with `update_meta()`

Call `update_meta()` in the server when the visible content changes — for example when the user switches tabs or navigates between routes.  Only the fields you supply are updated; everything else stays as set by `social_meta()`.

```r
ui <- shiny::navbarPage("My App",
  shinyseo::social_meta(list(
    title       = "My App",
    description = "A multi-tab Shiny app.",
    url         = "https://example.no",
    image       = "https://example.no/preview.png"
  )),
  shiny::tabPanel("Home"),
  shiny::tabPanel("About")
)

server <- function(input, output, session) {
  observeEvent(input$tabs, {
    if (input$tabs == "About") {
      shinyseo::update_meta(session,
        title       = "About – My App",
        description = "Learn more about the team."
      )
    } else {
      shinyseo::update_meta(session,
        title       = "My App",
        description = "A multi-tab Shiny app."
      )
    }
  })
}
```

`social_meta()` must be present in the UI for the JavaScript handler to be registered.

## When to use it

Use the package when you want a small, tidy metadata solution in a Shiny app without building a custom metadata engine.

It is especially useful when you:

- have one app or a small number of apps
- want to manage metadata from a YAML file
- want the same metadata across multiple environments
- want social sharing and search results to behave predictably
- have tabbed or multi-route apps where metadata should reflect the current view
