using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using PlotLine.Services; using PlotLine.ViewModels; namespace PlotLine.Controllers; [AllowAnonymous] [Route("")] public sealed class PublicController(IConfiguration configuration) : Controller { private const string SupportEmail = "hello@plotdirector.com"; private const string PolicyDate = "June 24, 2026"; private const string Keywords = "novel planning software, writing software, story planning app, author tools, plot tracking, character tracking, story timeline, novel organisation, fiction writing software, series writing software, continuity tracking, plot threads, story bible"; [HttpGet("about", Name = PublicRouteNames.About)] public IActionResult About() { SetSeo( "About", "Learn why PlotDirector was created by a novelist to help writers organise complex stories, manage continuity, and finish their books with confidence.", "/about", "AboutPage", "About PlotDirector"); return View(CreateModel()); } [HttpGet("contact", Name = PublicRouteNames.Contact)] public IActionResult Contact() { SetSeo( "Contact", "Contact PlotDirector for support, questions, feedback, or feature suggestions about our novel planning and story organisation platform.", "/contact", "ContactPage", "Contact PlotDirector"); return View(CreateModel()); } [HttpGet("privacy", Name = PublicRouteNames.Privacy)] public IActionResult Privacy() { SetSeo( "Privacy Policy", "Read the PlotDirector Privacy Policy to learn how we protect your account information, subscription data, and story content.", "/privacy", "PrivacyPolicy", "Privacy Policy"); return View(CreateModel()); } [HttpGet("terms", Name = PublicRouteNames.Terms)] public IActionResult Terms() { SetSeo( "Terms of Service", "Read the PlotDirector Terms of Service for information about subscriptions, user content, acceptable use, and account responsibilities.", "/terms", "WebPage", "Terms of Service"); return View(CreateModel()); } private void SetSeo(string title, string description, string path, string schemaType, string pageName) { PublicSeo.Apply(ViewData, configuration, new SeoMetadata { Title = title, Description = description, Keywords = Keywords, CanonicalPath = path, JsonLd = [ PublicSeo.WebPageJsonLd(configuration, schemaType, pageName, path, description) ] }); } private static PublicPageViewModel CreateModel() => new() { SupportEmail = SupportEmail, LastUpdated = PolicyDate }; }