How to force rendering by the site theme instead of the admin theme? When rendering HTML in hook_node_presave(), everything works as expected when I save the node manually.
However, when I use the &quot;Save content&quot; action on the content admin view (at /admin/content), then the page is rendered with the admin theme templates (Seven), instead of the templates of my custom theme/the site theme.
I tried using both Claro and Seven as the admin theme, and I get the same result: I can save the page manually and the site theme's templates are used, but if I use the &quot;Save content&quot; action to bulk re-save nodes, they are rendered incorrectly with the admin theme templates.
Here's the code that is causing the issue:
function MYMODULE_node_presave(NodeInterface $node) {
  $content_type = $node-&gt;getType();
  if ($content_type == 'page') {
    // Render the entire node and save that HTML to a specific field.
    $render_controller = \Drupal::entityTypeManager()
      -&gt;getViewBuilder($node-&gt;getEntityTypeId());
    $render_output = $render_controller-&gt;view($node, 'mymarkup_torender', 'ja');
    $html = \Drupal::service('renderer')-&gt;renderPlain($render_output);
    $node-&gt;set('field_text_cached_html', $html);
    $node-&gt;field_text_cached_html-&gt;format = 'mymarkup_processed';
  }

Is there a way to force Drupal to use the site theme instead of the admin theme when rendering?
On the Appearance administration page, &quot;Use the administration theme when editing or creating content&quot; is unchecked.
Based on the comment by @MrD, I found a working solution.
I implemented a custom theme negotiator based on this information:

Blog post: Dynamic theme switching in Drupal 8
Blog post: Choose your theme dynamically in Drupal 8 with theme negotiation
Drupal Answers: How can I programmatically change the active theme?

I needed to change the theme for the admin content page, so here is the code I used:
mymodule.services.yml
  MYMODULE.theme.negotiator:
    class: Drupal\MYMODULE\Theme\ThemeNegotiator
    tags:
      - { name: theme_negotiator, priority: -20 }

Here, I used a low priority to ensure my code runs first.
MYMODULE/src/Theme/ThemeNegotiator.php
&lt;?php

namespace Drupal\MYMODULE\Theme;

use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Theme\ThemeNegotiatorInterface;

/**
 * Select the correct theme for various routes.
 */
class ThemeNegotiator implements ThemeNegotiatorInterface {

  /**
   * {@inheritDoc}
   */
  public function applies(RouteMatchInterface $route_match) {
    return $this-&gt;negotiateRoute($route_match) ? TRUE : FALSE;
  }

  /**
   * {@inheritDoc}
   */
  public function determineActiveTheme(RouteMatchInterface $route_match) {
    return $this-&gt;negotiateRoute($route_match) ?: NULL;
  }

  /**
   * Select the theme for special cases.
   *
   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
   *   The currently matched route.
   *
   * @return bool|string
   *   The theme name to use (string) or false (bool).
   */
  private function negotiateRoute(RouteMatchInterface $route_match) {
    $route_name = $route_match-&gt;getRouteName();
    if ($route_name === 'system.admin_content') {
      return 'MYTHEMENAME';
    }
    else {
      return FALSE;
    }
  }

}