feat(pages): add blog section support to landing page templates
Add blog section configuration and rendering to landing pages. Includes: - New BlogSectionConfig with headline, max posts, and excerpt options - Logo source selection (URL, repo avatar, or org avatar) - Recent blog posts display with featured images - Navigation links to blog section - Absolute repo URLs for custom domain support
This commit is contained in:
@@ -44,6 +44,9 @@ type LandingConfig struct {
|
||||
// CTA section
|
||||
CTASection CTASectionConfig `yaml:"cta_section,omitempty"`
|
||||
|
||||
// Blog section
|
||||
Blog BlogSectionConfig `yaml:"blog,omitempty"`
|
||||
|
||||
// Footer
|
||||
Footer FooterConfig `yaml:"footer,omitempty"`
|
||||
|
||||
@@ -62,9 +65,10 @@ type LandingConfig struct {
|
||||
|
||||
// BrandConfig represents brand/identity settings
|
||||
type BrandConfig struct {
|
||||
Name string `yaml:"name,omitempty"`
|
||||
LogoURL string `yaml:"logo_url,omitempty"`
|
||||
Tagline string `yaml:"tagline,omitempty"`
|
||||
Name string `yaml:"name,omitempty"`
|
||||
LogoURL string `yaml:"logo_url,omitempty"`
|
||||
LogoSource string `yaml:"logo_source,omitempty"` // "url" (default), "repo", or "org" — selects avatar source
|
||||
Tagline string `yaml:"tagline,omitempty"`
|
||||
}
|
||||
|
||||
// HeroConfig represents hero section settings
|
||||
@@ -145,6 +149,16 @@ type CTASectionConfig struct {
|
||||
Button CTAButton `yaml:"button,omitempty"`
|
||||
}
|
||||
|
||||
// BlogSectionConfig represents blog section settings on the landing page
|
||||
type BlogSectionConfig struct {
|
||||
Enabled bool `yaml:"enabled,omitempty"`
|
||||
Headline string `yaml:"headline,omitempty"`
|
||||
Subheadline string `yaml:"subheadline,omitempty"`
|
||||
MaxPosts int `yaml:"max_posts,omitempty"` // default 3
|
||||
ShowExcerpt bool `yaml:"show_excerpt,omitempty"` // show subtitle as excerpt
|
||||
CTAButton CTAButton `yaml:"cta_button,omitempty"` // "View All Posts" link
|
||||
}
|
||||
|
||||
// FooterConfig represents footer settings
|
||||
type FooterConfig struct {
|
||||
Links []FooterLink `yaml:"links,omitempty"`
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
blog_model "code.gitcaddy.com/server/v3/models/blog"
|
||||
"code.gitcaddy.com/server/v3/models/renderhelper"
|
||||
repo_model "code.gitcaddy.com/server/v3/models/repo"
|
||||
"code.gitcaddy.com/server/v3/modules/git"
|
||||
@@ -106,6 +107,12 @@ func renderLandingPage(ctx *context.Context, repo *repo_model.Repository, config
|
||||
ctx.Data["Title"] = getPageTitle(repo, config)
|
||||
ctx.Data["PageIsPagesLanding"] = true
|
||||
|
||||
// Provide absolute repo URL for links on custom domains
|
||||
ctx.Data["RepoURL"] = repo.HTMLURL()
|
||||
|
||||
// Resolve logo URL based on logo_source config
|
||||
ctx.Data["LogoURL"] = resolveLogoURL(ctx, repo, config)
|
||||
|
||||
// Load README content
|
||||
readme, err := loadReadmeContent(ctx, repo)
|
||||
if err != nil {
|
||||
@@ -123,15 +130,54 @@ func renderLandingPage(ctx *context.Context, repo *repo_model.Repository, config
|
||||
if err == nil && release != nil {
|
||||
_ = repo_model.GetReleaseAttachments(ctx, release)
|
||||
ctx.Data["LatestRelease"] = release
|
||||
// Provide tag name with leading "v" stripped to avoid double "v" in templates
|
||||
ctx.Data["LatestReleaseTag"] = strings.TrimPrefix(release.TagName, "v")
|
||||
}
|
||||
ctx.Data["PublicReleases"] = config.Advanced.PublicReleases
|
||||
|
||||
// Load recent blog posts if blog section is enabled
|
||||
if config.Blog.Enabled && repo.BlogEnabled {
|
||||
maxPosts := config.Blog.MaxPosts
|
||||
if maxPosts <= 0 {
|
||||
maxPosts = 3
|
||||
}
|
||||
posts, _, err := blog_model.GetBlogPostsByRepoID(ctx, &blog_model.BlogPostSearchOptions{
|
||||
RepoID: repo.ID,
|
||||
AnyPublicStatus: true,
|
||||
Page: 1,
|
||||
PageSize: maxPosts,
|
||||
})
|
||||
if err == nil && len(posts) > 0 {
|
||||
for _, post := range posts {
|
||||
_ = post.LoadAuthor(ctx)
|
||||
_ = post.LoadFeaturedImage(ctx)
|
||||
}
|
||||
ctx.Data["BlogPosts"] = posts
|
||||
}
|
||||
}
|
||||
|
||||
// Select template based on config
|
||||
tpl := selectTemplate(config.Template)
|
||||
|
||||
ctx.HTML(http.StatusOK, tpl)
|
||||
}
|
||||
|
||||
// resolveLogoURL determines the logo URL based on the brand.logo_source config
|
||||
func resolveLogoURL(ctx *context.Context, repo *repo_model.Repository, config *pages_module.LandingConfig) string {
|
||||
switch config.Brand.LogoSource {
|
||||
case "repo":
|
||||
return repo.AvatarLink(ctx)
|
||||
case "org":
|
||||
if err := repo.LoadOwner(ctx); err != nil {
|
||||
log.Warn("Failed to load repo owner for logo: %v", err)
|
||||
return ""
|
||||
}
|
||||
return repo.Owner.AvatarLink(ctx)
|
||||
default: // "url" or empty
|
||||
return config.Brand.LogoURL
|
||||
}
|
||||
}
|
||||
|
||||
// getPageTitle returns the page title
|
||||
func getPageTitle(repo *repo_model.Repository, config *pages_module.LandingConfig) string {
|
||||
if config.SEO.Title != "" {
|
||||
|
||||
@@ -1113,7 +1113,8 @@
|
||||
{{if .Config.ValueProps}}<a href="#value-props" class="nb-nav-link">Why</a>{{end}}
|
||||
{{if .Config.Features}}<a href="#features" class="nb-nav-link">Features</a>{{end}}
|
||||
{{if .Config.Pricing.Plans}}<a href="#pricing" class="nb-nav-link">Pricing</a>{{end}}
|
||||
<a href="{{.Repository.Link}}" class="nb-nav-repo">
|
||||
{{if and .Config.Blog.Enabled .BlogPosts}}<a href="#blog" class="nb-nav-link">Blog</a>{{end}}
|
||||
<a href="{{.RepoURL}}" class="nb-nav-repo">
|
||||
<img src="/assets/img/gitcaddy-icon.svg" width="16" height="16" alt="GitCaddy">
|
||||
Repo
|
||||
</a>
|
||||
@@ -1134,7 +1135,8 @@
|
||||
{{if .Config.ValueProps}}<a href="#value-props" class="nb-nav-link">Why</a>{{end}}
|
||||
{{if .Config.Features}}<a href="#features" class="nb-nav-link">Features</a>{{end}}
|
||||
{{if .Config.Pricing.Plans}}<a href="#pricing" class="nb-nav-link">Pricing</a>{{end}}
|
||||
<a href="{{.Repository.Link}}" class="nb-nav-repo">
|
||||
{{if and .Config.Blog.Enabled .BlogPosts}}<a href="#blog" class="nb-nav-link">Blog</a>{{end}}
|
||||
<a href="{{.RepoURL}}" class="nb-nav-repo">
|
||||
<img src="/assets/img/gitcaddy-icon.svg" width="16" height="16" alt="GitCaddy">
|
||||
Repository
|
||||
</a>
|
||||
@@ -1188,12 +1190,12 @@
|
||||
<div class="nb-downloads-inner">
|
||||
<div class="nb-downloads-header nb-reveal">
|
||||
<div class="nb-section-label">Download</div>
|
||||
<h2><span class="nb-glow-text">v{{.LatestRelease.TagName}}</span></h2>
|
||||
<h2><span class="nb-glow-text">v{{.LatestReleaseTag}}</span></h2>
|
||||
<p>Get the latest release</p>
|
||||
</div>
|
||||
<div class="nb-downloads-grid">
|
||||
{{range .LatestRelease.Attachments}}
|
||||
<a href="{{$.Repository.Link}}/releases/download/{{$.LatestRelease.TagName}}/{{.Name}}" class="nb-download-item nb-reveal">
|
||||
<a href="{{$.RepoURL}}/releases/download/{{$.LatestRelease.TagName}}/{{.Name}}" class="nb-download-item nb-reveal">
|
||||
{{svg "octicon-download" 16}}
|
||||
{{.Name}}
|
||||
<span class="nb-download-size">{{FileSize .Size}}</span>
|
||||
@@ -1340,6 +1342,44 @@
|
||||
</section>
|
||||
{{end}}
|
||||
|
||||
<!-- Blog Section -->
|
||||
{{if and .Config.Blog.Enabled .BlogPosts}}
|
||||
<section class="nb-features" id="blog" style="border-top: 1px solid var(--nb-border-hard);">
|
||||
<div class="nb-section-header nb-reveal">
|
||||
<div class="nb-section-label">Blog</div>
|
||||
<h2>{{if .Config.Blog.Headline}}<span class="nb-glow-text">{{.Config.Blog.Headline}}</span>{{else}}Latest <span class="nb-glow-text">Posts</span>{{end}}</h2>
|
||||
{{if .Config.Blog.Subheadline}}<p>{{.Config.Blog.Subheadline}}</p>{{end}}
|
||||
</div>
|
||||
<div class="nb-feature-list">
|
||||
{{range .BlogPosts}}
|
||||
<a href="{{$.RepoURL}}/blog/{{.ID}}" class="nb-feature-row nb-reveal" style="text-decoration: none; color: inherit;">
|
||||
{{if .FeaturedImage}}
|
||||
<div style="flex-shrink: 0; width: 80px; height: 56px; overflow: hidden; clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 8px, 100% 100%, 8px 100%, 0 calc(100% - 8px));">
|
||||
<img src="{{.FeaturedImage.DownloadURL}}" alt="{{.Title}}" style="width: 100%; height: 100%; object-fit: cover;">
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="nb-feature-icon">
|
||||
{{svg "octicon-note" 22}}
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="nb-feature-title">{{.Title}}</div>
|
||||
<div class="nb-feature-desc">
|
||||
{{if and $.Config.Blog.ShowExcerpt .Subtitle}}{{.Subtitle}}{{else}}{{if .Author}}{{.Author.Name}}{{end}} · {{DateUtils.AbsoluteShort .CreatedUnix}}{{end}}
|
||||
</div>
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
{{if .Config.Blog.CTAButton.Label}}
|
||||
<div style="text-align: center; margin-top: 48px;" class="nb-reveal">
|
||||
<a href="{{if .Config.Blog.CTAButton.URL}}{{.Config.Blog.CTAButton.URL}}{{else}}{{.RepoURL}}/blog{{end}}" class="nb-btn-secondary">
|
||||
{{.Config.Blog.CTAButton.Label}}
|
||||
{{svg "octicon-arrow-right" 18}}
|
||||
</a>
|
||||
</div>
|
||||
{{end}}
|
||||
</section>
|
||||
{{end}}
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="nb-footer">
|
||||
<div class="nb-footer-brand">
|
||||
@@ -1370,8 +1410,8 @@
|
||||
<a href="{{.URL}}" class="nb-footer-link">{{.Label}}</a>
|
||||
{{end}}
|
||||
{{else}}
|
||||
<a href="{{.Repository.Link}}" class="nb-footer-link">Repository</a>
|
||||
<a href="{{.Repository.Link}}/releases" class="nb-footer-link">Releases</a>
|
||||
<a href="{{.RepoURL}}" class="nb-footer-link">Repository</a>
|
||||
<a href="{{.RepoURL}}/releases" class="nb-footer-link">Releases</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@@ -977,13 +977,14 @@
|
||||
<a href="{{.URL}}" class="ea-nav-link">{{.Label}}</a>
|
||||
{{end}}
|
||||
{{else}}
|
||||
<a href="{{.Repository.Link}}/wiki" class="ea-nav-link">Docs</a>
|
||||
<a href="{{.Repository.Link}}" class="ea-nav-link">API</a>
|
||||
<a href="{{.RepoURL}}/wiki" class="ea-nav-link">Docs</a>
|
||||
<a href="{{.RepoURL}}" class="ea-nav-link">API</a>
|
||||
{{end}}
|
||||
{{if .Config.ValueProps}}<a href="#why" class="ea-nav-link">Why</a>{{end}}
|
||||
{{if .Config.Features}}<a href="#features" class="ea-nav-link">Features</a>{{end}}
|
||||
{{if .Config.Pricing.Plans}}<a href="#pricing" class="ea-nav-link">Pricing</a>{{end}}
|
||||
<a href="{{.Repository.Link}}" class="ea-btn-text">
|
||||
{{if and .Config.Blog.Enabled .BlogPosts}}<a href="#blog" class="ea-nav-link">Blog</a>{{end}}
|
||||
<a href="{{.RepoURL}}" class="ea-btn-text">
|
||||
<img src="/assets/img/gitcaddy-icon.svg" width="16" height="16" alt="GitCaddy">
|
||||
Repository
|
||||
</a>
|
||||
@@ -996,13 +997,14 @@
|
||||
<a href="{{.URL}}" class="ea-nav-link">{{.Label}}</a>
|
||||
{{end}}
|
||||
{{else}}
|
||||
<a href="{{.Repository.Link}}/wiki" class="ea-nav-link">Docs</a>
|
||||
<a href="{{.Repository.Link}}" class="ea-nav-link">API</a>
|
||||
<a href="{{.RepoURL}}/wiki" class="ea-nav-link">Docs</a>
|
||||
<a href="{{.RepoURL}}" class="ea-nav-link">API</a>
|
||||
{{end}}
|
||||
{{if .Config.ValueProps}}<a href="#why" class="ea-nav-link">Why</a>{{end}}
|
||||
{{if .Config.Features}}<a href="#features" class="ea-nav-link">Features</a>{{end}}
|
||||
{{if .Config.Pricing.Plans}}<a href="#pricing" class="ea-nav-link">Pricing</a>{{end}}
|
||||
<a href="{{.Repository.Link}}" class="ea-btn-text">
|
||||
{{if and .Config.Blog.Enabled .BlogPosts}}<a href="#blog" class="ea-nav-link">Blog</a>{{end}}
|
||||
<a href="{{.RepoURL}}" class="ea-btn-text">
|
||||
<img src="/assets/img/gitcaddy-icon.svg" width="16" height="16" alt="GitCaddy">
|
||||
Repository
|
||||
</a>
|
||||
@@ -1023,7 +1025,7 @@
|
||||
{{svg "octicon-arrow-right" 14}}
|
||||
</a>
|
||||
{{else}}
|
||||
<a href="{{.Repository.Link}}" class="ea-btn-primary">
|
||||
<a href="{{.RepoURL}}" class="ea-btn-primary">
|
||||
Get Started
|
||||
{{svg "octicon-arrow-right" 14}}
|
||||
</a>
|
||||
@@ -1063,7 +1065,7 @@
|
||||
</div>
|
||||
{{if .LatestRelease}}
|
||||
<div class="ea-stat ea-reveal ea-reveal-delay-2">
|
||||
<div class="ea-stat-value">v{{.LatestRelease.TagName}}</div>
|
||||
<div class="ea-stat-value">v{{.LatestReleaseTag}}</div>
|
||||
<div class="ea-stat-label">Latest</div>
|
||||
</div>
|
||||
{{end}}
|
||||
@@ -1076,11 +1078,11 @@
|
||||
{{if and .PublicReleases .LatestRelease .LatestRelease.Attachments}}
|
||||
<section class="ea-downloads">
|
||||
<div class="ea-section-label ea-reveal">Downloads</div>
|
||||
<h2 class="ea-section-title ea-reveal">v{{.LatestRelease.TagName}}</h2>
|
||||
<h2 class="ea-section-title ea-reveal">v{{.LatestReleaseTag}}</h2>
|
||||
<p style="color: var(--ea-muted); font-size: 17px; margin-bottom: 28px;" class="ea-reveal">Get the latest release</p>
|
||||
<div class="ea-downloads-list ea-reveal">
|
||||
{{range .LatestRelease.Attachments}}
|
||||
<a href="{{$.Repository.Link}}/releases/download/{{$.LatestRelease.TagName}}/{{.Name}}" class="ea-download-item">
|
||||
<a href="{{$.RepoURL}}/releases/download/{{$.LatestRelease.TagName}}/{{.Name}}" class="ea-download-item">
|
||||
{{svg "octicon-download" 16}}
|
||||
{{.Name}}
|
||||
<span class="ea-download-size">{{FileSize .Size}}</span>
|
||||
@@ -1221,6 +1223,41 @@
|
||||
</section>
|
||||
{{end}}
|
||||
|
||||
<!-- Blog Section -->
|
||||
{{if and .Config.Blog.Enabled .BlogPosts}}
|
||||
<section class="ea-section" id="blog">
|
||||
<div class="ea-section-label ea-reveal">Blog</div>
|
||||
<h2 class="ea-section-title ea-reveal">{{if .Config.Blog.Headline}}{{.Config.Blog.Headline}}{{else}}Latest Posts{{end}}</h2>
|
||||
{{if .Config.Blog.Subheadline}}<p style="color: var(--ea-muted); font-size: 17px; margin-bottom: 32px;" class="ea-reveal">{{.Config.Blog.Subheadline}}</p>{{end}}
|
||||
{{range .BlogPosts}}
|
||||
<a href="{{$.RepoURL}}/blog/{{.ID}}" class="ea-value-item ea-reveal" style="text-decoration: none; color: inherit;">
|
||||
{{if .FeaturedImage}}
|
||||
<div style="flex-shrink: 0; width: 120px; height: 80px; overflow: hidden; border-radius: 4px;">
|
||||
<img src="{{.FeaturedImage.DownloadURL}}" alt="{{.Title}}" style="width: 100%; height: 100%; object-fit: cover;">
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="ea-value-body">
|
||||
<div class="ea-value-title">{{.Title}}</div>
|
||||
{{if and $.Config.Blog.ShowExcerpt .Subtitle}}
|
||||
<div class="ea-value-desc">{{.Subtitle}}</div>
|
||||
{{end}}
|
||||
<div style="font-family: 'IBM Plex Mono', monospace; font-size: 11px; color: var(--ea-light); letter-spacing: 0.04em; margin-top: 4px;">
|
||||
{{if .Author}}{{.Author.Name}}{{end}} · {{DateUtils.AbsoluteShort .CreatedUnix}}
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
{{end}}
|
||||
{{if .Config.Blog.CTAButton.Label}}
|
||||
<div style="margin-top: 32px;" class="ea-reveal">
|
||||
<a href="{{if .Config.Blog.CTAButton.URL}}{{.Config.Blog.CTAButton.URL}}{{else}}{{.RepoURL}}/blog{{end}}" class="ea-btn-text">
|
||||
{{.Config.Blog.CTAButton.Label}}
|
||||
{{svg "octicon-arrow-right" 14}}
|
||||
</a>
|
||||
</div>
|
||||
{{end}}
|
||||
</section>
|
||||
{{end}}
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="ea-footer">
|
||||
<span class="ea-footer-copyright">{{if .Config.Footer.Copyright}}{{.Config.Footer.Copyright}}{{else}}© <script>document.write(new Date().getFullYear())</script> {{if .Config.Brand.Name}}{{.Config.Brand.Name}}{{else}}{{.Repository.Name}}{{end}}{{end}}</span>
|
||||
@@ -1244,8 +1281,8 @@
|
||||
<a href="{{.URL}}" class="ea-footer-link">{{.Label}}</a>
|
||||
{{end}}
|
||||
{{else}}
|
||||
<a href="{{.Repository.Link}}" class="ea-footer-link">Repository</a>
|
||||
<a href="{{.Repository.Link}}/wiki" class="ea-footer-link">Documentation</a>
|
||||
<a href="{{.RepoURL}}" class="ea-footer-link">Repository</a>
|
||||
<a href="{{.RepoURL}}/wiki" class="ea-footer-link">Documentation</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@@ -953,8 +953,8 @@
|
||||
<!-- Navigation -->
|
||||
<nav class="osh-nav">
|
||||
<a href="/" class="osh-nav-brand">
|
||||
{{if .Config.Brand.LogoURL}}
|
||||
<img src="{{.Config.Brand.LogoURL}}" alt="{{.Config.Brand.Name}}" style="height: 30px;">
|
||||
{{if .LogoURL}}
|
||||
<img src="{{.LogoURL}}" alt="{{.Config.Brand.Name}}" style="height: 30px; border-radius: 4px;">
|
||||
{{else}}
|
||||
<div class="osh-nav-logo">
|
||||
{{svg "octicon-zap" 14}}
|
||||
@@ -968,14 +968,15 @@
|
||||
<a href="{{.URL}}" class="osh-nav-link">{{.Label}}</a>
|
||||
{{end}}
|
||||
{{else}}
|
||||
<a href="{{.Repository.Link}}" class="osh-nav-link">Repository</a>
|
||||
<a href="{{.Repository.Link}}/wiki" class="osh-nav-link">Docs</a>
|
||||
<a href="{{.Repository.Link}}/releases" class="osh-nav-link">Releases</a>
|
||||
<a href="{{.RepoURL}}" class="osh-nav-link">Repository</a>
|
||||
<a href="{{.RepoURL}}/wiki" class="osh-nav-link">Docs</a>
|
||||
<a href="{{.RepoURL}}/releases" class="osh-nav-link">Releases</a>
|
||||
{{end}}
|
||||
{{if .Config.ValueProps}}<a href="#value-props" class="osh-nav-link">Why Us</a>{{end}}
|
||||
{{if .Config.Features}}<a href="#features" class="osh-nav-link">Features</a>{{end}}
|
||||
{{if .Config.Pricing.Plans}}<a href="#pricing" class="osh-nav-link">Pricing</a>{{end}}
|
||||
<a href="{{.Repository.Link}}" class="osh-nav-cta">
|
||||
{{if and .Config.Blog.Enabled .BlogPosts}}<a href="#blog" class="osh-nav-link">Blog</a>{{end}}
|
||||
<a href="{{.RepoURL}}" class="osh-nav-cta">
|
||||
<img src="/assets/img/gitcaddy-icon.svg" width="16" height="16" alt="GitCaddy">
|
||||
Repository
|
||||
</a>
|
||||
@@ -992,7 +993,7 @@
|
||||
<div class="osh-hero-content">
|
||||
<div class="osh-badge osh-reveal visible">
|
||||
<span class="osh-badge-dot"></span>
|
||||
{{if .LatestRelease}}v{{.LatestRelease.TagName}} released{{else}}Open Source{{end}}
|
||||
{{if .LatestRelease}}v{{.LatestReleaseTag}} released{{else}}Open Source{{end}}
|
||||
</div>
|
||||
|
||||
<h1 class="osh-reveal visible osh-reveal-delay-1">{{if .Config.Hero.Headline}}{{.Config.Hero.Headline}}{{else}}{{.Repository.Name}}{{end}}</h1>
|
||||
@@ -1008,7 +1009,7 @@
|
||||
{{svg "octicon-arrow-right" 16}}
|
||||
</a>
|
||||
{{else}}
|
||||
<a href="{{.Repository.Link}}" class="osh-btn-primary">
|
||||
<a href="{{.RepoURL}}" class="osh-btn-primary">
|
||||
Get Started
|
||||
{{svg "octicon-arrow-right" 16}}
|
||||
</a>
|
||||
@@ -1020,7 +1021,7 @@
|
||||
{{.Config.Hero.SecondaryCTA.Label}}
|
||||
</a>
|
||||
{{else}}
|
||||
<a href="{{.Repository.Link}}" class="osh-btn-secondary">
|
||||
<a href="{{.RepoURL}}" class="osh-btn-secondary">
|
||||
<img src="/assets/img/gitcaddy-icon.svg" width="16" height="16" alt="GitCaddy">
|
||||
View Source
|
||||
</a>
|
||||
@@ -1061,7 +1062,7 @@
|
||||
</div>
|
||||
{{if .LatestRelease}}
|
||||
<div class="osh-stat-item">
|
||||
<div class="osh-stat-value">v{{.LatestRelease.TagName}}</div>
|
||||
<div class="osh-stat-value">v{{.LatestReleaseTag}}</div>
|
||||
<div class="osh-stat-label">Latest</div>
|
||||
</div>
|
||||
{{end}}
|
||||
@@ -1074,11 +1075,11 @@
|
||||
{{if and .PublicReleases .LatestRelease .LatestRelease.Attachments}}
|
||||
<section class="osh-downloads">
|
||||
<div class="osh-downloads-inner osh-reveal">
|
||||
<h2>Download v{{.LatestRelease.TagName}}</h2>
|
||||
<h2>Download v{{.LatestReleaseTag}}</h2>
|
||||
<p>Get the latest release</p>
|
||||
<div class="osh-downloads-grid">
|
||||
{{range .LatestRelease.Attachments}}
|
||||
<a href="{{$.Repository.Link}}/releases/download/{{$.LatestRelease.TagName}}/{{.Name}}" class="osh-download-item">
|
||||
<a href="{{$.RepoURL}}/releases/download/{{$.LatestRelease.TagName}}/{{.Name}}" class="osh-download-item">
|
||||
{{svg "octicon-download" 16}}
|
||||
{{.Name}}
|
||||
<span class="osh-download-size">{{FileSize .Size}}</span>
|
||||
@@ -1211,7 +1212,7 @@
|
||||
{{if .Config.CTASection.Subheadline}}
|
||||
<p>{{.Config.CTASection.Subheadline}}</p>
|
||||
{{end}}
|
||||
<a href="{{if .Config.CTASection.Button.URL}}{{.Config.CTASection.Button.URL}}{{else}}{{.Repository.Link}}{{end}}" class="osh-btn-primary" style="padding: 16px 32px; font-size: 15px;">
|
||||
<a href="{{if .Config.CTASection.Button.URL}}{{.Config.CTASection.Button.URL}}{{else}}{{.RepoURL}}{{end}}" class="osh-btn-primary" style="padding: 16px 32px; font-size: 15px;">
|
||||
{{if .Config.CTASection.Button.Label}}{{.Config.CTASection.Button.Label}}{{else}}Get Started{{end}}
|
||||
{{svg "octicon-arrow-right" 16}}
|
||||
</a>
|
||||
@@ -1219,6 +1220,45 @@
|
||||
</section>
|
||||
{{end}}
|
||||
|
||||
<!-- Blog Section -->
|
||||
{{if and .Config.Blog.Enabled .BlogPosts}}
|
||||
<section class="osh-features" id="blog" style="border-top: 1px solid rgba(255,255,255,0.04);">
|
||||
<div class="osh-features-inner">
|
||||
<div class="osh-section-header osh-reveal">
|
||||
<div class="osh-section-label">Blog</div>
|
||||
<h2>{{if .Config.Blog.Headline}}{{.Config.Blog.Headline}}{{else}}Latest Posts{{end}}</h2>
|
||||
{{if .Config.Blog.Subheadline}}<p>{{.Config.Blog.Subheadline}}</p>{{end}}
|
||||
</div>
|
||||
<div class="osh-features-grid">
|
||||
{{range .BlogPosts}}
|
||||
<a href="{{$.RepoURL}}/blog/{{.ID}}" class="osh-feature-card osh-reveal" style="text-decoration: none; color: inherit; display: flex; flex-direction: column;">
|
||||
{{if .FeaturedImage}}
|
||||
<div style="margin: -32px -32px 20px -32px; overflow: hidden; border-radius: 12px 12px 0 0;">
|
||||
<img src="{{.FeaturedImage.DownloadURL}}" alt="{{.Title}}" style="width: 100%; height: 180px; object-fit: cover; display: block;">
|
||||
</div>
|
||||
{{end}}
|
||||
<h3 class="osh-feature-title">{{.Title}}</h3>
|
||||
{{if and $.Config.Blog.ShowExcerpt .Subtitle}}
|
||||
<p class="osh-feature-desc">{{.Subtitle}}</p>
|
||||
{{end}}
|
||||
<div style="margin-top: auto; padding-top: 16px; font-size: 12px; color: var(--osh-muted); font-family: 'IBM Plex Mono', monospace;">
|
||||
{{if .Author}}{{.Author.Name}}{{end}} · {{DateUtils.AbsoluteShort .CreatedUnix}}
|
||||
</div>
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
{{if .Config.Blog.CTAButton.Label}}
|
||||
<div style="text-align: center; margin-top: 48px;" class="osh-reveal">
|
||||
<a href="{{if .Config.Blog.CTAButton.URL}}{{.Config.Blog.CTAButton.URL}}{{else}}{{.RepoURL}}/blog{{end}}" class="osh-btn-secondary">
|
||||
{{.Config.Blog.CTAButton.Label}}
|
||||
{{svg "octicon-arrow-right" 16}}
|
||||
</a>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</section>
|
||||
{{end}}
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="osh-footer">
|
||||
<div class="osh-footer-brand">
|
||||
@@ -1245,10 +1285,10 @@
|
||||
<a href="{{.URL}}" class="osh-footer-link">{{.Label}}</a>
|
||||
{{end}}
|
||||
{{else}}
|
||||
<a href="{{.Repository.Link}}" class="osh-footer-link">Repository</a>
|
||||
<a href="{{.Repository.Link}}/wiki" class="osh-footer-link">Documentation</a>
|
||||
<a href="{{.Repository.Link}}/releases" class="osh-footer-link">Releases</a>
|
||||
<a href="{{.Repository.Link}}/issues" class="osh-footer-link">Issues</a>
|
||||
<a href="{{.RepoURL}}" class="osh-footer-link">Repository</a>
|
||||
<a href="{{.RepoURL}}/wiki" class="osh-footer-link">Documentation</a>
|
||||
<a href="{{.RepoURL}}/releases" class="osh-footer-link">Releases</a>
|
||||
<a href="{{.RepoURL}}/issues" class="osh-footer-link">Issues</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@@ -1070,8 +1070,8 @@
|
||||
<!-- Navigation -->
|
||||
<nav class="gm-nav">
|
||||
<a href="/" class="gm-nav-brand">
|
||||
{{if .Config.Brand.LogoURL}}
|
||||
<img src="{{.Config.Brand.LogoURL}}" alt="{{.Config.Brand.Name}}" style="height: 32px;">
|
||||
{{if .LogoURL}}
|
||||
<img src="{{.LogoURL}}" alt="{{.Config.Brand.Name}}" style="height: 32px; border-radius: 6px;">
|
||||
{{else}}
|
||||
<div class="gm-nav-logo">
|
||||
{{svg "octicon-package" 16}}
|
||||
@@ -1088,11 +1088,12 @@
|
||||
{{if .Config.ValueProps}}<a href="#value-props" class="gm-nav-link">Why</a>{{end}}
|
||||
{{if .Config.Features}}<a href="#features" class="gm-nav-link">Features</a>{{end}}
|
||||
{{if .Config.Pricing.Plans}}<a href="#pricing" class="gm-nav-link">Pricing</a>{{end}}
|
||||
<a href="{{.Repository.Link}}" class="gm-nav-repo">
|
||||
{{if and .Config.Blog.Enabled .BlogPosts}}<a href="#blog" class="gm-nav-link">Blog</a>{{end}}
|
||||
<a href="{{.RepoURL}}" class="gm-nav-repo">
|
||||
<img src="/assets/img/gitcaddy-icon.svg" width="16" height="16" alt="GitCaddy">
|
||||
Repository
|
||||
</a>
|
||||
<a href="{{if .Config.Hero.PrimaryCTA.URL}}{{.Config.Hero.PrimaryCTA.URL}}{{else}}{{.Repository.Link}}{{end}}" class="gm-btn-primary" style="padding: 10px 20px; font-size: 13px;">
|
||||
<a href="{{if .Config.Hero.PrimaryCTA.URL}}{{.Config.Hero.PrimaryCTA.URL}}{{else}}{{.RepoURL}}{{end}}" class="gm-btn-primary" style="padding: 10px 20px; font-size: 13px;">
|
||||
<span>{{if .Config.Hero.PrimaryCTA.Label}}{{.Config.Hero.PrimaryCTA.Label}}{{else}}Get Started{{end}}</span>
|
||||
</a>
|
||||
</div>
|
||||
@@ -1107,7 +1108,8 @@
|
||||
{{if .Config.ValueProps}}<a href="#value-props" class="gm-nav-link">Why</a>{{end}}
|
||||
{{if .Config.Features}}<a href="#features" class="gm-nav-link">Features</a>{{end}}
|
||||
{{if .Config.Pricing.Plans}}<a href="#pricing" class="gm-nav-link">Pricing</a>{{end}}
|
||||
<a href="{{.Repository.Link}}" class="gm-nav-repo">
|
||||
{{if and .Config.Blog.Enabled .BlogPosts}}<a href="#blog" class="gm-nav-link">Blog</a>{{end}}
|
||||
<a href="{{.RepoURL}}" class="gm-nav-repo">
|
||||
<img src="/assets/img/gitcaddy-icon.svg" width="16" height="16" alt="GitCaddy">
|
||||
Repository
|
||||
</a>
|
||||
@@ -1131,7 +1133,7 @@
|
||||
</p>
|
||||
|
||||
<div class="gm-hero-ctas gm-reveal gm-reveal-delay-3">
|
||||
<a href="{{if .Config.Hero.PrimaryCTA.URL}}{{.Config.Hero.PrimaryCTA.URL}}{{else}}{{.Repository.Link}}{{end}}" class="gm-btn-primary">
|
||||
<a href="{{if .Config.Hero.PrimaryCTA.URL}}{{.Config.Hero.PrimaryCTA.URL}}{{else}}{{.RepoURL}}{{end}}" class="gm-btn-primary">
|
||||
<span>
|
||||
{{if .Config.Hero.PrimaryCTA.Label}}{{.Config.Hero.PrimaryCTA.Label}}{{else}}Get Started{{end}}
|
||||
{{svg "octicon-arrow-right" 16}}
|
||||
@@ -1189,12 +1191,12 @@
|
||||
<section class="gm-downloads">
|
||||
<div class="gm-downloads-inner">
|
||||
<div class="gm-downloads-header gm-reveal">
|
||||
<h2>Download v{{.LatestRelease.TagName}}</h2>
|
||||
<h2>Download v{{.LatestReleaseTag}}</h2>
|
||||
<p>Get the latest release</p>
|
||||
</div>
|
||||
<div class="gm-downloads-grid">
|
||||
{{range .LatestRelease.Attachments}}
|
||||
<a href="{{$.Repository.Link}}/releases/download/{{$.LatestRelease.TagName}}/{{.Name}}" class="gm-download-item gm-reveal">
|
||||
<a href="{{$.RepoURL}}/releases/download/{{$.LatestRelease.TagName}}/{{.Name}}" class="gm-download-item gm-reveal">
|
||||
{{svg "octicon-download" 16}}
|
||||
{{.Name}}
|
||||
<span class="gm-download-size">{{FileSize .Size}}</span>
|
||||
@@ -1340,7 +1342,7 @@
|
||||
{{if .Config.CTASection.Subheadline}}
|
||||
<p>{{.Config.CTASection.Subheadline}}</p>
|
||||
{{end}}
|
||||
<a href="{{if .Config.CTASection.Button.URL}}{{.Config.CTASection.Button.URL}}{{else}}{{.Repository.Link}}{{end}}" class="gm-btn-primary" style="font-size: 16px; padding: 16px 36px;">
|
||||
<a href="{{if .Config.CTASection.Button.URL}}{{.Config.CTASection.Button.URL}}{{else}}{{.RepoURL}}{{end}}" class="gm-btn-primary" style="font-size: 16px; padding: 16px 36px;">
|
||||
<span>
|
||||
{{if .Config.CTASection.Button.Label}}{{.Config.CTASection.Button.Label}}{{else}}Get Started Free{{end}}
|
||||
{{svg "octicon-arrow-right" 16}}
|
||||
@@ -1350,6 +1352,44 @@
|
||||
</section>
|
||||
{{end}}
|
||||
|
||||
<!-- Blog Section -->
|
||||
{{if and .Config.Blog.Enabled .BlogPosts}}
|
||||
<section class="gm-section" id="blog">
|
||||
<div class="gm-section-inner">
|
||||
<div class="gm-section-header gm-reveal">
|
||||
<h2>{{if .Config.Blog.Headline}}{{.Config.Blog.Headline}}{{else}}Latest <span class="gm-serif">Posts</span>{{end}}</h2>
|
||||
{{if .Config.Blog.Subheadline}}<p>{{.Config.Blog.Subheadline}}</p>{{end}}
|
||||
</div>
|
||||
<div class="gm-value-grid">
|
||||
{{range .BlogPosts}}
|
||||
<a href="{{$.RepoURL}}/blog/{{.ID}}" class="gm-value-card gm-reveal" style="text-decoration: none; color: inherit; display: flex; flex-direction: column;">
|
||||
{{if .FeaturedImage}}
|
||||
<div style="margin: -36px -36px 24px -36px; overflow: hidden; border-radius: 20px 20px 0 0;">
|
||||
<img src="{{.FeaturedImage.DownloadURL}}" alt="{{.Title}}" style="width: 100%; height: 180px; object-fit: cover; display: block;">
|
||||
</div>
|
||||
{{end}}
|
||||
<h3>{{.Title}}</h3>
|
||||
{{if and $.Config.Blog.ShowExcerpt .Subtitle}}
|
||||
<p>{{.Subtitle}}</p>
|
||||
{{end}}
|
||||
<div style="margin-top: auto; padding-top: 16px; font-size: 12px; color: var(--gm-light);">
|
||||
{{if .Author}}{{.Author.Name}}{{end}} · {{DateUtils.AbsoluteShort .CreatedUnix}}
|
||||
</div>
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
{{if .Config.Blog.CTAButton.Label}}
|
||||
<div style="text-align: center; margin-top: 48px;" class="gm-reveal">
|
||||
<a href="{{if .Config.Blog.CTAButton.URL}}{{.Config.Blog.CTAButton.URL}}{{else}}{{.RepoURL}}/blog{{end}}" class="gm-btn-secondary">
|
||||
{{.Config.Blog.CTAButton.Label}}
|
||||
{{svg "octicon-arrow-right" 16}}
|
||||
</a>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</section>
|
||||
{{end}}
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="gm-footer">
|
||||
<div class="gm-footer-brand">
|
||||
@@ -1376,10 +1416,10 @@
|
||||
<a href="{{.URL}}" class="gm-footer-link">{{.Label}}</a>
|
||||
{{end}}
|
||||
{{else}}
|
||||
<a href="{{.Repository.Link}}" class="gm-footer-link">Repository</a>
|
||||
<a href="{{.Repository.Link}}/wiki" class="gm-footer-link">Docs</a>
|
||||
<a href="{{.Repository.Link}}/releases" class="gm-footer-link">Releases</a>
|
||||
<a href="{{.Repository.Link}}/issues" class="gm-footer-link">Issues</a>
|
||||
<a href="{{.RepoURL}}" class="gm-footer-link">Repository</a>
|
||||
<a href="{{.RepoURL}}/wiki" class="gm-footer-link">Docs</a>
|
||||
<a href="{{.RepoURL}}/releases" class="gm-footer-link">Releases</a>
|
||||
<a href="{{.RepoURL}}/issues" class="gm-footer-link">Issues</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
Reference in New Issue
Block a user