Initial Pass
This commit is contained in:
commit
f4facbac7c
10 changed files with 335 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
*.gguf
|
||||||
|
svs-services-server
|
||||||
38
README.md
Normal file
38
README.md
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
I'm building a website for a joke company, that provides every service ever invented. The company's website is svsindustries.org. When going to, say, webdesign.svsindustries.org, the user will be presented with a site advertising SVS Industries' web design prowess. Similarly for, say, plumbing.svsindustries.org, hvac.svsindustries.org, management-consulting.svsindustries.org, landscaping.svsindustries.org, travel-nursing.svsindustries.org, etc. All companies have the same three employees: Chandler Swift, Eric Villnow, and Isaac Swift.
|
||||||
|
|
||||||
|
The sever will be implemented in Go, and will live behind a Caddy load balancer providing TLS termination. It should pick up the requested host, and generate content based on that. It will use a template, currently templates/a.html. That template will contain slots for the variable content. The program will fill up a Page struct (detailed later) and use that to render the page.
|
||||||
|
```go
|
||||||
|
type Color struct { // may have .rgba() and .hex() and similar functions
|
||||||
|
// something that can encode color
|
||||||
|
}
|
||||||
|
type Theme struct {
|
||||||
|
AccentColor Color
|
||||||
|
SecondaryColor Color
|
||||||
|
BackgroundColor Color
|
||||||
|
// possibly more?
|
||||||
|
}
|
||||||
|
type Testimonial struct {
|
||||||
|
Name string // Barack Obama
|
||||||
|
Position string // Frequent Design Admirer
|
||||||
|
Content string // I can't believe how good these were. After the Obamacare Website, I knew it's important to get a website right on the first try, and boy did these gentlemen manage!
|
||||||
|
}
|
||||||
|
type Page struct {
|
||||||
|
Theme Theme
|
||||||
|
Title string // "SVS Web Design"
|
||||||
|
Tagline string // "Custom websites cooked to order"
|
||||||
|
WhatWeDo string // 2-4 paragraphs following a "What We Do" header selling our incredible
|
||||||
|
ChandlerBio string // Chandler has years of experience in the [...] sector
|
||||||
|
EricBio string
|
||||||
|
IsaacBio string
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The server will keep a cache of all previous responses, to avoid time-consuming and inconsistent results. The cache will be stored in a sqlite database, with a single table with two columns, host and content; `host` will be e.g. `webdesign`; content will be a JSON encoding of the Page struct above.
|
||||||
|
|
||||||
|
There will be a 404 page that fits the primary theme of each site (e.g. for webdesign.svsindustries.org/about-us we'll return a 404 that uses the Theme, Title, and Tagline for `webdesign.svsindustries.org` to generate a fairly generic 404 page.)
|
||||||
|
|
||||||
|
To start, generate main.go.
|
||||||
|
|
||||||
|
# GGUF
|
||||||
|
|
||||||
|
https://huggingface.co/QuantFactory/SmolLM-135M-GGUF/resolve/main/SmolLM-135M.Q8_0.gguf?download=true
|
||||||
3
go.mod
Normal file
3
go.mod
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
module git.chandlerswift.com/chandlerswift/svs-services-server
|
||||||
|
|
||||||
|
go 1.25.4
|
||||||
0
go.sum
Normal file
0
go.sum
Normal file
BIN
headshots/chandlerswift.jpg
Normal file
BIN
headshots/chandlerswift.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
BIN
headshots/ericvillnow.jpg
Normal file
BIN
headshots/ericvillnow.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
BIN
headshots/isaacswift.jpg
Normal file
BIN
headshots/isaacswift.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 290 KiB |
103
main.go
Normal file
103
main.go
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
"html/template"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed templates/index.html
|
||||||
|
var indexHTML string
|
||||||
|
|
||||||
|
//go:embed templates/404.html
|
||||||
|
var notFoundHTML string
|
||||||
|
|
||||||
|
//go:embed headshots/*
|
||||||
|
var headshots embed.FS
|
||||||
|
|
||||||
|
type Color struct { // may have .rgba() and .hex() and similar
|
||||||
|
Hex string
|
||||||
|
// something that can encode color
|
||||||
|
}
|
||||||
|
|
||||||
|
type Theme struct {
|
||||||
|
AccentColor Color
|
||||||
|
SecondaryColor Color
|
||||||
|
BackgroundColor Color
|
||||||
|
// possibly more?
|
||||||
|
}
|
||||||
|
|
||||||
|
type Testimonial struct {
|
||||||
|
Name string
|
||||||
|
Position string
|
||||||
|
Quote string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Page struct {
|
||||||
|
Theme Theme
|
||||||
|
Occupation string
|
||||||
|
Tagline string
|
||||||
|
WhatWeDo string
|
||||||
|
ChandlerBio string
|
||||||
|
EricBio string
|
||||||
|
IsaacBio string
|
||||||
|
Testimonials []Testimonial
|
||||||
|
CurrentYear int
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPageDataForHost(host string) Page {
|
||||||
|
return Page{
|
||||||
|
Theme: Theme{
|
||||||
|
AccentColor: Color{
|
||||||
|
Hex: "#FF5733",
|
||||||
|
},
|
||||||
|
SecondaryColor: Color{
|
||||||
|
Hex: "#33C1FF",
|
||||||
|
},
|
||||||
|
BackgroundColor: Color{
|
||||||
|
// Creamy off-white
|
||||||
|
Hex: "#FFF8E7",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Occupation: "Web Design",
|
||||||
|
Tagline: "Custom websites cooked to order",
|
||||||
|
WhatWeDo: "Lorem Ipsum…",
|
||||||
|
ChandlerBio: "Chandler has years of experience in the [...] sector",
|
||||||
|
EricBio: "Eric is a seasoned professional in [...]",
|
||||||
|
IsaacBio: "Isaac specializes in [...]",
|
||||||
|
Testimonials: []Testimonial{
|
||||||
|
{
|
||||||
|
Name: "Barack Obama",
|
||||||
|
Position: "Poolhall acquaintance",
|
||||||
|
Quote: "After the fiasco of the ACA Website, I know how important it is to get a website right on the first try, and boy do these gentlemen deliver!",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Ada Lovelace",
|
||||||
|
Position: "Pioneer of Computing",
|
||||||
|
Quote: "The elegance and functionality of the websites created by SVS Web Design are truly ahead of their time.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Steve Jobs",
|
||||||
|
Position: "Visionary Entrepreneur",
|
||||||
|
Quote: "Design is not just what it looks like and feels like. Design is how it works. SVS Web Design understands this principle deeply.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
CurrentYear: time.Now().Year(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var tmpl = template.Must(template.New("index").Parse(indexHTML))
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
host := r.Host
|
||||||
|
pageData := getPageDataForHost(host)
|
||||||
|
// Render indexHTML as template
|
||||||
|
tmpl.Execute(w, pageData)
|
||||||
|
})
|
||||||
|
// Serve embedded headshots file
|
||||||
|
http.Handle("/headshots/", http.FileServer(http.FS(headshots)))
|
||||||
|
|
||||||
|
http.ListenAndServe(":8080", nil)
|
||||||
|
}
|
||||||
0
templates/404.html
Normal file
0
templates/404.html
Normal file
189
templates/index.html
Normal file
189
templates/index.html
Normal file
|
|
@ -0,0 +1,189 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Swift, Villnow & Swift Industries: {{.Occupation}}</title>
|
||||||
|
<!-- Bootstrap CSS -->
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||||
|
background: #f8f9fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
#what-we-do {
|
||||||
|
background: #e6e6e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
background: linear-gradient(135deg, #0d6efd, #6610f2);
|
||||||
|
color: white;
|
||||||
|
padding: 80px 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
header h1 {
|
||||||
|
font-size: 3rem;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about-section img {
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 150px;
|
||||||
|
height: 150px;
|
||||||
|
object-fit: cover;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
background: #212529;
|
||||||
|
color: white;
|
||||||
|
margin-top: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-fun {
|
||||||
|
background: linear-gradient(135deg, #0d6efd, #6610f2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sans {
|
||||||
|
font-family: "Comic Neue", cursive;
|
||||||
|
font-weight: 600;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link
|
||||||
|
href="https://fonts.googleapis.com/css2?family=Comic+Neue:ital,wght@0,300;0,400;0,700;1,300;1,400;1,700&display=swap"
|
||||||
|
rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<!-- Header -->
|
||||||
|
<header>
|
||||||
|
<div class="container">
|
||||||
|
<h1>SVS Industries</h1>
|
||||||
|
<h2 class="sans">{{.Occupation}}</h2>
|
||||||
|
<p class="lead">{{.Tagline}}</p>
|
||||||
|
<a href="#about" class="btn btn-light btn-lg mt-3">Meet Our Team</a>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
|
||||||
|
<section id="what-we-do" class="py-5">
|
||||||
|
<div class="container">
|
||||||
|
<h2 class="text-center mb-4">What We Do</h2>
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-lg-10">
|
||||||
|
{{.WhatWeDo}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- About Us -->
|
||||||
|
<section id="about" class="py-5">
|
||||||
|
<div class="container">
|
||||||
|
<h2 class="text-center mb-5">About Us</h2>
|
||||||
|
<div class="row g-4">
|
||||||
|
|
||||||
|
<div class="col-md-4 text-center d-flex flex-column align-items-center about-section">
|
||||||
|
<img src="headshots/chandlerswift.jpg"
|
||||||
|
alt="Chandler Swift">
|
||||||
|
<h4 class="mt-3">Chandler <b>Swift</b></h4>
|
||||||
|
<div class="flex-grow-1 d-flex flex-column justify-content-evenly">
|
||||||
|
{{.ChandlerBio}}
|
||||||
|
</div>
|
||||||
|
<a href="https://chandlerswift.com/" class="btn btn-dark btn-fun btn-lg mt-3">chandlerswift.com</a>
|
||||||
|
</div>
|
||||||
|
<hr class="d-xl-none d-xxl-none d-lg-none d-md-none">
|
||||||
|
<div class="col-md-4 text-center d-flex flex-column align-items-center about-section">
|
||||||
|
<img src="headshots/ericvillnow.jpg"
|
||||||
|
alt="Developer 2">
|
||||||
|
<h4 class="mt-3">Eric <b>Villnow</b></h4>
|
||||||
|
<div class="flex-grow-1 d-flex flex-column justify-content-evenly">
|
||||||
|
{{.EricBio}}
|
||||||
|
</div>
|
||||||
|
<a href="https://vill.now/" class="btn btn-dark btn-fun btn-lg mt-3">vill.now</a>
|
||||||
|
</div>
|
||||||
|
<hr class="d-xl-none d-xxl-none d-lg-none d-md-none">
|
||||||
|
<div class="col-md-4 text-center d-flex flex-column align-items-center about-section">
|
||||||
|
<img src="headshots/isaacswift.jpg" alt="Isaac Swift">
|
||||||
|
<h4 class="mt-3">Isaac <b>Swift</b></h4>
|
||||||
|
<div class="flex-grow-1 d-flex flex-column justify-content-evenly">
|
||||||
|
{{.IsaacBio}}
|
||||||
|
</div>
|
||||||
|
<a href="https://isaacswift.com/" class="btn btn-dark btn-fun btn-lg mt-3">isaacswift.com</a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="testimonials" class="py-5">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<h2 class="text-center mb-5">What Our Clients Say</h2>
|
||||||
|
<div id="testimonialCarousel" class="carousel carousel-dark slide" data-bs-ride="carousel">
|
||||||
|
<div class="carousel-inner">
|
||||||
|
{{range $index, $testimonial := .Testimonials}}
|
||||||
|
<div class="carousel-item text-center {{if eq $index 0}}active{{end}}">
|
||||||
|
<p class="fs-5 fst-italic">"{{$testimonial.Quote}}"</p>
|
||||||
|
<h5 class="mt-3">— {{$testimonial.Name}}, {{$testimonial.Position}}</h5>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Carousel controls -->
|
||||||
|
<button class="carousel-control-prev" type="button" data-bs-target="#testimonialCarousel"
|
||||||
|
data-bs-slide="prev">
|
||||||
|
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
|
||||||
|
<span class="visually-hidden">Previous</span>
|
||||||
|
</button>
|
||||||
|
<button class="carousel-control-next" type="button" data-bs-target="#testimonialCarousel"
|
||||||
|
data-bs-slide="next">
|
||||||
|
<span class="carousel-control-next-icon" aria-hidden="true"></span>
|
||||||
|
<span class="visually-hidden">Next</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#clients {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.client-logo {
|
||||||
|
max-height: 100px;
|
||||||
|
filter: grayscale(100%);
|
||||||
|
opacity: 0.6;
|
||||||
|
transition: opacity 0.3s ease;
|
||||||
|
margin-left: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.client-logo:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<!-- Footer -->
|
||||||
|
<div class="footer d-flex justify-content-between align-items-md-end p-5 flex-column flex-md-row">
|
||||||
|
<p>
|
||||||
|
<b>Swift, Villnow & Swift Industries</b><br>
|
||||||
|
{{.Occupation}} Division<br>
|
||||||
|
<a href="tel:2182105180">(218) 210-5180</a><br>
|
||||||
|
<a href="mailto:sales@svsindustries.org">sales@svsindustries.org</a>
|
||||||
|
|
||||||
|
</p>
|
||||||
|
<p>© {{.CurrentYear}} Swift, Villnow & Swift Industries. All rights reserved.</p>
|
||||||
|
</div>
|
||||||
|
<!-- Bootstrap JS -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue