It is definitely because your admin theme is active when you do the render.
There is no straight-forward and easy way to switch the theme in the middle of a request and you will likely run into further problems.
I would consider other options, e.g. creating the nodes markup via a menu callback that uses the frontend theme, either directly in your hook_entity_postsave
or in a cron job for example.
If you still want to try it by switching themes, this is the way it worked for my now after a bit of tinkering with the code from https://stackoverflow.com/a/56358189/368479 and borrowing code from drupal_theme_initialize().
The most notable change is the clearing of the cache at the end of the switch function. Performance-wise this is awful, but I couldn't make it work without it.
/**
* Switch to or from an alternative theme in the middle of a request.
*
* This is useful if you need to render something (like a node) in a different
* theme without changing the theme of the entire page. An example use case is
* when you need to render something for a front end user from an admin page.
*
* Usage example:
* my_module_switch_theme('bartik');
* $node = node_load(1);
* $renderable = node_view($node);
* $rendered = render($renderable);
* my_module_switch_theme();
*
* @param string|null $to
* The name of the theme to switch to. If NULL, it switches back to the
* original theme.
*/
function my_module_switch_theme(string $to = NULL) {
global $theme, $theme_key;
// Backup the original theme.
static $original_theme;
if (empty($original_theme)) {
$original_theme = $theme;
}
// Perform the switch.
$theme = $to ?? $original_theme;
$theme_key = $theme;
// Find all our ancestor themes and put them in an array.
$themes = list_themes();
$base_theme = array();
$ancestor = $theme;
while ($ancestor && isset($themes[$ancestor]->base_theme)) {
$ancestor = $themes[$ancestor]->base_theme;
$base_theme[] = $themes[$ancestor];
}
_drupal_theme_initialize($themes[$theme], array_reverse($base_theme));
// Themes can have alter functions, so reset the drupal_alter() cache.
drupal_static_reset('drupal_alter');
// Clear the cache.
drupal_flush_all_caches();
}
Note that this might not work if you implement hook_custom_theme for the page where the action happens, but if you use the admin theme then I guess that is not the case.
The code above can then be used like in the following example and correctly uses the node.tpl.php
from the bartik theme instead of the one that the current theme uses, at least in my test setup.
my_module_switch_theme('bartik');
$node = node_load(1);
$renderable = node_view($node);
$rendered = render($renderable);
my_module_switch_theme();