Initial commit: Hugo static site for nerdy events
Some checks failed
Build Hugo Site / build (push) Failing after 19s
Some checks failed
Build Hugo Site / build (push) Failing after 19s
- Custom cyberpunk/console theme with pure CSS - Event management with RSS and iCal calendar feeds - Gitea workflow for automated deployment - Complete documentation and setup instructions 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
11
layouts/_partials/footer.html
Normal file
11
layouts/_partials/footer.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<div class="ascii-border">
|
||||
<pre>
|
||||
+===================================================================+
|
||||
</pre>
|
||||
</div>
|
||||
<p class="prompt">NERDER.LAND {{ now.Year }} - Connecting the tech underground</p>
|
||||
<p style="margin-top: 1rem; font-size: 0.8rem;">
|
||||
<a href="{{ "events/feed.xml" | absURL }}">📡 RSS Feed</a> |
|
||||
<a href="{{ "events/calendar.ics" | absURL }}">📅 Calendar Subscription</a> |
|
||||
<a href="mailto:{{ .Site.Params.eventSubmissionEmail | default "events@nerder.land" }}?subject=Event Submission&body=Please include:%0A%0AEvent Name:%0ADate & Time:%0ALocation:%0ADescription:%0AOrganizer:%0AContact Info:%0ACost:%0ARegistration URL (if any):">📧 Submit an Event</a>
|
||||
</p>
|
||||
10
layouts/_partials/header.html
Normal file
10
layouts/_partials/header.html
Normal file
@@ -0,0 +1,10 @@
|
||||
{{ if .IsHome }}
|
||||
<h1>{{ site.Title }}</h1>
|
||||
<div class="ascii-border">
|
||||
<pre>
|
||||
+===================================================================+
|
||||
</pre>
|
||||
</div>
|
||||
{{ else }}
|
||||
<h2><a href="{{ "/" | relURL }}">{{ site.Title }}</a></h2>
|
||||
{{ end }}
|
||||
29
layouts/baseof.html
Normal file
29
layouts/baseof.html
Normal file
@@ -0,0 +1,29 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ or site.Language.LanguageCode }}" dir="{{ or site.Language.LanguageDirection `ltr` }}">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{ if .IsHome }}{{ site.Title }}{{ else }}{{ .Title }} - {{ site.Title }}{{ end }}</title>
|
||||
<link rel="stylesheet" href="{{ "css/style.css" | relURL }}">
|
||||
|
||||
<!-- RSS Feeds -->
|
||||
<link rel="alternate" type="application/rss+xml" title="{{ site.Title }} - All Content" href="{{ "feed.xml" | absURL }}">
|
||||
<link rel="alternate" type="application/rss+xml" title="{{ site.Title }} - Events" href="{{ "events/feed.xml" | absURL }}">
|
||||
|
||||
<!-- Calendar Feeds -->
|
||||
<link rel="alternate" type="text/calendar" title="{{ site.Title }} - Events Calendar" href="{{ "events/calendar.ics" | absURL }}">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<header>
|
||||
{{ partial "header.html" . }}
|
||||
</header>
|
||||
<main>
|
||||
{{ block "main" . }}{{ end }}
|
||||
</main>
|
||||
<footer>
|
||||
{{ partial "footer.html" . }}
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
48
layouts/events/calendar.ics
Normal file
48
layouts/events/calendar.ics
Normal file
@@ -0,0 +1,48 @@
|
||||
BEGIN:VCALENDAR
|
||||
VERSION:2.0
|
||||
PRODID:-//NERDER.LAND//Event Calendar//EN
|
||||
NAME:{{ .Site.Title }} Events
|
||||
X-WR-CALNAME:{{ .Site.Title }} Events
|
||||
DESCRIPTION:{{ .Site.Params.description }}
|
||||
TIMEZONE-ID:America/Denver
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/Denver
|
||||
BEGIN:DAYLIGHT
|
||||
TZOFFSETFROM:-0700
|
||||
TZOFFSETTO:-0600
|
||||
TZNAME:MDT
|
||||
DTSTART:20250309T020000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
|
||||
END:DAYLIGHT
|
||||
BEGIN:STANDARD
|
||||
TZOFFSETFROM:-0600
|
||||
TZOFFSETTO:-0700
|
||||
TZNAME:MST
|
||||
DTSTART:20251102T020000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
|
||||
END:STANDARD
|
||||
END:VTIMEZONE
|
||||
{{- range .RegularPages }}
|
||||
BEGIN:VEVENT
|
||||
UID:{{ .File.UniqueID }}@{{ $.Site.BaseURL | replaceRE "^https?://" "" }}
|
||||
DTSTART;TZID=America/Denver:{{ .Params.date | dateFormat "20060102T150405" }}
|
||||
{{- if .Params.end_date }}
|
||||
DTEND;TZID=America/Denver:{{ .Params.end_date | dateFormat "20060102T150405" }}
|
||||
{{- else }}
|
||||
DTEND;TZID=America/Denver:{{ .Params.date.Add (time.ParseDuration "2h") | dateFormat "20060102T150405" }}
|
||||
{{- end }}
|
||||
DTSTAMP:{{ now | dateFormat "20060102T150405Z" }}
|
||||
SUMMARY:{{ .Title }}
|
||||
DESCRIPTION:{{ .Summary | replaceRE "\n" "\\n" | replaceRE "," "\\," }}
|
||||
{{- if .Params.location }}
|
||||
LOCATION:{{ .Params.location | replaceRE "," "\\," }}
|
||||
{{- end }}
|
||||
URL:{{ .Permalink }}
|
||||
{{- if .Params.organizer }}
|
||||
ORGANIZER:{{ .Params.organizer | replaceRE "," "\\," }}
|
||||
{{- end }}
|
||||
STATUS:CONFIRMED
|
||||
TRANSP:OPAQUE
|
||||
END:VEVENT
|
||||
{{- end }}
|
||||
END:VCALENDAR
|
||||
39
layouts/events/rss.xml
Normal file
39
layouts/events/rss.xml
Normal file
@@ -0,0 +1,39 @@
|
||||
{{- $pctx := . -}}
|
||||
{{- if .IsHome -}}{{ $pctx = .Site }}{{- end -}}
|
||||
{{- $pages := slice -}}
|
||||
{{- if or $.IsHome $.IsSection -}}
|
||||
{{- $pages = $pctx.RegularPages -}}
|
||||
{{- else -}}
|
||||
{{- $pages = $pctx.Pages -}}
|
||||
{{- end -}}
|
||||
{{- $limit := .Site.Config.Services.RSS.Limit -}}
|
||||
{{- if ge $limit 1 -}}
|
||||
{{- $pages = $pages | first $limit -}}
|
||||
{{- end -}}
|
||||
{{- printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" | safeHTML }}
|
||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<channel>
|
||||
<title>{{ if eq .Title .Site.Title }}{{ .Site.Title }}{{ else }}{{ with .Title }}{{.}} on {{ end }}{{ .Site.Title }}{{ end }}</title>
|
||||
<link>{{ .Permalink }}</link>
|
||||
<description>{{ .Site.Params.description | default "Recent events" }}</description>
|
||||
<generator>Hugo -- gohugo.io</generator>{{ with .Site.LanguageCode }}
|
||||
<language>{{.}}</language>{{end}}{{ with .Site.Author.email }}
|
||||
<managingEditor>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</managingEditor>{{end}}{{ with .Site.Author.email }}
|
||||
<webMaster>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</webMaster>{{end}}{{ with .Site.Copyright }}
|
||||
<copyright>{{.}}</copyright>{{end}}{{ if not .Date.IsZero }}
|
||||
<lastBuildDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</lastBuildDate>{{ end }}
|
||||
{{- with .OutputFormats.Get "RSS" -}}
|
||||
{{ printf "<atom:link href=%q rel=\"self\" type=%q />" .Permalink .MediaType | safeHTML }}
|
||||
{{- end -}}
|
||||
{{ range $pages }}
|
||||
<item>
|
||||
<title>{{ .Title }}</title>
|
||||
<link>{{ .Permalink }}</link>
|
||||
<pubDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</pubDate>
|
||||
{{ with .Site.Author.email }}<author>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</author>{{end}}
|
||||
<guid>{{ .Permalink }}</guid>
|
||||
<description>{{ with .Params.location }}📍 {{ . }} | {{ end }}{{ with .Params.date }}🗓️ {{ dateFormat "January 2, 2006 at 3:04 PM MST" . }} | {{ end }}{{ with .Params.cost }}💰 {{ . }} | {{ end }}{{ .Summary | html }}</description>
|
||||
</item>
|
||||
{{ end }}
|
||||
</channel>
|
||||
</rss>
|
||||
98
layouts/events/single.html
Normal file
98
layouts/events/single.html
Normal file
@@ -0,0 +1,98 @@
|
||||
{{ define "main" }}
|
||||
<article class="event-detail">
|
||||
<div class="ascii-border">
|
||||
<pre>
|
||||
+==================================================================+
|
||||
| EVENT DETAILS |
|
||||
+==================================================================+
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<h1>{{ .Title }}</h1>
|
||||
|
||||
<div class="event-meta">
|
||||
<div class="meta-item">
|
||||
<span class="meta-label">Date & Time</span>
|
||||
<span class="meta-value">{{ .Params.date | dateFormat "Monday, January 2, 2006 at 3:04 PM MST" }}</span>
|
||||
</div>
|
||||
|
||||
{{ if .Params.end_date }}
|
||||
<div class="meta-item">
|
||||
<span class="meta-label">End Time</span>
|
||||
<span class="meta-value">{{ .Params.end_date | dateFormat "Monday, January 2, 2006 at 3:04 PM MST" }}</span>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
<div class="meta-item">
|
||||
<span class="meta-label">Timezone</span>
|
||||
<span class="meta-value">Mountain Time (UTC-6)</span>
|
||||
</div>
|
||||
|
||||
{{ if .Params.location }}
|
||||
<div class="meta-item">
|
||||
<span class="meta-label">Location</span>
|
||||
<span class="meta-value">{{ .Params.location }}</span>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{ if .Params.organizer }}
|
||||
<div class="meta-item">
|
||||
<span class="meta-label">Organizer</span>
|
||||
<span class="meta-value">{{ .Params.organizer }}</span>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{ if .Params.capacity }}
|
||||
<div class="meta-item">
|
||||
<span class="meta-label">Capacity</span>
|
||||
<span class="meta-value">{{ .Params.capacity }} people</span>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{ if .Params.cost }}
|
||||
<div class="meta-item">
|
||||
<span class="meta-label">Cost</span>
|
||||
<span class="meta-value">{{ .Params.cost }}</span>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
|
||||
<div class="event-content">
|
||||
{{ .Content }}
|
||||
</div>
|
||||
|
||||
{{ if .Params.registration_url }}
|
||||
<div class="registration">
|
||||
<div class="ascii-border">
|
||||
<pre>
|
||||
+--------------------------------------------------------------+
|
||||
| REGISTRATION |
|
||||
+--------------------------------------------------------------+
|
||||
</pre>
|
||||
</div>
|
||||
<p class="prompt"><a href="{{ .Params.registration_url }}">Register for this event</a></p>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{ if .Params.contact }}
|
||||
<div class="contact">
|
||||
<h3>Contact Information</h3>
|
||||
<p>{{ .Params.contact }}</p>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
<div class="calendar-actions">
|
||||
<div class="ascii-border">
|
||||
<pre>
|
||||
+--------------------------------------------------------------+
|
||||
| ADD TO CALENDAR |
|
||||
+--------------------------------------------------------------+
|
||||
</pre>
|
||||
</div>
|
||||
<p class="prompt">
|
||||
<a href="{{ .RelPermalink }}calendar.ics" download>📅 Download Event (.ics)</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</article>
|
||||
{{ end }}
|
||||
48
layouts/events/single.ics
Normal file
48
layouts/events/single.ics
Normal file
@@ -0,0 +1,48 @@
|
||||
BEGIN:VCALENDAR
|
||||
VERSION:2.0
|
||||
PRODID:-//NERDER.LAND//Event Calendar//EN
|
||||
NAME:{{ .Title }}
|
||||
X-WR-CALNAME:{{ .Title }}
|
||||
TIMEZONE-ID:America/Denver
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/Denver
|
||||
BEGIN:DAYLIGHT
|
||||
TZOFFSETFROM:-0700
|
||||
TZOFFSETTO:-0600
|
||||
TZNAME:MDT
|
||||
DTSTART:20250309T020000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
|
||||
END:DAYLIGHT
|
||||
BEGIN:STANDARD
|
||||
TZOFFSETFROM:-0600
|
||||
TZOFFSETTO:-0700
|
||||
TZNAME:MST
|
||||
DTSTART:20251102T020000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
|
||||
END:STANDARD
|
||||
END:VTIMEZONE
|
||||
BEGIN:VEVENT
|
||||
UID:{{ .File.UniqueID }}@{{ .Site.BaseURL | replaceRE "^https?://" "" }}
|
||||
DTSTART;TZID=America/Denver:{{ .Params.date | dateFormat "20060102T150405" }}
|
||||
{{- if .Params.end_date }}
|
||||
DTEND;TZID=America/Denver:{{ .Params.end_date | dateFormat "20060102T150405" }}
|
||||
{{- else }}
|
||||
DTEND;TZID=America/Denver:{{ .Params.date.Add (time.ParseDuration "2h") | dateFormat "20060102T150405" }}
|
||||
{{- end }}
|
||||
DTSTAMP:{{ now | dateFormat "20060102T150405Z" }}
|
||||
SUMMARY:{{ .Title }}
|
||||
DESCRIPTION:{{ .Content | plainify | replaceRE "\n" "\\n" | replaceRE "," "\\," }}
|
||||
{{- if .Params.location }}
|
||||
LOCATION:{{ .Params.location | replaceRE "," "\\," }}
|
||||
{{- end }}
|
||||
URL:{{ .Permalink }}
|
||||
{{- if .Params.organizer }}
|
||||
ORGANIZER:{{ .Params.organizer | replaceRE "," "\\," }}
|
||||
{{- end }}
|
||||
{{- if .Params.contact }}
|
||||
CONTACT:{{ .Params.contact | replaceRE "," "\\," }}
|
||||
{{- end }}
|
||||
STATUS:CONFIRMED
|
||||
TRANSP:OPAQUE
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
||||
44
layouts/home.html
Normal file
44
layouts/home.html
Normal file
@@ -0,0 +1,44 @@
|
||||
{{ define "main" }}
|
||||
<div class="intro">
|
||||
<p class="prompt">{{ .Site.Params.description | default "Welcome to the underground tech scene." }}</p>
|
||||
</div>
|
||||
|
||||
<div class="ascii-border">
|
||||
<pre>
|
||||
+==================================================================+
|
||||
| UPCOMING EVENTS |
|
||||
+==================================================================+
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
{{ $futureEvents := where .Site.RegularPages "Section" "events" }}
|
||||
{{ $futureEvents := where $futureEvents "Params.date" "ge" now }}
|
||||
{{ $futureEvents := $futureEvents.ByParam "date" }}
|
||||
|
||||
{{ if $futureEvents }}
|
||||
<ul class="event-list">
|
||||
{{ range $futureEvents }}
|
||||
<li class="event-item">
|
||||
<div class="event-date">{{ .Params.date | dateFormat "Monday, January 2, 2006 at 3:04 PM MST" }}</div>
|
||||
<h3 class="event-title">
|
||||
<a href="{{ .RelPermalink }}">{{ .Title }}</a>
|
||||
</h3>
|
||||
{{ if .Params.location }}
|
||||
<div class="event-location">📍 {{ .Params.location }}</div>
|
||||
{{ end }}
|
||||
{{ if .Params.cost }}
|
||||
<div class="event-cost">💰 {{ .Params.cost }}</div>
|
||||
{{ end }}
|
||||
<div class="event-description">{{ .Summary }}</div>
|
||||
<div class="event-link">
|
||||
<a href="{{ .RelPermalink }}">View Details →</a>
|
||||
</div>
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
{{ else }}
|
||||
<div class="no-events">
|
||||
<p class="prompt">No upcoming events found. Check back later for more cyberpunk gatherings!</p>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
76
layouts/single.html
Normal file
76
layouts/single.html
Normal file
@@ -0,0 +1,76 @@
|
||||
{{ define "main" }}
|
||||
<article class="event-detail">
|
||||
<div class="ascii-border">
|
||||
+==================================================================+
|
||||
| EVENT DETAILS |
|
||||
+==================================================================+
|
||||
</div>
|
||||
|
||||
<h1>{{ .Title }}</h1>
|
||||
|
||||
<div class="event-meta">
|
||||
<div class="meta-item">
|
||||
<span class="meta-label">Date & Time</span>
|
||||
<span class="meta-value">{{ .Params.date | dateFormat "Monday, January 2, 2006 at 3:04 PM" }}</span>
|
||||
</div>
|
||||
|
||||
{{ if .Params.end_date }}
|
||||
<div class="meta-item">
|
||||
<span class="meta-label">End Time</span>
|
||||
<span class="meta-value">{{ .Params.end_date | dateFormat "Monday, January 2, 2006 at 3:04 PM" }}</span>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{ if .Params.location }}
|
||||
<div class="meta-item">
|
||||
<span class="meta-label">Location</span>
|
||||
<span class="meta-value">{{ .Params.location }}</span>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{ if .Params.organizer }}
|
||||
<div class="meta-item">
|
||||
<span class="meta-label">Organizer</span>
|
||||
<span class="meta-value">{{ .Params.organizer }}</span>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{ if .Params.capacity }}
|
||||
<div class="meta-item">
|
||||
<span class="meta-label">Capacity</span>
|
||||
<span class="meta-value">{{ .Params.capacity }} people</span>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{ if .Params.cost }}
|
||||
<div class="meta-item">
|
||||
<span class="meta-label">Cost</span>
|
||||
<span class="meta-value">{{ .Params.cost }}</span>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
|
||||
<div class="event-content">
|
||||
{{ .Content }}
|
||||
</div>
|
||||
|
||||
{{ if .Params.registration_url }}
|
||||
<div class="registration">
|
||||
<div class="ascii-border">
|
||||
+--------------------------------------------------------------+
|
||||
| REGISTRATION |
|
||||
+--------------------------------------------------------------+
|
||||
</div>
|
||||
<p class="prompt"><a href="{{ .Params.registration_url }}">Register for this event</a></p>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{ if .Params.contact }}
|
||||
<div class="contact">
|
||||
<h3>Contact Information</h3>
|
||||
<p>{{ .Params.contact }}</p>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
</article>
|
||||
{{ end }}
|
||||
Reference in New Issue
Block a user