2
0

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:
2026-03-07 10:34:51 -05:00
parent b7d8fcc719
commit 238f0974d8
6 changed files with 268 additions and 51 deletions

View File

@@ -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"`

View File

@@ -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 != "" {

View File

@@ -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>

View File

@@ -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}}&copy; <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>

View File

@@ -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>

View File

@@ -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>