systemprompt_content/
homepage_prerenderer.rs1use std::path::PathBuf;
2use std::sync::Arc;
3
4use anyhow::Result;
5use async_trait::async_trait;
6use systemprompt_cloud::constants::storage;
7use systemprompt_models::ContentConfigRaw;
8use systemprompt_provider_contracts::{
9 PagePrepareContext, PagePrerenderer, PageRenderSpec, WebConfig,
10};
11
12const PAGE_TYPE: &str = "homepage";
13const TEMPLATE_NAME: &str = "homepage";
14const OUTPUT_FILE: &str = "index.html";
15
16#[derive(Debug, Clone, Copy, Default)]
17pub struct DefaultHomepagePrerenderer;
18
19impl DefaultHomepagePrerenderer {
20 #[must_use]
21 pub const fn new() -> Self {
22 Self
23 }
24
25 fn extract_branding(
26 web_config: &WebConfig,
27 content_config: &ContentConfigRaw,
28 ) -> HomepageBranding {
29 let org = &content_config.metadata.structured_data.organization;
30 let branding = &web_config.branding;
31
32 HomepageBranding {
33 org_name: org.name.clone(),
34 org_url: org.url.clone(),
35 org_logo: org.logo.clone(),
36 logo_path: branding
37 .logo
38 .primary
39 .svg
40 .clone()
41 .unwrap_or_else(String::new),
42 favicon_path: branding.favicon.clone(),
43 twitter_handle: branding.twitter_handle.clone(),
44 display_sitename: branding.display_sitename,
45 }
46 }
47}
48
49struct HomepageBranding {
50 org_name: String,
51 org_url: String,
52 org_logo: String,
53 logo_path: String,
54 favicon_path: String,
55 twitter_handle: String,
56 display_sitename: bool,
57}
58
59#[async_trait]
60impl PagePrerenderer for DefaultHomepagePrerenderer {
61 fn page_type(&self) -> &str {
62 PAGE_TYPE
63 }
64
65 fn priority(&self) -> u32 {
66 100
67 }
68
69 async fn prepare(&self, ctx: &PagePrepareContext<'_>) -> Result<Option<PageRenderSpec>> {
70 let content_config = ctx
71 .content_config::<ContentConfigRaw>()
72 .ok_or_else(|| anyhow::anyhow!("ContentConfigRaw not available in context"))?;
73
74 let branding = Self::extract_branding(ctx.web_config, content_config);
75
76 let base_data = serde_json::json!({
77 "site": ctx.web_config,
78 "ORG_NAME": branding.org_name,
79 "ORG_URL": branding.org_url,
80 "ORG_LOGO": branding.org_logo,
81 "LOGO_PATH": branding.logo_path,
82 "FAVICON_PATH": branding.favicon_path,
83 "TWITTER_HANDLE": branding.twitter_handle,
84 "DISPLAY_SITENAME": branding.display_sitename,
85 "HEADER_CTA_URL": "/",
86 "JS_BASE_PATH": format!("/{}", storage::JS),
87 "CSS_BASE_PATH": format!("/{}", storage::CSS)
88 });
89
90 Ok(Some(PageRenderSpec::new(
91 TEMPLATE_NAME,
92 base_data,
93 PathBuf::from(OUTPUT_FILE),
94 )))
95 }
96}
97
98pub fn default_homepage_prerenderer() -> Arc<dyn PagePrerenderer> {
99 Arc::new(DefaultHomepagePrerenderer::new())
100}