Purpose
- Publisher project responsible for serving published content and static proxy endpoints used in production delivery.
Quick start (local)
dotnet build SkyCMS.sln
dotnet run --project PublisherWhere to look
- Entry point:
Publisher/Program.cs. - Static proxy and routing controllers:
Publisher/Controllers. - Refer to
Editorfor how content is produced andCosmos.*projects for storage patterns.
Tests
- Run tests with
dotnet test SkyCMS.slnor target specific test projects.
Notes & conventions
- Avoid changing public-facing routes without tests and coordination.
- Follow DI and scoped service conventions used across the solution.
- Ask before editing
.github/workflows/*or release pipelines.
The SkyCMS Publisher is the public-facing web application component of the SkyCMS system that renders and serves complete web pages to end users. It operates in multiple modes to provide flexible deployment options for different performance and architectural requirements.
The Publisher application's primary function is to render complete HTML pages, either dynamically through server-side processing or by serving pre-generated static HTML files from cloud storage (Azure Blob Storage, AWS S3, or Cloudflare R2). This is fundamentally different from headless CMS architectures that rely on API endpoints to deliver content fragments.
The Publisher is designed to be highly performant, scalable, and configurable to meet various deployment scenarios.
The Publisher component represents a revolutionary improvement over traditional static site deployment workflows (GitHub Pages, Netlify, Vercel, etc.):
Traditional Git-Based Workflow Pain Points:
- Content editors must understand Git workflows
- Separate CI/CD pipeline configuration required
- External static site generators (Jekyll, Hugo, Gatsby) needed
- Build time delays (minutes per deployment)
- Multiple tools and services to integrate
- Complex troubleshooting across pipeline stages
- Choose either static OR dynamic—not both
SkyCMS Publisher Solution:
- No Git Knowledge Required: Content editors use intuitive CMS interface
- No CI/CD Pipeline: Built-in automatic triggers and rendering
- No External Generators: Direct rendering without Jekyll, Hugo, or Gatsby
- Instant Publishing: Changes go live immediately without build delays
- Single Integrated Platform: Everything in one system
- Simplified Operations: Fewer moving parts and failure points
- Hybrid Architecture: Serve static files AND dynamic content simultaneously
Technical Superiority:
- The Publisher acts as both the build system and deployment mechanism
- Tight integration eliminates the complexity of JAMstack toolchains
- Achieves the same benefits (speed, scalability, CDN distribution) without the overhead
- Direct deployment to cloud storage without intermediary services
- Version control built into the CMS—no external repository needed
The Publisher operates in two primary modes, determined by the CosmosStaticWebPages configuration setting:
Traditional CMS functionality with full page rendering:
- Server-side HTML generation - Complete pages rendered on each request
- Database-driven content from Azure Cosmos DB, SQL Server, MySQL
- User authentication and authorization support
- Real-time content with dynamic data integration
- Interactive features like comments, forms, and user sessions
- Personalized content based on user context
When to use: Dynamic content requirements, user-specific pages, real-time data integration
High-performance pre-rendered pages:
- Pre-generated HTML files stored in cloud storage (Azure Blob, S3, Cloudflare R2)
- Blazing-fast delivery - Pages served directly from CDN/edge locations
- Minimal server overhead - Publisher acts as a smart proxy to storage
- Maximum scalability - Handle massive traffic with minimal infrastructure
- Automatic static site generation triggered by content publishing in Editor
- Edge hosting support - Deploy origin-less sites with Cloudflare R2 + Rules (no Worker required)
When to use: Public-facing websites, high-traffic sites, edge hosting, maximum performance requirements
SkyCMS is built on the principle that most websites are best served as complete HTML pages rather than through API-driven frontend frameworks. This approach provides:
Better Performance: Static HTML from CDN beats API calls Simpler Architecture: No separate frontend application needed SEO Benefits: Server-rendered HTML works perfectly with search engines Lower Costs: Minimal compute requirements, especially in static mode Faster Development: Standard web development skills (HTML/CSS/JS) Better Reliability: Fewer dependencies and points of failure
While the Publisher does expose API endpoints (e.g., /pub/ routes for file access), these are:
- Supporting infrastructure for asset delivery, not primary content delivery
- Optional capabilities for specific use cases (mobile apps, integrations)
- Not the primary architecture - pages are the primary output
This contrasts with headless CMS systems where APIs are the primary (or only) way to deliver content.
- .NET 9.0 - Latest ASP.NET Core framework
- Docker containerized - Linux-based deployment
- Azure-native - Optimized for Azure App Services
- Azure Cosmos DB - Primary database for content storage
- Azure Blob Storage - Static asset and file storage
- Azure Application Insights - Telemetry and monitoring
- ASP.NET Core Identity - User authentication framework
- Cosmos.EmailServices - Email delivery services
- Cosmos.MicrosoftGraph - Microsoft Graph integration
- Microsoft.Extensions.Caching.Cosmos - Distributed caching
- Newtonsoft.Json - JSON serialization
Publisher/
├── Boot/ # Application bootstrapping
│ ├── DynamicPublisherWebsite.cs # Dynamic mode configuration
│ └── StaticWebsiteProxy.cs # Static mode configuration
├── Controllers/ # MVC Controllers
│ ├── HomeController.cs # Main content controller
│ ├── PubController.cs # Publication controller
│ └── StaticProxyController.cs # Static proxy handling
├── Models/ # Data models
│ ├── ApiResult.cs # API response models
│ ├── ErrorViewModel.cs # Error handling models
│ ├── FileCacheObject.cs # File caching models
│ └── InputVarDefinition.cs # Input variable definitions
├── Views/ # Razor view templates
├── wwwroot/ # Static web assets
├── Areas/Identity/ # Authentication views
├── appsettings.json # Configuration
├── Dockerfile # Container definition
└── Sky.Publisher.csproj # Project file
- SEO-optimized HTML output with meta tags and structured data
- Responsive design support for mobile and desktop
- Fast loading times through optimized caching strategies
- Content versioning with publish/unpublish workflows
- Memory caching for frequently accessed content
- Distributed caching using Azure Cosmos DB
- Static file optimization through Azure Blob Storage
- Rate limiting to prevent abuse and ensure stability
- OAuth integration with Google and Microsoft accounts
- Azure B2C support for enterprise authentication
- CORS configuration for cross-origin requests
- Anti-forgery tokens for CSRF protection
- HTTPS enforcement with security headers
- Application Insights integration for telemetry
- Structured logging for debugging and monitoring
- Health checks for system status monitoring
- Error handling with graceful degradation
| Variable | Description | Example |
|---|---|---|
CosmosStaticWebPages |
Enable static mode | true or false |
ConnectionStrings__ApplicationDbContextConnection |
Database connection | AccountEndpoint=...;AccountKey=...;Database=... |
ConnectionStrings__StorageConnectionString |
Azure Storage connection | DefaultEndpointsProtocol=https;... |
| Variable | Description | Default |
|---|---|---|
CosmosPublisherUrl |
Publisher URL | Auto-detected |
CorsAllowedOrigins |
CORS origins | All origins |
CosmosIdentityDbName |
Database name | cosmoscms |
GoogleOAuth__ClientId |
Google OAuth client | Not configured |
MicrosoftOAuth__ClientId |
Microsoft OAuth client | Not configured |
# Pull the latest image
docker pull toiyabe/sky-publisher:latest
# Run with basic configuration
docker run -d \
-p 8080:8080 \
-e CosmosStaticWebPages=false \
-e ConnectionStrings__ApplicationDbContextConnection="AccountEndpoint=...;AccountKey=...;Database=..." \
toiyabe/sky-publisher:latest- Create App Service with Linux container support
- Configure container to use
toiyabe/sky-publisher:latest - Set environment variables in Application Settings
- Enable Application Insights for monitoring
# Clone the repository
git clone https://github.com/CWALabs/SkyCMS.git
cd SkyCMS/Publisher
# Restore dependencies
dotnet restore
# Run the application
dotnet run- Seamless content sync from SkyCMS Editor
- Real-time updates when content is published
- Version management with rollback capabilities
- Preview functionality before publishing
- Automatic generation of static HTML files
- Asset optimization and compression
- CDN integration for global distribution
- Incremental updates for changed content only
GET /- Home page with latest contentGET /{article-path}- Individual article pagesGET /pub/{path}- Public API for content accessGET /ccms__antiforgery/token- CSRF token for forms
GET /Identity/Account/Login- User authenticationGET /Identity/Account/Register- User registrationPOST /Identity/Account/Logout- User logout
- Static mode: ~50ms average response time
- Dynamic mode: ~200ms average response time
- Cache hit ratio: >95% for frequently accessed content
- Horizontal scaling through multiple container instances
- Auto-scaling based on CPU and memory usage
- Load balancing across multiple regions
- Database scaling through Azure Cosmos DB
# Check application health
curl https://your-publisher.azurewebsites.net/Identity/Account/Login
# Monitor application insights
# Navigate to Azure portal > Application Insights > your-app-
Database Connection Issues
- Verify connection strings in app settings
- Check Azure Cosmos DB firewall rules
- Validate database permissions
-
Static File Serving Problems
- Confirm Azure Storage account configuration
- Verify blob container permissions
- Check CORS settings on storage account
-
Authentication Failures
- Validate OAuth provider configurations
- Check redirect URIs in Azure/Google console
- Verify SSL certificate configuration
Application logs are available through:
- Azure App Service Logs (Log Stream)
- Application Insights (Traces and Exceptions)
- Docker container logs (
docker logs <container-id>)
- Connection string encryption using Azure Key Vault
- Data protection keys stored in Azure Blob Storage
- Secure cookie configuration with HTTPS only
- SQL injection protection through Entity Framework
- Role-based authentication with ASP.NET Core Identity
- OAuth integration for secure third-party authentication
- Rate limiting to prevent denial-of-service attacks
- CORS policy configuration for API access
- .NET 9.0 SDK or later
- Docker Desktop (optional, for containerization)
- Azure Storage Emulator or Azure Storage account
- Visual Studio 2022 or VS Code (recommended)
# Build the project
dotnet build Sky.Publisher.csproj
# Run tests (if available)
dotnet test
# Publish for deployment
dotnet publish -c Release -o ./publish- Use Visual Studio debugger with container support
- Enable detailed error pages in development
- Configure logging levels for troubleshooting
- Use Azure Application Insights for production debugging
The Publisher application works seamlessly with CDN providers to deliver cached content globally while supporting automatic cache invalidation triggered by the Editor.
- Editor publishes content → Triggers CDN purge via configured provider API
- CDN receives purge request → Invalidates cached copies at edge locations
- Next visitor request → CDN fetches fresh content from Publisher origin
- Subsequent requests → Served from CDN edge cache (fast delivery)
- Azure CDN - Integrated with Azure Front Door and CDN profiles
- Cloudflare - Full integration with zones and purge APIs
- Sucuri - WAF-integrated CDN with security features
- Generic CDN - Works with any CDN supporting origin pull
Publisher must be accessible as CDN origin:
Azure CDN:
{
"CdnConfig": {
"OriginUrl": "https://your-publisher.azurewebsites.net",
"EnableCaching": true,
"CacheDuration": "1.00:00:00"
}
}Cloudflare:
- Point DNS to Cloudflare nameservers
- Configure SSL/TLS mode (Full or Full Strict recommended)
- Set cache level: Standard or Aggressive
- Configure page rules for dynamic content exclusions
Publisher Response Headers:
// In Program.cs - Configure caching headers
app.Use(async (context, next) =>
{
if (!context.Request.Path.StartsWithSegments("/api"))
{
context.Response.Headers.CacheControl = "public, max-age=3600";
context.Response.Headers.Vary = "Accept-Encoding";
}
await next();
});Static Assets (CSS, JS, images):
- Cache-Control:
public, max-age=31536000, immutable - Versioning: Use query strings or path versioning (
/css/style.v123.css)
HTML Pages:
- Cache-Control:
public, max-age=3600(1 hour) - Purged automatically on publish via Editor
Dynamic Content (search, forms):
- Cache-Control:
no-cacheorprivate - Excluded from CDN caching
Endpoint: GET /health
Response:
{
"status": "Healthy",
"checks": {
"database": "Healthy",
"storage": "Healthy"
},
"totalDuration": "00:00:00.0523"
}Use for CDN origin health monitoring and load balancer probes.
Contributions are welcome! Please follow these guidelines:
- Fork the repository and create a feature branch
- Follow coding standards using the included StyleCop rules
- Add unit tests for new functionality
- Update documentation as needed
- Submit a pull request with a clear description
This project is licensed under the GNU General Public License v2.0-or-later (GPL-2.0-or-later). See the LICENSE-GPL and LICENSE-MIT files for details. For complete third-party attribution, see NOTICE.md.
- Documentation: sky.moonrise.net/docs
- Community Support: SkyCMS Slack
- Issues: GitHub Issues
- Professional Support: Available through Moonrise Software
Configuration Guides:
- Storage Configuration - Configure cloud storage providers
- Database Configuration - Set up database connections
- Cloudflare Edge Hosting - Origin-less static hosting
Related Components:
- Editor Application - Content management interface
- Cosmos.Common - Shared core library
- Cosmos.BlobService - Storage abstraction
- Dynamic Configuration - Multi-tenant support
Documentation:
- Main Documentation Hub - Complete documentation index
- Azure Installation - Deploy to Azure
- Quick Start Guide - Get started quickly
Copyright (c) 2025 Moonrise Software, LLC. All rights reserved.