diff options
| author | Kyren223 <contact@kyren.codes> | 2026-10-09 06:19:56 +0300 |
|---|---|---|
| committer | Kyren223 <contact@kyren.codes> | 2026-10-09 06:19:56 +0300 |
| commit | a7ecfccc8a5f1bb8d0d3ae03dc125672b428f31f (patch) | |
| tree | 1c905b64db1da08c1bd26af2f1759fd67b3ad1f0 /website.templ | |
| parent | d3aa8982bfb70cda8d04130347e2a870aebd2d19 (diff) | |
Save
Diffstat (limited to 'website.templ')
| -rw-r--r-- | website.templ | 396 |
1 files changed, 363 insertions, 33 deletions
diff --git a/website.templ b/website.templ index 88b8c40..bec1453 100644 --- a/website.templ +++ b/website.templ @@ -1,5 +1,7 @@ package main +import "flag" + templ HeadComponent(title string, description string) { <head> <meta charset="UTF-8"/> @@ -28,8 +30,16 @@ templ HeadComponent(title string, description string) { </head> } +func Choose(chooseA bool, a string, b string) string { + if chooseA { + return a + } else { + return b + } +} + templ BlogItem(header string, blog Blog, extra string) { - @TerminalBorder(header, blog.Date.Format("January 2, 2006"), "bg-black/20 hover:bg-white/5 transition-colors duration-150 "+extra) { + @TerminalBorderForBlog(header, blog.Date.Format("January 2, 2006"), Choose(header == "", "bg-black/20 hover:bg-white/5 transition-colors duration-150", "")+" "+extra, header == "") { <span class="cursor-pointer group block"> <a href={ templ.SafeURL("/blogs/" + blog.Slug) } class="no-underline hover:no-underline"> <h1 class="text-[130%] font-bold text-(--accent) group-hover:underline"> @@ -59,17 +69,31 @@ templ TerminalStack(joined bool, extra string) { </div> } +templ TerminalBorderForBlog(header string, footer string, extra string, enable bool) { + if enable { + <div class={ "relative flex px-3.5 py-(--ypad) pt-[calc(var(--ypad)+0.0625rem)] [--ypad:var(--border-py,0.875rem)] border-[0.1rem] border-solid border-[color:var(--alt)]", extra }> + <span class="absolute px-[0.625rem] text-[1rem] left-[0.625rem] top-[-0.75rem] bg-[var(--text)] text-[color:var(--alt)]">{ header }</span> + <span class="absolute px-[0.625rem] text-[0.6rem] left-[0.625rem] bottom-[-0.55rem] bg-[var(--background)] border-[0.05rem] text-(--alt)">{ footer }</span> + { children... } + </div> + } else { + @TerminalBorder(header, footer, extra) { + { children... } + } + } +} + templ TerminalBorder(header string, footer string, extra string) { - <div class={ "relative flex px-3.5 py-(--ypad) pt-[calc(var(--ypad)+0.0625rem)] [--ypad:var(--border-py,0.875rem)] border-[0.1rem] border-solid border-[color:var(--alt)]", extra }> - <span class="absolute px-[0.625rem] text-[1rem] left-[0.625rem] top-[-0.75rem] text-[color:var(--alt)] bg-[linear-gradient(to_bottom,var(--background),var(--cmp-bg,transparent))]">{ header }</span> - <span class="absolute px-[0.625rem] text-[1rem] left-[0.625rem] bottom-[-0.75rem] text-[color:var(--alt)] bg-[linear-gradient(to_bottom,#181825,var(--background))]">{ footer }</span> - { children... } - </div> // <div class={ "relative flex px-3.5 py-(--ypad) pt-[calc(var(--ypad)+0.0625rem)] [--ypad:var(--border-py,0.875rem)] border-[0.1rem] border-solid border-[color:var(--alt)]", extra }> - // <span class="bg-transparent absolute px-[0.625rem] text-[1rem] left-[0.625rem] top-[-0.75rem] bg-[var(--background)] text-[color:var(--alt)]">{ header }</span> - // <span class="bg-transparent absolute px-[0.625rem] text-[1rem] left-[0.625rem] bottom-[-0.75rem] bg-[var(--background)] text-[color:var(--alt)]">{ footer }</span> + // <span class="absolute px-[0.625rem] text-[1rem] left-[0.625rem] top-[-0.75rem] text-[color:var(--alt)] bg-[linear-gradient(to_bottom,var(--background),var(--cmp-bg,transparent))]">{ header }</span> + // <span class="absolute px-[0.625rem] text-[1rem] left-[0.625rem] bottom-[-0.75rem] text-[color:var(--alt)] bg-[linear-gradient(to_bottom,#181825,var(--background))]">{ footer }</span> // { children... } // </div> + <div class={ "relative flex px-3.5 py-(--ypad) pt-[calc(var(--ypad)+0.0625rem)] [--ypad:var(--border-py,0.875rem)] border-[0.1rem] border-solid border-(--alt)", extra }> + <span class="absolute px-[0.625rem] text-[1rem] left-[0.625rem] top-[-0.75rem] bg-[var(--background)] text-[color:var(--alt)]">{ header }</span> + <span class="absolute px-[0.625rem] text-[1rem] left-[0.625rem] bottom-[-0.75rem] bg-[var(--background)] text-[color:var(--alt)]">{ footer }</span> + { children... } + </div> } templ CopyIcon() { @@ -240,17 +264,15 @@ templ SkillsPage(style Style) { } type Project struct { - Slug string // e.g. "my-game" - Title string // e.g. "MyGame" - Category string // e.g. "Game written in Zig" - Desc string // 1-2 line description/pitch - Tags []ProjectTag // ["Zig", "OpenGL", "Linux"] - Status string - Icon templ.Component - CgitURL string // e.g. "https://cgit.yourdomain.com/my-game" - GithubURL string // Fallback mirror link - IsFlagship bool - IsPinned bool + Slug string // e.g. "my-game" + Title string // e.g. "MyGame" + Category string // e.g. "Game written in Zig" + Desc string // 1-2 line description/pitch + Tags []ProjectTag // ["Zig", "OpenGL", "Linux"] + Status string + Icon templ.Component + CgitURL string // e.g. "https://cgit.yourdomain.com/my-game" + GithubURL string // Fallback mirror link } type ProjectTag struct { @@ -258,18 +280,37 @@ type ProjectTag struct { Color string } -type ProjectFLink struct { +type ProjectLink struct { URL string Icon templ.Component } +type FlagshipInfo struct { + Downloads []Download + Version string + Stats []Stat + Snippet string +} + +type Download struct { + Label string // "Linux", "Windows" + URL string + Size string // "42 MB" +} + +type Stat struct { + Label string + Value string +} + var p Project = Project{ Slug: "krypton", Title: "Krypton", Category: "Programming Language Compiler", Desc: "A modern Minecraft creator event. As a developer, I helped with minor improvements to the cosmetics system. ", Icon: IconCpu("text-[#F5A670] self-center"), - Status: "ON", + // Icon: IconKrypton(), + Status: "ON", Tags: []ProjectTag{ // {"Programming Language", Color("--extra")}, // {"Compiler", Color("--extra")}, @@ -277,13 +318,297 @@ var p Project = Project{ {"LLVM", Color("text-[#FFFFFF]")}, // {"Java", Color("#F5A670")}, }, - CgitURL: "https://whatever", - GithubURL: "", - IsFlagship: true, - IsPinned: false, + CgitURL: "https://whatever", + GithubURL: "", +} + +var flagship FlagshipInfo = FlagshipInfo{ + Version: "Sprout.0 2026-08-13", + Downloads: []Download{ + {"linux-amd64", "https://foobar", "23 MB"}, + // {"linux-arm64", "https://foobar", "52 MB"}, + // {"macos-arm64", "https://fooshit", "47 MB"}, + {"windows-amd64", "https://fooshit", "65.7 MB"}, + }, + // Stats: []Stat{{"lines of code", "18.7k"}}, + Snippet: ` +io :: import "core/io"; + +main :: proc() { + io.printf("Hello, %s", "world"); +} +`, +} + +var versionBeforeDownloads = false + +const flagshipClasses = "[--border-py:1.25rem] border-(--accent)! bg-white/[0.03] shadow-[0_0_1.5rem_color-mix(in_srgb,var(--accent)_25%,transparent)]" + +templ FlagshipProject(project Project, extra string) { + @TerminalBorder("", "", flagshipClasses+" "+extra) { + <div class="flex gap-8 w-full"> + <div class="flex flex-col gap-4 flex-1 min-w-0"> + <div class="flex flex-wrap items-baseline gap-x-[1ch] gap-y-[0.4rem]"> + @project.Icon + <a href={ templ.SafeURL("/projects/" + project.Slug) } class="text-[170%] font-bold text-(--accent) hover:underline">{ project.Title }</a> + <span class="text-[85%] text-(--primary)">{ project.Category }</span> + for _, tag := range project.Tags { + <code class={ "text-[75%] px-[0.4rem] inline-block rounded-[0.3rem] border-[0.01rem] bg-(--alt)/25" + " " + tag.Color }>{ tag.Name }</code> + } + <span class="ml-auto flex items-center self-center"> + @IconLink("https://git.example.com/foo", "git", "") { + @IconGit("text-(--primary)") + } + @IconLink("https://github.com/foo", "github", "") { + @IconGithub("text-(--secondary)") + } + @IconLink("https://example.com", "website", "") { + @IconExternal("text-(--accent)") + } + </span> + </div> + <p class="leading-relaxed max-w-3xl">{ project.Desc }</p> + if len(flagship.Downloads) > 0 || flagship.Version != "" { + <div class="flex flex-wrap items-center gap-x-4 gap-y-2"> + if versionBeforeDownloads { + @VersionTag(project) + } + for _, d := range flagship.Downloads { + @DownloadButton(d) + } + if !versionBeforeDownloads { + @VersionTag(project) + } + </div> + } + if len(flagship.Stats) > 0 { + <div class="flex flex-wrap gap-x-[2rem] gap-y-[0.4rem] text-[85%]"> + for _, stat := range flagship.Stats { + <span class="flex gap-[1ch]"> + <span class="font-bold text-(--primary)">{ stat.Value }</span> + <span class="text-(--alt)">{ stat.Label }</span> + </span> + } + </div> + } + </div> + if flagship.Snippet != "" { + <div class="shrink-0 self-start flex flex-col gap-[0.5rem] p-[1rem] rounded-[0.4rem] bg-black/30"> + <span class="text-[75%] text-(--alt)">example</span> + @CopyPre(flagship.Snippet, "text-[80%] leading-[normal]") { + { flagship.Snippet } + } + </div> + } + </div> + } +} + +templ VersionTag(project Project) { + if flagship.Version != "" { + <span class="flex items-baseline gap-[1ch] text-[85%]"> + <code class="text-[#46d46c]">{ flagship.Version }</code> + // <a href={ templ.SafeURL("/projects/" + project.Slug + "#changelog") } class="text-(--alt) hover:underline">changelog</a> + </span> + } +} + +templ DownloadButton(d Download) { + <a href={ templ.SafeURL(d.URL) } class="no-underline inline-flex items-center gap-[1ch] px-[0.6rem] py-[0.1rem] rounded-[0.4rem] border-[0.1rem] border-solid border-(--secondary)/60 text-[85%] text-(--secondary) transition-colors hover:bg-(--secondary)/15"> + @IconArchive("text-(--secondary)") + <span>{ d.Label }</span> + if d.Size != "" { + <span class="text-(--alt)">{ d.Size }</span> + } + </a> +} + +templ IconArchive(color string) { + @Icon(color) { + <rect width="20" height="5" x="2" y="3" rx="1"></rect> + <path d="M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8"></path> + <path d="M10 12h4"></path> + } +} + +const flagshipClassesV4 = "[--border-py:1.25rem] border-(--accent)! bg-white/[0.03] shadow-[0_0_1.5rem_color-mix(in_srgb,var(--accent)_25%,transparent)]" + +templ FlagshipProjectV4(project Project, extra string) { + @TerminalBorder("", "", flagshipClasses+" "+extra) { + <div class="flex gap-[2rem] w-full"> + <div class="flex flex-col gap-[1rem] flex-1 min-w-0"> + <div class="flex flex-wrap items-baseline gap-x-[1ch] gap-y-[0.4rem]"> + @project.Icon + <a href={ templ.SafeURL("/projects/" + project.Slug) } class="text-[170%] font-bold text-(--accent) hover:underline">{ project.Title }</a> + <span class="text-[85%] text-(--primary)">{ project.Category }</span> + for _, tag := range project.Tags { + <code class={ "text-[75%] px-[0.4rem] inline-block rounded-[0.3rem] border-[0.01rem] bg-(--alt)/25" + " " + tag.Color }>{ tag.Name }</code> + } + <span class="ml-auto flex items-center self-center"> + @IconLink("https://git.example.com/foo", "git", "") { + @IconGit("text-(--primary)") + } + @IconLink("https://github.com/foo", "github", "") { + @IconGithub("text-(--secondary)") + } + @IconLink("https://example.com", "website", "") { + @IconExternal("text-(--accent)") + } + </span> + </div> + <p class="leading-relaxed max-w-3xl">{ project.Desc }</p> + if len(project.Downloads) > 0 || project.Version != "" { + <div class="flex flex-wrap items-center gap-x-[1rem] gap-y-[0.5rem]"> + for _, d := range project.Downloads { + @DownloadButton(d) + } + if project.Version != "" { + <code class="text-[85%] text-(--alt)">{ project.Version }</code> + } + </div> + } + if len(project.Stats) > 0 { + <div class="flex flex-wrap gap-x-[2rem] gap-y-[0.4rem] text-[85%]"> + for _, stat := range project.Stats { + <span class="flex gap-[1ch]"> + <span class="font-bold text-(--primary)">{ stat.Value }</span> + <span class="text-(--alt)">{ stat.Label }</span> + </span> + } + </div> + } + </div> + if project.Snippet != "" { + <div class="shrink-0 self-start flex flex-col gap-[0.5rem] p-[1rem] rounded-[0.4rem] bg-black/30"> + <span class="text-[75%] text-(--alt)">example</span> + @CopyPre(project.Snippet, "text-[80%] leading-[normal]") { + { project.Snippet } + } + </div> + } + </div> + } } -templ FlagshipProject(project Project) { +templ DownloadButtonV4(d Download) { + <a href={ templ.SafeURL(d.URL) } class="inline-flex items-center gap-[1ch] px-[0.8rem] py-[0.3rem] rounded-[0.4rem] border-[0.1rem] border-solid border-(--alt) text-(--primary) transition-colors hover:bg-(--alt)/25"> + @IconDownload("text-(--primary)") + { d.Label } + </a> +} + +templ IconDownload(color string) { + @Icon(color) { + <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path> + <polyline points="7 10 12 15 17 10"></polyline> + <line x1="12" x2="12" y1="15" y2="3"></line> + } +} + +const flagshipClassesV3 = "[--border-py:1.25rem] border-(--primary)! bg-white/[0.03] shadow-[0_0_1.5rem_color-mix(in_srgb,var(--primary)_25%,transparent)]" + +templ FlagshipProjectV3(project Project, extra string) { + @TerminalBorder("", "", flagshipClasses+" "+extra) { + <div class="flex gap-[2rem] w-full"> + <div class="flex flex-col gap-[1rem] flex-1 min-w-0"> + <div class="flex flex-wrap items-baseline gap-x-[1ch] gap-y-[0.4rem]"> + @project.Icon + <a href={ templ.SafeURL("/projects/" + project.Slug) } class="text-[170%] font-bold text-(--accent) hover:underline">{ project.Title }</a> + <code class="px-[0.5rem] rounded-[0.3rem] border-[0.1rem] border-(--accent)/50 text-[85%] text-(--accent)">{ project.Version }</code> + <span class="text-[85%] text-(--primary)">{ project.Category }</span> + for _, tag := range project.Tags { + <code class={ "text-[75%] px-[0.4rem] inline-block rounded-[0.3rem] border-[0.01rem] bg-(--alt)/25" + " " + tag.Color }>{ tag.Name }</code> + } + <span class="ml-auto flex items-center self-center"> + @IconLink("https://git.example.com/foo", "git", "") { + @IconGit("text-(--primary)") + } + @IconLink("https://github.com/foo", "github", "") { + @IconGithub("text-(--secondary)") + } + @IconLink("https://example.com", "website", "") { + @IconExternal("text-(--accent)") + } + </span> + </div> + <p class="leading-relaxed max-w-3xl">{ project.Desc }</p> + if project.Install != "" { + @CopyPre(project.Install, "text-[85%] leading-[normal]") { + { "$ " + project.Install } + } + } + if project.Devlog != nil { + <a href={ templ.SafeURL("/blogs/" + project.Devlog.Slug) } class="text-[85%] text-(--secondary) hover:underline"> + { "latest devlog: " + project.Devlog.Title } + </a> + } + </div> + if project.Snippet != "" { + <div class="shrink-0 self-start flex flex-col gap-[0.5rem] p-[1rem] rounded-[0.4rem] bg-black/30"> + <span class="text-[75%] text-(--alt)">example</span> + @CopyPre(project.Snippet, "text-[80%] leading-[normal]") { + { project.Snippet } + } + </div> + } + </div> + } +} + +templ FlagshipProjectV2(project Project, extra string) { + @TerminalBorder(project.Version, "", flagshipClasses+" "+extra) { + <div class="flex gap-[2rem] w-full"> + <div class="flex flex-col gap-[1rem] flex-1 min-w-0"> + <div class="flex flex-wrap items-baseline gap-x-[1ch] gap-y-[0.4rem]"> + @project.Icon + <a href={ templ.SafeURL("/projects/" + project.Slug) } class="text-[170%] font-bold text-(--primary) hover:underline">{ project.Title }</a> + <span class="text-[85%] text-(--secondary)">{ project.Category }</span> + for _, tag := range project.Tags { + <code class={ "text-[75%] px-[0.4rem] inline-block rounded-[0.3rem] border-[0.01rem] bg-(--alt)/25" + " " + tag.Color }>{ tag.Name }</code> + } + <span class="ml-auto flex items-center self-center"> + @IconLink("https://git.example.com/foo", "git", "") { + @IconGit("text-(--primary)") + } + @IconLink("https://github.com/foo", "github", "") { + @IconGithub("text-(--secondary)") + } + @IconLink("https://example.com", "website", "") { + @IconExternal("text-(--accent)") + } + </span> + </div> + <p class="leading-relaxed max-w-3xl">{ project.Desc }</p> + <div class="flex flex-wrap items-center gap-[0.5ch] pt-[1rem] border-t border-white/10 text-[85%]"> + for i, stage := range project.Pipeline { + if i > 0 { + <span class="text-(--alt)">→</span> + } + <code class="px-[0.4rem] rounded-[0.3rem] bg-(--alt)/25 text-(--accent)">{ stage }</code> + } + </div> + <div class="flex flex-wrap gap-x-[2.5rem] gap-y-[0.75rem]"> + for _, stat := range project.Stats { + <div class="flex flex-col"> + <span class="text-[150%] font-bold text-(--primary)">{ stat.Value }</span> + <span class="text-[75%] text-(--alt)">{ stat.Label }</span> + </div> + } + </div> + </div> + if project.Snippet != "" { + <div class="shrink-0 self-start flex flex-col gap-[0.5rem] p-[1rem] rounded-[0.4rem] bg-black/30"> + <span class="text-[75%] text-(--alt)">example</span> + @CopyPre(project.Snippet, "text-[80%] leading-[normal]") { + { project.Snippet } + } + </div> + } + </div> + } +} + +templ FlagshipProjectV1(project Project) { <div class="relative border border-[var(--primary)]/40 rounded bg-white/[0.03] p-6 mb-10 shadow-[0_0_15px_rgba(0,0,0,0.3)]"> <!-- Header Bar --> <div class="flex items-center justify-between pb-3 mb-4 border-b border-white/10 font-mono text-xs"> @@ -401,6 +726,13 @@ templ IconExternal(color string) { } } +templ IconKrypton() { + @Icon("text-[#00f1ff]") { + <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-circle-dot preview-icon"><circle cx="12" cy="12" r="1"></circle><circle cx="12" cy="12" r="10"></circle></svg> + } + // { "\uf192" } +} + templ ProjectItem(project Project, extra string) { <div> @TerminalBorder("", "", "[--border-py:0.25rem] py-2 text-[80%] bg-black/20 hover:bg-white/5 transition-colors duration-150"+" "+extra) { @@ -438,17 +770,15 @@ func DoubleProject(project Project) Project { return project } -templ ProjectsPage(style Style, projects []Project) { +templ ProjectsPage(style Style, projects []Project, pinned int) { @TerminalLayout(style, "/home/kyren/projects") { - @FlagshipProject(p) - // @PinnedGrid(projects) - // All projects + @FlagshipProject(projects[0], "mb-[1.5rem]") @ScrollBox("") { @TerminalStack(false, "mt-[0.5rem]") { for i := 0; i < 1; i++ { - for i, project := range projects { - if i % 2 == 0 { - @ProjectItem(DoubleProject(project), "my-[-0.15rem]") + for i, project := range projects[1:] { + if i < pinned { + @ProjectItem(project, "my-[-0.15rem] border-(--text)") } else { @ProjectItem(project, "my-[-0.15rem]") } |
