dvStaticPage function

String dvStaticPage({
  1. required String shell,
  2. required String route,
  3. required String title,
  4. String? description,
  5. String? content,
  6. String? siteUrl,
  7. String? image,
  8. String? siteName,
  9. Map<String, String> alternates = const <String, String>{},
  10. String? defaultAlternate,
  11. String? favicon,
  12. String? schemaType,
})

A route's own HTML: the app shell with this page's head tags and, where prerendering captured it, this page's text.

Implementation

String dvStaticPage({
  required String shell,
  required String route,
  required String title,
  String? description,
  String? content,
  String? siteUrl,
  String? image,
  String? siteName,
  Map<String, String> alternates = const <String, String>{},
  String? defaultAlternate,
  String? favicon,
  String? schemaType,
}) {
  final canonical =
      siteUrl == null ? null : dvStaticCanonical(siteUrl, route);

  // What the page *is*, which OpenGraph cannot say: og:type is "website" for
  // every page on every site. This is what produces a site name in a result
  // and a breadcrumb trail under a link.
  //
  // Folded into the one head application rather than applied after it.
  // dvSeoApply writes into a marked region, so a second call replaces the
  // first call's tags -- which took the title and the canonical with it.
  final String jsonLd = dvStructuredData(
    route: route,
    title: title,
    siteName: siteName ?? title,
    description: description,
    siteUrl: siteUrl,
    image: dvAbsoluteAsset(image, siteUrl),
    schemaType: schemaType,
  );

  var html = dvSeoApply(
    shell,
    dvSeoHead(
      title: title,
      description: description,
      // Its own URL, not the site root. Every page canonicalising to `/` tells
      // a crawler they are the same page, which is worse than no canonical.
      siteUrl: canonical,
      // Resolved against the site root here, because dvSeoHead resolves a
      // relative image against whatever it is given as siteUrl -- and that is
      // the page's canonical URL, which is what the canonical link and og:url
      // need. Passing both through one argument put the route into the image:
      // /docs asked for https://example.com/docs/icons/Icon-512.png, which
      // does not exist. A broken og:image is invisible until someone shares
      // the link.
      image: dvAbsoluteAsset(image, siteUrl),
      siteName: siteName,
      alternates: alternates,
      defaultAlternate: defaultAlternate,
    ) + (jsonLd.isEmpty ? '' : '\n$jsonLd'),
  );

  // Outside the marked region deliberately. dvSeoApply rewrites what is
  // between its markers, and the shell's icon link is not in there -- it is a
  // tag Flutter wrote, and replacing it is the only way a page gets its own
  // icon rather than a second one next to the application's.
  html = dvApplyFavicon(html, favicon);

  if (content != null && content.trim().isNotEmpty) {
    html = _injectContent(html, content);
  }
  return html;
}