feat: Initial commit
This commit is contained in:
7
.editorconfig
Normal file
7
.editorconfig
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*.swift]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
tab_width = 2
|
||||||
|
trim_trailing_whitespace = true
|
||||||
3
.gitattributes
vendored
Normal file
3
.gitattributes
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
*.gif filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.jpg filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.png filter=lfs diff=lfs merge=lfs -text
|
||||||
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
.DS_Store
|
||||||
|
/.build
|
||||||
|
/Packages
|
||||||
|
xcuserdata/
|
||||||
|
DerivedData/
|
||||||
|
.swiftpm/configuration/registries.json
|
||||||
|
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
|
||||||
|
.netrc
|
||||||
11
.swiftformat
Normal file
11
.swiftformat
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
--self init-only
|
||||||
|
--indent 2
|
||||||
|
--ifdef indent
|
||||||
|
--trimwhitespace always
|
||||||
|
--wraparguments before-first
|
||||||
|
--wrapparameters before-first
|
||||||
|
--wrapcollections preserve
|
||||||
|
--wrapconditions after-first
|
||||||
|
--typeblanklines preserve
|
||||||
|
--commas inline
|
||||||
|
--stripunusedargs closure-only
|
||||||
78
Package.resolved
Normal file
78
Package.resolved
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
{
|
||||||
|
"originHash" : "5d7da13ee05350773a3642a17ad9bfd12d659ceb6e153869823bf4e618f9b62d",
|
||||||
|
"pins" : [
|
||||||
|
{
|
||||||
|
"identity" : "parsley",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/loopwerk/Parsley",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "ad35091c7a790f04fc5a912c8bde8963eba753d2",
|
||||||
|
"version" : "0.9.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "pathkit",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/kylef/PathKit",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "3bfd2737b700b9a36565a8c94f4ad2b050a5e574",
|
||||||
|
"version" : "1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "saga",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/loopwerk/Saga",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "a0c91194ef119a08481c87f1603424d7d12abda1",
|
||||||
|
"version" : "2.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "sagaparsleymarkdownreader",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/loopwerk/SagaParsleyMarkdownReader",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "9605b14aa43e32eec454d2dff26bcaf95a1a1a93",
|
||||||
|
"version" : "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "sagaswimrenderer",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/loopwerk/SagaSwimRenderer",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "b6186c767689768c5d1efc21b169947ede16c1d0",
|
||||||
|
"version" : "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "spectre",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/kylef/Spectre.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "26cc5e9ae0947092c7139ef7ba612e34646086c7",
|
||||||
|
"version" : "0.10.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "swift-cmark-gfm",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/stackotter/swift-cmark-gfm",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "7ec44e7384793e507cf046336aef68586719a24e",
|
||||||
|
"version" : "1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "swim",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/robb/Swim",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "a0943e6f3cb5751ee7b69ed43a33613ea67d0c6a",
|
||||||
|
"version" : "0.4.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version" : 3
|
||||||
|
}
|
||||||
26
Package.swift
Normal file
26
Package.swift
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
// swift-tools-version: 5.10
|
||||||
|
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
||||||
|
|
||||||
|
import PackageDescription
|
||||||
|
|
||||||
|
let package = Package(
|
||||||
|
name: "Mhoush",
|
||||||
|
platforms: [.macOS(.v12)],
|
||||||
|
dependencies: [
|
||||||
|
.package(url: "https://github.com/loopwerk/Saga", from: "2.0.0"),
|
||||||
|
.package(url: "https://github.com/loopwerk/SagaParsleyMarkdownReader", from: "1.0.0"),
|
||||||
|
.package(url: "https://github.com/loopwerk/SagaSwimRenderer", from: "1.0.0")
|
||||||
|
],
|
||||||
|
targets: [
|
||||||
|
// Targets are the basic building blocks of a package, defining a module or a test suite.
|
||||||
|
// Targets can depend on other targets in this package and products from dependencies.
|
||||||
|
.executableTarget(
|
||||||
|
name: "Mhoush",
|
||||||
|
dependencies: [
|
||||||
|
.product(name: "Saga", package: "Saga"),
|
||||||
|
.product(name: "SagaParsleyMarkdownReader", package: "SagaParsleyMarkdownReader"),
|
||||||
|
.product(name: "SagaSwimRenderer", package: "SagaSwimRenderer")
|
||||||
|
]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
27
Sources/Mhoush/Extensions.swift
Normal file
27
Sources/Mhoush/Extensions.swift
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import Foundation
|
||||||
|
import Saga
|
||||||
|
|
||||||
|
extension Date {
|
||||||
|
func formatted(_ format: String) -> String {
|
||||||
|
let formatter = DateFormatter()
|
||||||
|
formatter.dateFormat = format
|
||||||
|
return formatter.string(from: self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Item where M == ArticleMetadata {
|
||||||
|
var summary: String {
|
||||||
|
if let summary = metadata.summary {
|
||||||
|
return summary
|
||||||
|
}
|
||||||
|
return String(body.withoutHtmlTags.truncate())
|
||||||
|
}
|
||||||
|
|
||||||
|
var imagePath: String {
|
||||||
|
let image = metadata.image ?? "\(filenameWithoutExtension).png"
|
||||||
|
|
||||||
|
return SiteMetadata.url
|
||||||
|
.appendingPathComponent("/articles/images/\(image)")
|
||||||
|
.absoluteString
|
||||||
|
}
|
||||||
|
}
|
||||||
30
Sources/Mhoush/String+Extensions.swift
Normal file
30
Sources/Mhoush/String+Extensions.swift
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension String {
|
||||||
|
var numberOfWords: Int {
|
||||||
|
let characterSet = CharacterSet.whitespacesAndNewlines.union(.punctuationCharacters)
|
||||||
|
let components = self.components(separatedBy: characterSet)
|
||||||
|
return components.filter { !$0.isEmpty }.count
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a sloppy implementation but sadly `NSAttributedString(data:options:documentAttributes:)`
|
||||||
|
// is not available in CoreFoundation, and as such can't run on Linux (blocking CI builds).
|
||||||
|
var withoutHtmlTags: String {
|
||||||
|
return replacingOccurrences(of: "(?m)<pre><span></span><code>[\\s\\S]+?</code></pre>", with: "", options: .regularExpression, range: nil)
|
||||||
|
.replacingOccurrences(of: "<[^>]+>", with: "", options: .regularExpression, range: nil)
|
||||||
|
.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See https://jinja2docs.readthedocs.io/en/stable/templates.html#truncate
|
||||||
|
func truncate(length: Int = 255, killWords: Bool = false, end: String = "...", leeway: Int = 5) -> String {
|
||||||
|
if count <= length + leeway {
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
if killWords {
|
||||||
|
return prefix(length - end.count) + end
|
||||||
|
}
|
||||||
|
|
||||||
|
return prefix(length - end.count).split(separator: " ").dropLast().joined(separator: " ") + end
|
||||||
|
}
|
||||||
|
}
|
||||||
117
Sources/Mhoush/run.swift
Normal file
117
Sources/Mhoush/run.swift
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
import Foundation
|
||||||
|
import PathKit
|
||||||
|
@preconcurrency import Saga
|
||||||
|
import SagaParsleyMarkdownReader
|
||||||
|
import SagaSwimRenderer
|
||||||
|
|
||||||
|
enum SiteMetadata {
|
||||||
|
#if DEBUG
|
||||||
|
static let url = URL(string: "http://localhost:3000")!
|
||||||
|
#else
|
||||||
|
static let url = URL(string: "https://mhoush.com")!
|
||||||
|
#endif
|
||||||
|
static let name = "mhoush"
|
||||||
|
static let author = "Michael Housh"
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ArticleMetadata: Metadata {
|
||||||
|
let tags: [String]
|
||||||
|
var summary: String?
|
||||||
|
let `public`: Bool?
|
||||||
|
let image: String?
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AppMetadata: Metadata {
|
||||||
|
let url: URL?
|
||||||
|
let images: [String]?
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PageMetadata: Metadata {
|
||||||
|
let section: String?
|
||||||
|
}
|
||||||
|
|
||||||
|
// An easy way to only get public articles, since ArticleMetadata.public is optional
|
||||||
|
extension Item where M == ArticleMetadata {
|
||||||
|
var `public`: Bool {
|
||||||
|
return metadata.public ?? true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func permalink(item: Item<ArticleMetadata>) {
|
||||||
|
// Insert the publication year into the permalink.
|
||||||
|
// If the `relativeDestination` was "articles/looking-for-django-cms/index.html", then it becomes "articles/2009/looking-for-django-cms/index.html"
|
||||||
|
var components = item.relativeDestination.components
|
||||||
|
components.insert("\(Calendar.current.component(.year, from: item.date))", at: 1)
|
||||||
|
item.relativeDestination = Path(components: components)
|
||||||
|
}
|
||||||
|
|
||||||
|
@main
|
||||||
|
struct Run {
|
||||||
|
static func main() async throws {
|
||||||
|
try await Saga(input: "content", output: "deploy")
|
||||||
|
// All markdown files within the "articles" subfolder will be parsed to html,
|
||||||
|
// using ArticleMetadata as the Item's metadata type.
|
||||||
|
// Furthermore we are only interested in public articles.
|
||||||
|
.register(
|
||||||
|
folder: "articles",
|
||||||
|
metadata: ArticleMetadata.self,
|
||||||
|
readers: [.parsleyMarkdownReader],
|
||||||
|
itemProcessor: sequence(publicationDateInFilename, permalink),
|
||||||
|
filter: \.public,
|
||||||
|
writers: [
|
||||||
|
.itemWriter(swim(renderArticle)),
|
||||||
|
.listWriter(swim(renderArticles)),
|
||||||
|
.tagWriter(swim(renderTag), tags: \.metadata.tags),
|
||||||
|
.yearWriter(swim(renderYear)),
|
||||||
|
|
||||||
|
// Atom feed for all articles, and a feed per tag
|
||||||
|
.listWriter(
|
||||||
|
atomFeed(
|
||||||
|
title: SiteMetadata.name,
|
||||||
|
author: SiteMetadata.author,
|
||||||
|
baseURL: SiteMetadata.url,
|
||||||
|
summary: \.metadata.summary
|
||||||
|
),
|
||||||
|
output: "feed.xml"
|
||||||
|
),
|
||||||
|
.tagWriter(
|
||||||
|
atomFeed(
|
||||||
|
title: SiteMetadata.name,
|
||||||
|
author: SiteMetadata.author, baseURL: SiteMetadata.url, summary: \.metadata.summary
|
||||||
|
),
|
||||||
|
output: "tag/[key]/feed.xml",
|
||||||
|
tags: \.metadata.tags
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
// All markdown files within the "apps" subfolder will be parsed to html,
|
||||||
|
// using AppMetadata as the Item's metadata type.
|
||||||
|
// .register(
|
||||||
|
// folder: "apps",
|
||||||
|
// metadata: AppMetadata.self,
|
||||||
|
// readers: [.parsleyMarkdownReader],
|
||||||
|
// writers: [.listWriter(swim(renderApps))]
|
||||||
|
// )
|
||||||
|
//
|
||||||
|
// .register(
|
||||||
|
// folder: "photos",
|
||||||
|
// readers: [.parsleyMarkdownReader],
|
||||||
|
// writers: [.itemWriter(swim(renderPhotos))]
|
||||||
|
// )
|
||||||
|
|
||||||
|
// All the remaining markdown files will be parsed to html,
|
||||||
|
// using the default EmptyMetadata as the Item's metadata type.
|
||||||
|
.register(
|
||||||
|
metadata: PageMetadata.self,
|
||||||
|
readers: [.parsleyMarkdownReader],
|
||||||
|
writers: [.itemWriter(swim(renderPage))]
|
||||||
|
)
|
||||||
|
|
||||||
|
// Run the steps we registered above
|
||||||
|
.run()
|
||||||
|
// All the remaining files that were not parsed to markdown, so for example images, raw html files and css,
|
||||||
|
// are copied as-is to the output folder.
|
||||||
|
.staticFiles()
|
||||||
|
}
|
||||||
|
}
|
||||||
104
Sources/Mhoush/templates/BaseLayout.swift
Normal file
104
Sources/Mhoush/templates/BaseLayout.swift
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
import Foundation
|
||||||
|
import HTML
|
||||||
|
|
||||||
|
enum Section: String {
|
||||||
|
case home
|
||||||
|
case articles
|
||||||
|
case about
|
||||||
|
case notFound
|
||||||
|
}
|
||||||
|
|
||||||
|
func baseLayout(
|
||||||
|
canocicalURL: String,
|
||||||
|
section: Section,
|
||||||
|
title pageTitle: String,
|
||||||
|
rssLink: String = "",
|
||||||
|
extraHeader: NodeConvertible = Node.fragment([]),
|
||||||
|
@NodeBuilder children: () -> NodeConvertible
|
||||||
|
) -> Node {
|
||||||
|
return [
|
||||||
|
.documentType("html"),
|
||||||
|
html(lang: "en-US") {
|
||||||
|
generateHeader(pageTitle, extraHeader)
|
||||||
|
body(class: "bg-page text-white pb-5 font-avenir \(section.rawValue)") {
|
||||||
|
header(class: "bg-nav text-gray py-4 text-base/6 lg:fixed w-full lg:h-[62px]") {
|
||||||
|
nav(class: "container flex gap-x-5 lg:gap-x-y items-center") {
|
||||||
|
ul(class: "flex flex-wrap gap-x-2 lg:gap-x-5") {
|
||||||
|
li {
|
||||||
|
a(class: section == .home ? "active" : "", href: "/") { "Home" }
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
a(class: section == .articles ? "active" : "", href: "/articles/") { "Articles" }
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
a(class: section == .about ? "active" : "", href: "/about/") { "About" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
div(class: "container pt-12 lg:pt-28") {
|
||||||
|
children()
|
||||||
|
}
|
||||||
|
|
||||||
|
footer(rssLink)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
private func footer(_ rssLink: String) -> Node {
|
||||||
|
div(class: "site-footer container text-gray gray-links border-t border-light text-center pt-6 mt-8 text-sm") {
|
||||||
|
p {
|
||||||
|
"Copyright © Michael Housh 2023-\(Date().description.prefix(4))."
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
"Built in Swift using"
|
||||||
|
a(href: "https://github.com/loopwerk/Saga", rel: "nofollow", target: "_blank") { "Saga" }
|
||||||
|
"("
|
||||||
|
%a(href: "https://github.com/m-housh/mhoush.com", rel: "nofollow", target: "_blank") { "source" }
|
||||||
|
%")."
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
a(
|
||||||
|
href: "\(SiteMetadata.url.absoluteString)/articles/\(rssLink)feed.xml",
|
||||||
|
rel: "nofollow",
|
||||||
|
target: "_blank"
|
||||||
|
) { "RSS" }
|
||||||
|
" | "
|
||||||
|
a(href: "https://github.com/m-housh", rel: "nofollow", target: "_blank") { "Github" }
|
||||||
|
" | "
|
||||||
|
a(
|
||||||
|
href: "https://www.youtube.com/channel/UCb58SeURd5bObfTiL0KoliA",
|
||||||
|
rel: "nofollow",
|
||||||
|
target: "_blank"
|
||||||
|
) { "Youtube" }
|
||||||
|
" | "
|
||||||
|
a(href: "https://www.facebook.com/michael.housh", rel: "nofollow", target: "_blank") { "Facebook" }
|
||||||
|
" | "
|
||||||
|
a(href: "mailto:michael@mhoush.com", rel: "nofollow") { "Email" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func generateHeader(_ pageTitle: String, _ extraHeader: NodeConvertible) -> Node {
|
||||||
|
head {
|
||||||
|
meta(charset: "utf-8")
|
||||||
|
meta(content: "#0e1112", name: "theme-color", customAttributes: ["media": "(prefers-color-scheme: dark)"])
|
||||||
|
meta(content: "#566B78", name: "theme-color", customAttributes: ["media": "(prefers-color-scheme: light)"])
|
||||||
|
meta(content: "Michael Housh", name: "author")
|
||||||
|
meta(content: "Mhoush", name: "apple-mobile-web-app-title")
|
||||||
|
meta(content: "initial-scale=1.0, width=device-width", name: "viewport")
|
||||||
|
meta(content: "telephone=no", name: "format-detection")
|
||||||
|
meta(content: "True", name: "HandheldFriendly")
|
||||||
|
meta(content: "320", name: "MobileOptimized")
|
||||||
|
meta(content: "Mhoush", name: "og:site_name")
|
||||||
|
meta(content: "hvac, developer, swift, home-performance, design", name: "keywords")
|
||||||
|
title { SiteMetadata.name + ": \(pageTitle)" }
|
||||||
|
link(href: "/static/favicon.ico", rel: "shortcut icon")
|
||||||
|
link(href: "/static/output.css", rel: "stylesheet")
|
||||||
|
link(href: "/static/style.css", rel: "stylesheet")
|
||||||
|
link(href: "/articles/feed.xml", rel: "alternate", title: SiteMetadata.name, type: "application/rss+xml")
|
||||||
|
extraHeader
|
||||||
|
}
|
||||||
|
}
|
||||||
128
Sources/Mhoush/templates/RenderArticle.swift
Normal file
128
Sources/Mhoush/templates/RenderArticle.swift
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
import Foundation
|
||||||
|
import HTML
|
||||||
|
import Saga
|
||||||
|
|
||||||
|
func tagPrefix(index: Int, totalTags: Int) -> Node {
|
||||||
|
if index > 0 {
|
||||||
|
if index == totalTags - 1 {
|
||||||
|
return " and "
|
||||||
|
} else {
|
||||||
|
return ", "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func renderArticleInfo(_ article: Item<ArticleMetadata>) -> Node {
|
||||||
|
div(class: "text-gray gray-links text-sm") {
|
||||||
|
span(class: "border-r border-gray pr-2 mr-2") {
|
||||||
|
article.date.formatted("MMMM dd, yyyy")
|
||||||
|
}
|
||||||
|
|
||||||
|
%.text("\(article.body.withoutHtmlTags.numberOfWords) words, posted in ")
|
||||||
|
|
||||||
|
article.metadata.tags.sorted().enumerated().map { index, tag in
|
||||||
|
Node.fragment([
|
||||||
|
%tagPrefix(index: index, totalTags: article.metadata.tags.count),
|
||||||
|
%a(href: "/articles/tag/\(tag.slugified)/") { tag }
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ogURL(_ article: Item<ArticleMetadata>) -> String {
|
||||||
|
SiteMetadata.url
|
||||||
|
.appendingPathComponent("/articles/images/\(article.url)")
|
||||||
|
.absoluteString
|
||||||
|
}
|
||||||
|
|
||||||
|
@NodeBuilder
|
||||||
|
func getArticleHeader(_ article: Item<ArticleMetadata>) -> NodeConvertible {
|
||||||
|
link(href: "/static/prism.css", rel: "stylesheet")
|
||||||
|
meta(content: article.summary, name: "description")
|
||||||
|
meta(content: "summary_large_image", name: "twitter:card")
|
||||||
|
meta(content: article.imagePath, name: "twitter:image")
|
||||||
|
meta(content: article.title, name: "twitter:image:alt")
|
||||||
|
meta(content: ogURL(article), name: "og:url")
|
||||||
|
meta(content: article.title, name: "og:title")
|
||||||
|
meta(content: article.summary, name: "og:description")
|
||||||
|
meta(content: article.imagePath, name: "og:image")
|
||||||
|
meta(content: "1014", name: "og:image:width")
|
||||||
|
meta(content: "530", name: "og:image:height")
|
||||||
|
script(crossorigin: "anonymous", src: "https://kit.fontawesome.com/f209982030.js")
|
||||||
|
}
|
||||||
|
|
||||||
|
func renderArticle(context: ItemRenderingContext<ArticleMetadata>) -> Node {
|
||||||
|
let extraHeader = getArticleHeader(context.item)
|
||||||
|
|
||||||
|
let allArticles = context.allItems.compactMap { $0 as? Item<ArticleMetadata> }
|
||||||
|
let otherArticles = allArticles.filter { $0.url != context.item.url }.prefix(2)
|
||||||
|
|
||||||
|
return baseLayout(
|
||||||
|
canocicalURL: context.item.url,
|
||||||
|
section: .articles,
|
||||||
|
title: context.item.title,
|
||||||
|
extraHeader: extraHeader
|
||||||
|
) {
|
||||||
|
article(class: "prose") {
|
||||||
|
h1 { context.item.title }
|
||||||
|
div(class: "-mt-6") {
|
||||||
|
renderArticleInfo(context.item)
|
||||||
|
}
|
||||||
|
img(alt: "banner", src: context.item.imagePath)
|
||||||
|
Node.raw(context.item.body)
|
||||||
|
}
|
||||||
|
|
||||||
|
div(class: "border-t border-light mt-8 pt-8") {
|
||||||
|
h2(class: "text-4xl font-extrabold mb-8") { "Written by" }
|
||||||
|
div(class: "flex flex-col lg:flex-row gap-8") {
|
||||||
|
div(class: "flex-[0_0_120px]") {
|
||||||
|
img(class: "w-[120px] h-[120px] rounded-full", src: "/static/images/avatar.png")
|
||||||
|
}
|
||||||
|
|
||||||
|
div(class: "prose") {
|
||||||
|
h3(class: "!m-0") { SiteMetadata.author }
|
||||||
|
p(class: "text-gray") {
|
||||||
|
"""
|
||||||
|
HVAC business owner with over 27 years of experience. Writes articles about HVAC,
|
||||||
|
Programming, Home-Performance, and Building Science
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
div(class: "mt-16") {
|
||||||
|
h2(class: "text-4xl font-extrabold mb-8") { "More articles" }
|
||||||
|
|
||||||
|
div(class: "grid lg:grid-cols-2 gap-10") {
|
||||||
|
otherArticles.map { renderArticleForGrid(article: $0) }
|
||||||
|
}
|
||||||
|
|
||||||
|
p(class: "prose mt-8") {
|
||||||
|
a(href: "/articles/") { "› See all articles" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// div(class: "border-t border-light mt-8 pt-8") {
|
||||||
|
// Node.raw("""
|
||||||
|
// <script src="https://giscus.app/client.js"
|
||||||
|
// data-repo="loopwerk/loopwerk.io"
|
||||||
|
// data-repo-id="MDEwOlJlcG9zaXRvcnk0Nzg0NTA3MA=="
|
||||||
|
// data-category="Article discussions"
|
||||||
|
// data-category-id="DIC_kwDOAtoOzs4Ciykw"
|
||||||
|
// data-mapping="pathname"
|
||||||
|
// data-strict="1"
|
||||||
|
// data-reactions-enabled="1"
|
||||||
|
// data-emit-metadata="0"
|
||||||
|
// data-input-position="bottom"
|
||||||
|
// data-theme="preferred_color_scheme"
|
||||||
|
// data-lang="en"
|
||||||
|
// data-loading="lazy"
|
||||||
|
// crossorigin="anonymous"
|
||||||
|
// async>
|
||||||
|
// </script>
|
||||||
|
// """)
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
83
Sources/Mhoush/templates/RenderArticles.swift
Normal file
83
Sources/Mhoush/templates/RenderArticles.swift
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
import Foundation
|
||||||
|
import HTML
|
||||||
|
import Saga
|
||||||
|
|
||||||
|
func uniqueTagsWithCount(_ articles: [Item<ArticleMetadata>]) -> [(String, Int)] {
|
||||||
|
let tags = articles.flatMap { $0.metadata.tags }
|
||||||
|
let tagsWithCounts = tags.reduce(into: [:]) { $0[$1, default: 0] += 1 }
|
||||||
|
return tagsWithCounts.sorted { $0.1 > $1.1 }
|
||||||
|
}
|
||||||
|
|
||||||
|
func renderArticleForGrid(article: Item<ArticleMetadata>) -> Node {
|
||||||
|
section {
|
||||||
|
h2(class: "text-2xl font-bold mb-2") {
|
||||||
|
a(class: "[&:hover]:border-b border-orange", href: article.url) { article.title }
|
||||||
|
}
|
||||||
|
div(class: "text-gray gray-links text-sm mb-4") {
|
||||||
|
span(class: "border-r border-gray pr-2 mr-2") {
|
||||||
|
article.date.formatted("MMMM dd, YYYY")
|
||||||
|
}
|
||||||
|
|
||||||
|
article.metadata.tags.sorted().enumerated().map { index, tag in
|
||||||
|
Node.fragment([
|
||||||
|
%tagPrefix(index: index, totalTags: article.metadata.tags.count),
|
||||||
|
%a(href: "/articles/tag/\(tag.slugified)/") { tag }
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
a(href: article.url) {
|
||||||
|
div {
|
||||||
|
img(alt: "banner", src: article.imagePath)
|
||||||
|
article.summary
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func renderArticles(context: ItemsRenderingContext<ArticleMetadata>) -> Node {
|
||||||
|
let dateFormatter = DateFormatter()
|
||||||
|
dateFormatter.dateFormat = "yyyy"
|
||||||
|
|
||||||
|
let articlesPerYear = Dictionary(grouping: context.items, by: { dateFormatter.string(from: $0.date) })
|
||||||
|
let sortedByYearDescending = articlesPerYear.sorted { $0.key > $1.key }
|
||||||
|
|
||||||
|
return baseLayout(canocicalURL: "/articles/", section: .articles, title: "Articles", rssLink: "", extraHeader: "") {
|
||||||
|
sortedByYearDescending.map { year, articles in
|
||||||
|
div {
|
||||||
|
h1(class: "text-4xl font-extrabold mb-12") { year }
|
||||||
|
|
||||||
|
div(class: "grid gap-10 mb-16") {
|
||||||
|
articles.map { renderArticleForGrid(article: $0) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func _renderArticles(_ articles: [Item<ArticleMetadata>], canocicalURL: String, title pageTitle: String, rssLink: String = "", extraHeader: NodeConvertible = Node.fragment([])) -> Node {
|
||||||
|
return baseLayout(canocicalURL: canocicalURL, section: .articles, title: pageTitle, rssLink: rssLink, extraHeader: extraHeader) {
|
||||||
|
articles.map { article in
|
||||||
|
section(class: "mb-10") {
|
||||||
|
h1(class: "text-2xl font-bold mb-2") {
|
||||||
|
a(class: "[&:hover]:border-b border-orange", href: article.url) { article.title }
|
||||||
|
}
|
||||||
|
renderArticleInfo(article)
|
||||||
|
p(class: "mt-4") {
|
||||||
|
a(href: article.url) { article.summary }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func renderTag<T>(context: PartitionedRenderingContext<T, ArticleMetadata>) -> Node {
|
||||||
|
let extraHeader = link(href: "/articles/tag/\(context.key.slugified)/feed.xml", rel: "alternate", title: "\(SiteMetadata.name): articles with tag \(context.key)", type: "application/rss+xml")
|
||||||
|
|
||||||
|
return _renderArticles(context.items, canocicalURL: "/articles/tag/\(context.key.slugified)/", title: "Articles in \(context.key)", rssLink: "tag/\(context.key.slugified)/", extraHeader: extraHeader)
|
||||||
|
}
|
||||||
|
|
||||||
|
func renderYear<T>(context: PartitionedRenderingContext<T, ArticleMetadata>) -> Node {
|
||||||
|
_renderArticles(context.items, canocicalURL: "/articles/\(context.key)/", title: "Articles in \(context.key)")
|
||||||
|
}
|
||||||
57
Sources/Mhoush/templates/RenderPage.swift
Normal file
57
Sources/Mhoush/templates/RenderPage.swift
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import HTML
|
||||||
|
import Saga
|
||||||
|
|
||||||
|
func renderPage(context: ItemRenderingContext<PageMetadata>) -> Node {
|
||||||
|
let section = Section(rawValue: context.item.metadata.section ?? "")
|
||||||
|
assert(section != nil)
|
||||||
|
|
||||||
|
return baseLayout(canocicalURL: context.item.url, section: section!, title: context.item.title) {
|
||||||
|
switch section {
|
||||||
|
case .home:
|
||||||
|
renderHome(body: context.item.body)
|
||||||
|
case .notFound:
|
||||||
|
let articles = context.allItems
|
||||||
|
.compactMap { $0 as? Item<ArticleMetadata> }
|
||||||
|
.prefix(10)
|
||||||
|
render404(body: context.item.body, articles: Array(articles))
|
||||||
|
default:
|
||||||
|
renderNonHome(body: context.item.body)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func renderHome(body: String) -> Node {
|
||||||
|
div {
|
||||||
|
img(alt: "Avatar", class: "my-24 w-[315px] h-200px mx-auto", src: "/static/images/avatar.png")
|
||||||
|
|
||||||
|
div(class: "my-24 uppercase font-avenir text-[40px] leading-[1.25] font-thin text-center [&>h1>strong]:font-bold") {
|
||||||
|
Node.raw(body)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func renderNonHome(body: String) -> Node {
|
||||||
|
article {
|
||||||
|
div(class: "prose") {
|
||||||
|
Node.raw(body)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func render404(body: String, articles: [Item<ArticleMetadata>]) -> Node {
|
||||||
|
article(class: "prose") {
|
||||||
|
Node.raw(body)
|
||||||
|
|
||||||
|
ul {
|
||||||
|
articles.map { article in
|
||||||
|
li {
|
||||||
|
a(href: article.url) { article.title }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
div {
|
||||||
|
a(href: "/articles/") { "› See all articles" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
33
content/about.md
Normal file
33
content/about.md
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
---
|
||||||
|
section: about
|
||||||
|
---
|
||||||
|
|
||||||
|
# About - Michael Housh
|
||||||
|
|
||||||
|
Michael is a third generation HVAC technician / owner located in Monroe, Ohio. He is the president
|
||||||
|
of [Housh - The Home Energy Experts](https://www.houshhomeenergy.com), where they focus on high
|
||||||
|
performance HVAC systems, indoor air quality, and home performance upgrades.
|
||||||
|
|
||||||
|
Michael is passionate about helping the HVAC trade grow in skill and integrity. He is also
|
||||||
|
passionate about programming solutions (primarily in Swift) for the HVAC industry to automate his
|
||||||
|
business and help others automate theirs.
|
||||||
|
|
||||||
|
Michael likes to think deeply about where the industry has been and where it is going. Coming up
|
||||||
|
with innovative solutions to common problems that are faced, with a primary focus on residential
|
||||||
|
HVAC and Home Performance.
|
||||||
|
|
||||||
|
**Michael’s Favorite Quote:**
|
||||||
|
|
||||||
|
Integrity is doing the right thing, even when no one is watching!
|
||||||
|
|
||||||
|
~ C.S. Lewis
|
||||||
|
|
||||||
|
Michael is a proud contributor to many online groups / podcasts:
|
||||||
|
|
||||||
|
HVAC School
|
||||||
|
The HVAC Grapevine
|
||||||
|
HVAC Overtime
|
||||||
|
|
||||||
|
Michael’s PGP Fingerprint
|
||||||
|
|
||||||
|
B86F487BF0A715D016DB140A37F1B52C60D8C24B
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
---
|
||||||
|
tags: formulas, HVAC, tech-tip
|
||||||
|
---
|
||||||
|
# Calculate SEER Degradation by Age
|
||||||
|
|
||||||
|
This is a quick tech-tip to learn how to calculate the degradation of SEER based
|
||||||
|
on age.
|
||||||
|
|
||||||
|
The degradation of SEER is due to fouling of the evaporator coil with dirt and
|
||||||
|
refrigerant charge losses. It should be noted that this is not true for all
|
||||||
|
applications, but is used as an estimation based on research done by the `DOE`
|
||||||
|
of the average degradation based on systems tested.
|
||||||
|
|
||||||
|
## Formula
|
||||||
|
|
||||||
|
This is the formula used to calculate the SEER based on age of the evaporator
|
||||||
|
coil / air handler.
|
||||||
|
|
||||||
|
$$ SEER_d = SEER_n \times (1 - M)^{age} $$
|
||||||
|
|
||||||
|
| Where | |
|
||||||
|
| -------- | ------------------------------------------ | --- |
|
||||||
|
| $SEER_d$ | Degradated SEER rating |
|
||||||
|
| $SEER_n$ | Nominal SEER rating when equipment was new | |
|
||||||
|
| M | Maintenance factor, 0.01-0.03 |
|
||||||
|
| age | The age of the equipment, in years |
|
||||||
|
|
||||||
|
The maintenance factor of 0.01 is for expertly maintained equipment and 0.03 is
|
||||||
|
for unmaintained. The maintenance factor in essence is based on 1%-3%
|
||||||
|
degradation per year, however there are some
|
||||||
|
[studies](https://publications.energyresearch.ucf.edu/wp-content/uploads/2018/09/FSEC-PF-474-18.pdf)
|
||||||
|
that show that this can actually be as high as 5% or above depending on climate.
|
||||||
|
We could use up to 0.05 as the maintenance factor, just to see what the "range"
|
||||||
|
of degradation would be.
|
||||||
|
|
||||||
|
Interestingly, the study linked also shows that the degradation is higher the
|
||||||
|
higher the tonnage of the equipment. It also shows that the degradation is lower
|
||||||
|
per year the higher the nominal SEER rating of the system (which is corelated to
|
||||||
|
using TXV's and lower airflow rates because of the equipment having multiple
|
||||||
|
stages).
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
Let's consider that we have a 13 SEER piece of equipment that was matched when
|
||||||
|
installed and the system is 15 years old.
|
||||||
|
|
||||||
|
Plugging those numbers into our formula.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### Lowest Range (1% degradation / year)
|
||||||
|
|
||||||
|
$$ SEER_d = 13 \times (1 - 0.01)^{15} = 11.2 $$
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### Highest Rage (5% degradation / year)
|
||||||
|
|
||||||
|
$$ SEER_d = 13 \times (1 - 0.05)^{15} = 6 $$
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
An expertly maintained system may not have degraded that much, with an 11.2 SEER
|
||||||
|
vs. a poorly maintained / dirty system that also suffers from refrigerant charge
|
||||||
|
losses can be as low as 6 SEER.
|
||||||
|
|
||||||
|
Thanks for learning how to estimate SEER degradation based on equipment age!
|
||||||
142
content/articles/2023-10-18-the-struggle.md
Normal file
142
content/articles/2023-10-18-the-struggle.md
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
---
|
||||||
|
public: true
|
||||||
|
date: 2023-10-18
|
||||||
|
tags: article, general
|
||||||
|
banner: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# The Struggle
|
||||||
|
|
||||||
|
This is a get stuff of my chest article. Probably going to be a mixture of ranting and whining. If
|
||||||
|
that is not your cup of tea then feel free to skip this article.
|
||||||
|
|
||||||
|
## The struggle
|
||||||
|
|
||||||
|
It has been one of those "when it rains, it pours" type of weeks. As write this, I feel like a baby
|
||||||
|
/ complainer, which is not my intention, but here it goes.
|
||||||
|
|
||||||
|
My aunt had a stroke and is likely not going to make it through the week. My aunt has always lived
|
||||||
|
in Florida during my life / memory, but has always come to visit. She is my mom's oldest sister (9
|
||||||
|
years apart), so she helped raise my mother growing up. They've always had a close relationship and
|
||||||
|
are like two peas in a pod. They would always visit us, especially while my grand-parents were still
|
||||||
|
alive. She is currently not really awake or expected to make it. She does not eat / drink and
|
||||||
|
they've basically just been making her comfortable.
|
||||||
|
|
||||||
|
One of my employees broke his neck over the weekend. I don't have a ton of details on this subject,
|
||||||
|
but he had surgery to fuse some discs back together and should eventually be ok, however it will be
|
||||||
|
a long recovery time.
|
||||||
|
|
||||||
|
A few weeks ago, I commited one of the deadly sins of running a blower door test without checking /
|
||||||
|
asking about the fireplaces, which caused lord knows how much damage from the soot that was spread
|
||||||
|
throughout the living room(s).
|
||||||
|
|
||||||
|
An online friend lost her mother.
|
||||||
|
|
||||||
|
All of these things have just got me emotional.
|
||||||
|
|
||||||
|
## My secrets
|
||||||
|
|
||||||
|
I am an emotional person, sometimes to my detriment. I'm prone to fits of anger and depression. I
|
||||||
|
spent many years masking things through alcohol abuse and many other idiotic tendencies. I still
|
||||||
|
drink on occasion, but not as I once did.
|
||||||
|
|
||||||
|
I often put my faith in folks, even if I haven't met them in person, this can often lead to being
|
||||||
|
let down. I guess I struggle sometimes with the reality of online relationships. I think that people
|
||||||
|
are genuine, because I'm that way (how I act online is the same as I act in person for the most
|
||||||
|
part). I will happily show / share the good and the bad, in hopes that someone may learn. This is
|
||||||
|
not at all something to be ashamed of, or anything that I'd like to change, however it does on
|
||||||
|
occasion lead me into turmoil when I find out some true identity / personality of someone.
|
||||||
|
|
||||||
|
I hold grudges, like forever grudges. It is very hard for me to get over somethings, even if I want
|
||||||
|
to. I can sometimes put things out of my mind, but when I'm spinning, they will resurface. I want to
|
||||||
|
forgive people, but it is just not the way it works for me often times. It takes a lot to get me
|
||||||
|
beyond my breaking point, but once someone has gotten me there, there is likely no turning back for
|
||||||
|
that person. Luckily, I can count on one hand the number of folks that I've had to cut out of my
|
||||||
|
life for these reasons. I'd love to say that I'm a bigger / better person, that I forgive them, but
|
||||||
|
truthfully I do not.
|
||||||
|
|
||||||
|
My emotions sometimes make me say things publicly that I should keep to myself. I don't have a lot
|
||||||
|
of regret around these things, because I generally mean what I say, and also feel we are entitled to
|
||||||
|
opinions as well as entitled to change those opinions as often as we see fit. Although I don't
|
||||||
|
regret them per-se, it does make me wonder what type of impression it leaves (something for future
|
||||||
|
pondering, perhaps).
|
||||||
|
|
||||||
|
I'm one of those that says "I don't care what they think about me", when I really do care what
|
||||||
|
people think about me. This often leads to fear and anxiety, especially in social settings. I'm not
|
||||||
|
the greatest at conversation, I'm better at writing or some interaction that gives me a bit of time
|
||||||
|
to think before responding. Therefore, I'm quick to make a joke or something rather than having
|
||||||
|
thoughtful / genuine responses.
|
||||||
|
|
||||||
|
## Community
|
||||||
|
|
||||||
|
All of these things have just got me thinking about community. Community is an aspect that seems
|
||||||
|
distant nowadays, even though we have more opportunity than ever. We call ourselves part of
|
||||||
|
communities, especially online, but I'm not convinced that it is really community (or at least not
|
||||||
|
most of the time, not saying it can't be / in absolute terms).
|
||||||
|
|
||||||
|
I have met a lot of folks online that I consider true friends. Friends that I would do anything for
|
||||||
|
and feel they would do anything for me, just like my real life friends who have stuck with me for
|
||||||
|
many years. These are people that challenge me and how I think on a regular basis. They do their
|
||||||
|
best to lift me up when I'm down.
|
||||||
|
|
||||||
|
It's easy to hide when so much of our interactions are not really in person, to feel like the
|
||||||
|
relationships we do have are not genuine, but that's awfully cynical. I prefer to give people the
|
||||||
|
benefit / trust they deserve until, at least until they don't then see my part about holding grudges
|
||||||
|
;)
|
||||||
|
|
||||||
|
Do you ever feel the same? Instead of being cynical and down, today, I'm trying to be positive. I'm
|
||||||
|
trying to share a little bit of what I feel community should be. Although, I've never met HVAChicks
|
||||||
|
Jennifer in real life, I read today about her mom and decided to take an hour or so to put together
|
||||||
|
a website for the [HVAChicks Community](https://hvachicks.com), hoping it would bring a moment of
|
||||||
|
happiness to her day. While I've deployed several websites in the past, this one for some reason was
|
||||||
|
a total PITA, but I got through it. I could feel how grateful she was when I shared it with her (and
|
||||||
|
it's basic AF), but that truly made me feel useful / great after being down in the dumps for a bit.
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
I've probably rambled enough and am losing direction here, so I will end with a few things.
|
||||||
|
|
||||||
|
1. Build the community around you that you want / deserve.
|
||||||
|
1. Don't be so quick to pass judgment.
|
||||||
|
1. Spend time with your loved ones, while you can.
|
||||||
|
1. Tell someone you love them.
|
||||||
|
|
||||||
|
Finally, I'd like to shout out some people that I'm grateful for. This is non-exhaustive list, if I
|
||||||
|
left you off, I'm sorry and please do not take it personally.
|
||||||
|
|
||||||
|
1. Bryan Orr
|
||||||
|
- Bryan has cultivated an awesome group / community that I'm proud to be a part of. His time and
|
||||||
|
commitment to the HVAC industry is something that I hope he himself is proud of. Without Bryan,
|
||||||
|
mostly all the following names would not even be in my vocabulary.
|
||||||
|
1. Ty Branaman (forget exactly how to spell his last name).
|
||||||
|
- Ty has such a great personality during his videos / training and I'm sure it's a struggle to be
|
||||||
|
positive all the time, however it brings me hope and joy everytime!
|
||||||
|
1. Dustin (mother f'n) Cole
|
||||||
|
- Dustin is like a brother that I never had, he's a true master of his craft and I know that I
|
||||||
|
can rely on him anytime I need it!
|
||||||
|
1. Genry Garcia
|
||||||
|
- The cuban crusader who has taught me so much about home performance, and especially ZPD (baby,
|
||||||
|
baby)!
|
||||||
|
1. Chris Hughes
|
||||||
|
- It's hard to put into words here, but I know that Chris is there to talk when I need it and
|
||||||
|
he's a great motivator because of his action items :)
|
||||||
|
1. Eric Kaiser
|
||||||
|
- I think genuine when I think of Eric, I hear his voice in my head when I write reports because
|
||||||
|
of guidance he has given in the past. He truly wants to help teach people.
|
||||||
|
1. Michael Cianfracco (??)
|
||||||
|
- Man does he make me laugh and we share a passion for the 4-Roses.
|
||||||
|
1. HVAChicks Jennifer (I'll butcher her last name from memory)
|
||||||
|
- Jennifer is inspiring with her goals and everything she does to help anyone in the industry. I
|
||||||
|
can't wait to meet her in person one day soon!
|
||||||
|
1. HVAC Overtime Crew
|
||||||
|
- I'm lumping these guys together because I truly enjoy when I'm able to make their live stream
|
||||||
|
on Friday's. And I interact with A-Team a lot and really appreciate him / them!
|
||||||
|
1. Alicia Hollon
|
||||||
|
- Alicia is so awesome to me, I mean she just made my favorite pancakes and sausage for dinner,
|
||||||
|
love you babe!
|
||||||
|
|
||||||
|
Lastly, I have to shout out to my mom. I know she's going through a rough time with my aunt
|
||||||
|
currently. My mother is the kindest gentlest soul that I've ever met. I look up to all 5' of her!
|
||||||
|
|
||||||
|
At any rate, thanks for sticking it out to the end through my ramblings. Be kind to someone today
|
||||||
|
and tomorrow!
|
||||||
56
content/articles/2023-10-21-you-should-learn-markdown.md
Normal file
56
content/articles/2023-10-21-you-should-learn-markdown.md
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
---
|
||||||
|
tags: HVAC, general, programming
|
||||||
|
---
|
||||||
|
|
||||||
|
# You Should Learn Markdown
|
||||||
|
|
||||||
|
This is a quick article about why you should learn markdown.
|
||||||
|
|
||||||
|
## What is markdown
|
||||||
|
|
||||||
|
Markdown is a "mark-up" language. It allows you to write content in plain text that can be easily
|
||||||
|
converted to other formats, such as **html, pdf, docx**, and many more. All the articles written on
|
||||||
|
this website are written in markdown, here's an image of this article written in markdown.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
The reason you should learn markdown is that it allows you to focus on the content / text of your
|
||||||
|
content with simple concepts for formatting. Markdown is used heavily in documenting software
|
||||||
|
projects, which is how I got introduced to it, however it can scale all the way up to writing
|
||||||
|
research papers or even books.
|
||||||
|
|
||||||
|
I use markdown for probably 80% of all the text documents I need to write, from company documents,
|
||||||
|
web / software documentation, and so on. It allows me to get content out quickly without having to
|
||||||
|
click around with formatting options in a program like **Word** or **Pages**. To be clear, a lot of
|
||||||
|
the reports and things I generate for my **Home Performance Assessments** are written using
|
||||||
|
**Pages** (for now at least) because I have templates that make the documents look more
|
||||||
|
professional, however I am working on solutions to migrate those to be markdown based.
|
||||||
|
|
||||||
|
Markdown is supported in mostly all the **Google** tools, as well as the **Outlook** email client
|
||||||
|
(which is one of my least favorite tools, BTW). It makes it simple to create tables, lists, and many
|
||||||
|
common document related tasks.
|
||||||
|
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
You can learn more about the syntax used for markdown at
|
||||||
|
[markdownguide.org](https://www.markdownguide.org/basic-syntax/).
|
||||||
|
|
||||||
|
### A non-exhaustive list of where you can use Markdown and editors.
|
||||||
|
|
||||||
|
| Platform | Description |
|
||||||
|
| ------------ | --------------------------------------------------------------- |
|
||||||
|
| Google | Most goggle tools support markdown, docs, sheets, etc. |
|
||||||
|
| Outlook | Although I hate outlook email client, it does support markdown. |
|
||||||
|
| Dillinger.io | An online tool for writing / previewing markdown |
|
||||||
|
| MarkText | A multi-platform editor for writing markdown |
|
||||||
|
|
||||||
|
You can use tools such as [pandoc](https://pandoc.org/#) to convert Markdown files to other formats.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
I hope that you take the time to research and see if Markdown is good fit for your document /
|
||||||
|
content creation.
|
||||||
|
|
||||||
|
Thanks for reading until the end!
|
||||||
92
content/articles/2023-10-27-heat-recovery-chiller.md
Normal file
92
content/articles/2023-10-27-heat-recovery-chiller.md
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
---
|
||||||
|
tags: HVAC, hydronics, chiller
|
||||||
|
---
|
||||||
|
|
||||||
|
# Heat Recovery Chiller
|
||||||
|
|
||||||
|
This is an article that I wrote back in 2020, but I don't believe that I published it anywhere, so
|
||||||
|
I'm doing it now. I did discuss this on
|
||||||
|
[this episode of the HVAC School Podcast.](https://hvacrschool.com/podcasts/is-the-future-of-air-conditioning-self-contained-propane-chillers/)
|
||||||
|
|
||||||
|
## Heat Recovery Chillers
|
||||||
|
|
||||||
|
I have always had a love and passion for hydronic systems, perhaps it's because they are not that
|
||||||
|
common in most areas. The designs tend to be elegant and the flexibility is unparalleled by most
|
||||||
|
equipment choices currently available in the U.S. I'm going to try to not get too far into the weeds
|
||||||
|
in this article, but offer an overview of what I feel would be my dream system.
|
||||||
|
|
||||||
|
## The Source
|
||||||
|
|
||||||
|
A heat recovery chiller will do simultaneous heating and cooling, as opposed to a traditional
|
||||||
|
heat-pump or reverse cycle chiller that can only operate in one mode at a time. This system would
|
||||||
|
have a second refrigerant to water heat exchanger and utilize the air-source when we don't need to
|
||||||
|
bank / store heat, or are running in heat only mode. There are several benefits to this style
|
||||||
|
system, the main being that while operating simultaneous heating / cooling mode the COP of the
|
||||||
|
system doubles. For example, the [Multi-Aqua MHRC2](https://multiaqua.com/mhrc2/) shows a COP of
|
||||||
|
about 8, which is approximately equivalent to 30 EER or 34 SEER. This gives us geothermal level
|
||||||
|
performance without the need of a field.
|
||||||
|
|
||||||
|
## Indoor Portion
|
||||||
|
|
||||||
|
The indoor portion of the system, we would utilize buffer tanks as thermal storage for the chiller.
|
||||||
|
The buffer tanks give us several benefits, including longer run times for the chiller, load
|
||||||
|
matching, and the ability to size for larger load (heating or cooling) without some of the problems
|
||||||
|
that occur when over-sizing a traditional system. The buffer tanks also allow sizing more
|
||||||
|
aggressively by having storage during peak load conditions.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
This shows a cooling buffer tank as well as a heating buffer tank. The horizontal pumps are what
|
||||||
|
circulate water through the chiller, while the vertical pumps are what distribute the water to the
|
||||||
|
load / emitters. This configuration allows for water to be used for the loads first and extra
|
||||||
|
capacity to go into the buffer tanks. The buffer tanks also offer hydraulic separation for the pumps
|
||||||
|
(meaning that they won't interfere with each other if / when there are different flow rates).
|
||||||
|
Another advantage of the buffer tanks is that you can connect multiple heating or cooling sources in
|
||||||
|
parallel to the system. This is shown by the extra tees in the hot buffer tank where we could
|
||||||
|
connect something such as solar water collectors, pellet or wood boiler, or a conventional boiler.
|
||||||
|
You'll also notice on the right side of the hot buffer tank, that I am showing a brazed plate heat
|
||||||
|
exchanger that would be used to supply domestic hot water.
|
||||||
|
|
||||||
|
## Distribution System
|
||||||
|
|
||||||
|
This could be a number of things, from radiant panels, in-floor, high-output baseboard radiators,
|
||||||
|
however I'm going to model it as a 4-pipe hydronic air handler.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
The hydronic air handler is able to provide cooling, heating, and re-heat dehumidification, all in
|
||||||
|
one package. With a hydronic system, it would be very easy to load match by controlling the fan
|
||||||
|
speed and utilizing a Delta-T pump or outdoor reset controls. These air handlers are available from
|
||||||
|
several manufacturers and come in different styles from traditional (as shown), small duct high
|
||||||
|
velocity systems, and even ductless styles.
|
||||||
|
|
||||||
|
## Disadvantages
|
||||||
|
|
||||||
|
1. Not highly available in the U.S.
|
||||||
|
1. When the chiller is down nothing works (not much different than traditional)
|
||||||
|
1. Lack of understanding / technicians afraid to work on this style system.
|
||||||
|
1. Potentially higher upfront costs.
|
||||||
|
1. Lack of design or planning could cause unhappy clients (same with traditional)
|
||||||
|
1. Distribution systems need to be designed around low water temperatures (not a drop in replacement
|
||||||
|
for traditional boiler systems)
|
||||||
|
|
||||||
|
## Advantages
|
||||||
|
|
||||||
|
1. Central plant for heating, cooling, and DHW (also a disadvantage)
|
||||||
|
1. Flexible distribution options / methods.
|
||||||
|
1. Self contained refrigerant circuit
|
||||||
|
1. Ability to produce / store thermal energy during off peak electrical hours
|
||||||
|
1. Ability to move BTU's more efficiently through water than air
|
||||||
|
1. Long life for distribution system (50-100+ years)
|
||||||
|
1. Easier transition to natural / flammable refrigerants
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
In conclusion, there are many advantages to this style system, as well as disadvantages. One of the
|
||||||
|
main points is to think of the system in 3 distinct components, the source(s), thermal storage, and
|
||||||
|
distribution. As mentioned, this only one concept, but in reality, there are many ways to accomplish
|
||||||
|
this, which is one of it's advantages. For example, perhaps in certain scenarios it makes sense to
|
||||||
|
dump excess heat into a pool, create ice storage during off peak hours, cascade into another water
|
||||||
|
-> water heat pump for higher temperature distribution, incorporate solar collectors, and so on.
|
||||||
|
|
||||||
|
Thank you for reading all the way to the end!
|
||||||
66
content/articles/2023-10-30-hope.md
Normal file
66
content/articles/2023-10-30-hope.md
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
---
|
||||||
|
tags: general
|
||||||
|
---
|
||||||
|
|
||||||
|
# Hope
|
||||||
|
|
||||||
|
This is a piggy-back article off of
|
||||||
|
[The Struggle](https://mhoush.com/posts/20231018224631-the-struggle/) article that I had recently.
|
||||||
|
|
||||||
|
I was a bit of a "Debbie Downer" in that article, which is okay, I get that way sometimes. In this
|
||||||
|
article I'd like to take a minute to layout some of the things that give me hope, things that I
|
||||||
|
focus on to try and kick myself out of the rut I can get into sometimes.
|
||||||
|
|
||||||
|
I believe it's important to have **hope**, to realize that feeling down is normal / part of being
|
||||||
|
human. It's just as important to have hope. For some it is a harder thing to focus on, it may be
|
||||||
|
easy for us to try and dwell in negative feelings, to some that may feel more comfortable. When
|
||||||
|
we're feeling cynical, it's easy to feed the negativity, although it's rarely helpful.
|
||||||
|
|
||||||
|
## Hope
|
||||||
|
|
||||||
|
One of the things that I try to focus on is that I'm human, it brings me hope to realize that I'm
|
||||||
|
not the only one who feels the way that I do. This was evident by the feedback on my previous
|
||||||
|
article.
|
||||||
|
|
||||||
|
> My problems are very much "first world problems".
|
||||||
|
|
||||||
|
Make no mistake, I'm selfish, but it's the selfishness that makes me feel distant or disconnected.
|
||||||
|
The times that I feel connected are without a doubt the times that I let go of my ego and focus on
|
||||||
|
things outside of myself.
|
||||||
|
|
||||||
|
It's the feeling I get from going to customers home and feeling truly appreciated. There's no push
|
||||||
|
back on price, no one telling me how I should run my business, no "the part only costs $x on
|
||||||
|
amazon", etc.
|
||||||
|
|
||||||
|
The feeling of seeing your child smile. The safety you feel when getting a hug from your mother or
|
||||||
|
father. When you're looking up at the stars and realize how small you actually are.
|
||||||
|
|
||||||
|
When you're out with friends and trick the DJ into playing a Mr. Bungle song and no one else
|
||||||
|
appreciates it, but you. The times when your guard is completely down and you laugh with abandon.
|
||||||
|
|
||||||
|
The smell of your lover's hair when you're holding them close. The joy you receive from sitting with
|
||||||
|
your pets. The songs of nature, insects, birds, etc. The sounds of waves / water in the distance.
|
||||||
|
|
||||||
|
The feeling when you've helped someone learn a new skill, when something finally clicks and makes
|
||||||
|
sense. When a complex topic is understood at a fundamental level. The breakthrough of a problem
|
||||||
|
you've pondered for days / months / years.
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
There are so many things to be grateful for. This does not mean that there will not be hard times,
|
||||||
|
there surely will be. This does not mean that you are wrong for having negative feelings, for
|
||||||
|
feeling depressed or anxious. There are many around you that likely feel similar (they may just not
|
||||||
|
be able to express it in the same way). You never truly know what the person next to you is dealing
|
||||||
|
with. Be compassionate (including showing yourself compassion).
|
||||||
|
|
||||||
|
When you are feeling down, try to do something for someone else. Make your own list of things to be
|
||||||
|
thankful for. Maybe my non-exhaustive list above will give you some ideas. Write those items down
|
||||||
|
regularly so that you can look back on them when you feel out of balance.
|
||||||
|
|
||||||
|
There is plenty of negative energy in this world, be true and genuine and you will receive rewards.
|
||||||
|
When you focus on blessings then the negativity will fade.
|
||||||
|
|
||||||
|
What impact are you going to leave with what little time we have?
|
||||||
|
|
||||||
|
I hope that you enjoyed this short article. Know that you are _NOT_ alone, you are important, and
|
||||||
|
that I appreciate _you!_
|
||||||
66
content/articles/2023-12-12-cancel-this.md
Normal file
66
content/articles/2023-12-12-cancel-this.md
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
---
|
||||||
|
tags: HVAC
|
||||||
|
image: 2023-12-12-cancel-this.gif
|
||||||
|
---
|
||||||
|
|
||||||
|
# Cancel This
|
||||||
|
|
||||||
|
This post is going to be hard to put into words, it's going to seem egotistical at points, but know
|
||||||
|
that my actions / feelings online are the same as they are if you met me in person. The problem with
|
||||||
|
online interactions is tone and other subtleties do not come across, so it's hard to tell when
|
||||||
|
someone is joking or being serious.
|
||||||
|
|
||||||
|
## The Meat
|
||||||
|
|
||||||
|
It has been brought to my attention that someone out there thinks that I'm sexist and should not
|
||||||
|
speak at the HVAC School symposium because of it. They are holding a curse word against me that I
|
||||||
|
said two years ago, in the moment A) it was fitting and B) it was one of those times that my mouth
|
||||||
|
was working faster than my brain (raise your hand if that's ever happened to you).
|
||||||
|
|
||||||
|
I am an open book, I am not afraid of showing failures and strengths. I've never claimed to be
|
||||||
|
perfect (well, actually I have but it's always a joke). I'm not at all condoning what I've said in
|
||||||
|
the past, nor will I repeat it out of context now, but I communicate with people like adults and I
|
||||||
|
look at people as piers. We do not always have to agree with one another, conflict helps us learn
|
||||||
|
where to grow, but we also can not expect people to change to fit our wants / needs, that's just not
|
||||||
|
how it works.
|
||||||
|
|
||||||
|
I do not at all agree with the tactics used by whomever is behind this. I would happily discuss this
|
||||||
|
in private or out in the open. You can find all my contact / social information in the sidebar of
|
||||||
|
this website and I've offered up my cell phone number in private groups that we are all probably a
|
||||||
|
part of.
|
||||||
|
|
||||||
|
## The Potatoes
|
||||||
|
|
||||||
|
I am a father of 3 girls, I have a sister, talk crap about my mom and you'll find out who I am! I
|
||||||
|
love women, I have no problem with women in the trades, I encourage women who are in the trades. I
|
||||||
|
try to help every person that I can, if I can. I have failed more times than you can imagine! I am
|
||||||
|
self taught in about everything I do, so I give of it freely. I have all kinds of work to do to grow
|
||||||
|
into the man that I should be, but at the same time, I am not afraid to be the man that I am today.
|
||||||
|
I will greet you by whatever pronoun you want to be referred as.
|
||||||
|
|
||||||
|
I would love to say that I don't judge people, but I do, just as I'm being judged! I am fine with
|
||||||
|
someone judging me and having opinions about me, I mean that is our right. I will not say that
|
||||||
|
person is wrong, because in their mind they're right. What I will not do is stop being myself. I
|
||||||
|
know for a fact that I've helped more people than this person has gotten "cancelled". I will
|
||||||
|
continue to help people in the trades, homeowners, or people in need. I also will not remain quiet!
|
||||||
|
I will give my opinion like it or not. There are people in my corner that really know me and my
|
||||||
|
intentions.
|
||||||
|
|
||||||
|
## Final Words
|
||||||
|
|
||||||
|
The trades are rough around the edges, just as am I. The trades are a slow turning ship (just look
|
||||||
|
at how many still do not follow proper practices, etc. even with the capabilities and resources
|
||||||
|
available today).
|
||||||
|
|
||||||
|
If you are new / coming into the trades then I hope you are not overly sensitive to foul language
|
||||||
|
and other inappropriate comments. Thick skin is valuable in the trades, but at the same time don't
|
||||||
|
be afraid to speak up if something offends you. Remember we are adults, we can handle disagreements
|
||||||
|
like adults (well, some of us can). Adults can learn from those of any age, they can reflect on
|
||||||
|
their own behavior and make their own decisions.
|
||||||
|
|
||||||
|
I personally think that being offended is not a bad thing, it causes us to reflect / repair our
|
||||||
|
foundational beliefs. I hope that we can stop with this "cancel culture" of today, stop hiding
|
||||||
|
behind a keyboard, and be a diverse community.
|
||||||
|
|
||||||
|
To wrap things up, I just want to reiterate that I am not at all mad at whomever is behind this. To
|
||||||
|
everyone out there who has shown me love and support, I greatly appreciate it.
|
||||||
31
content/articles/2023-12-14-most-important-job.md
Normal file
31
content/articles/2023-12-14-most-important-job.md
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
image: 2023-12-14-most-important-job.gif
|
||||||
|
tags: HVAC, tech-tip
|
||||||
|
---
|
||||||
|
|
||||||
|
# Most Important Job
|
||||||
|
|
||||||
|
This short tech tip is about something one of my good friends in the trade told me a long time ago,
|
||||||
|
that has stuck with me through the years. It is a simple phrase / mindset.
|
||||||
|
|
||||||
|
> "The current job you're on, is the most important job of your day".
|
||||||
|
|
||||||
|
This mindset should be carried from the dispatcher, manager, and technician to make this successful.
|
||||||
|
I'm not gonna lie and say this is always easy, or even always possible, but if you strive to use
|
||||||
|
this mindset then you will gain lifelong customers and satisfaction of not having loose ends hanging
|
||||||
|
out there.
|
||||||
|
|
||||||
|
I do think it's also important to acknowledge that there are times that a technician has exhausted
|
||||||
|
all their options, maybe they just don't have the mental capacity anymore to continue with a problem
|
||||||
|
job, or need a break to come back another day with a fresh set of eyes, etc... This is also an
|
||||||
|
important thing for a technician to realize, and hopefully those type of instances are much more few
|
||||||
|
and far between, but I do want to acknowledge that scenario does also exist.
|
||||||
|
|
||||||
|
If you are a business owner, then this is something to consider instilling in your operations.
|
||||||
|
Empower your technicians and dispatchers to understand when things need to be shuffled around in
|
||||||
|
order to accommodate taking care of the customer at hand. It costs a lot of money to get a
|
||||||
|
technician to job, so minimizing truck rolls to the same job is important from a business
|
||||||
|
standpoint.
|
||||||
|
|
||||||
|
This was just a quick tech tip of something that has been rolling around in my mind lately. I hope
|
||||||
|
you find it helpful and it sticks with you through your career as it has mine.
|
||||||
71
content/articles/2024-02-27-elevating-hvac.md
Normal file
71
content/articles/2024-02-27-elevating-hvac.md
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
---
|
||||||
|
tags: HVAC
|
||||||
|
---
|
||||||
|
|
||||||
|
# Elevating HVAC: A Skilled Trade Beyond Labor
|
||||||
|
|
||||||
|
This is a guest post from my good friend, **Ty Branaman**.
|
||||||
|
|
||||||
|
## Introduction:
|
||||||
|
|
||||||
|
Heating, Ventilation, and Air Conditioning (HVAC) is often mistakenly categorized as a simple labor
|
||||||
|
job, overshadowing the intricate skill set and technical expertise required in this field. Labor
|
||||||
|
jobs are also very important positions needed to keep society running. HVAC, like other skilled
|
||||||
|
trades, demands a high level of knowledge, precision, and adaptability. This article aims to shed
|
||||||
|
light on the misconception surrounding HVAC, emphasizing its status as a skilled trade that plays a
|
||||||
|
pivotal role in creating comfortable and efficient living and working environments.
|
||||||
|
|
||||||
|
## Technical Proficiency:
|
||||||
|
|
||||||
|
One of the defining features that distinguish HVAC as a skilled trade is the level of technical
|
||||||
|
proficiency required. HVAC professionals must have a deep understanding of thermodynamics, fluid
|
||||||
|
mechanics, electrical circuits, Psychrometrics and air properties. This knowledge is essential for
|
||||||
|
designing, installing, and maintaining HVAC systems that operate seamlessly and efficiently.
|
||||||
|
|
||||||
|
## System Design and Installation:
|
||||||
|
|
||||||
|
HVAC professionals are involved in the intricate process of designing and installing heating,
|
||||||
|
ventilation, and air conditioning systems. This task requires not only a thorough understanding of
|
||||||
|
the physical principles governing HVAC but also the ability to tailor solutions to meet the unique
|
||||||
|
needs of each space. Proper system design and installation are crucial for achieving optimal energy
|
||||||
|
efficiency and performance.
|
||||||
|
|
||||||
|
## Diagnostic Skills:
|
||||||
|
|
||||||
|
Troubleshooting and diagnosing issues in HVAC systems require a keen analytical mind and
|
||||||
|
problem-solving skills. Skilled HVAC technicians possess the ability to identify and rectify
|
||||||
|
problems efficiently, ensuring minimal downtime and disruption to the comfort of occupants. This
|
||||||
|
diagnostic acumen is a hallmark of a trade that goes beyond routine labor.
|
||||||
|
|
||||||
|
## Adaptability to Advanced Technologies:
|
||||||
|
|
||||||
|
The HVAC industry is in a constant state of evolution, with new technologies and innovations
|
||||||
|
continuously being introduced. Skilled HVAC professionals are adaptable and stay abreast of these
|
||||||
|
advancements. From smart thermostats to energy-efficient systems, they integrate cutting-edge
|
||||||
|
technologies to provide state-of-the-art solutions for their clients.
|
||||||
|
|
||||||
|
## Safety and Compliance:
|
||||||
|
|
||||||
|
Safety is paramount in the HVAC trade. Professionals must adhere to strict safety protocols to
|
||||||
|
protect both themselves and the occupants of the spaces they work in. Additionally, compliance with
|
||||||
|
industry regulations and codes is a testament to the skilled nature of the trade, ensuring that HVAC
|
||||||
|
systems meet the highest standards of safety and efficiency.
|
||||||
|
|
||||||
|
## Continual Learning and Certification:
|
||||||
|
|
||||||
|
Unlike a labor job, HVAC professionals engage in continual learning to stay current with industry
|
||||||
|
trends and technological advancements. Many pursue certifications and attend training programs to
|
||||||
|
enhance their skills and expand their knowledge base. This commitment to ongoing education is a
|
||||||
|
hallmark of skilled trades.
|
||||||
|
|
||||||
|
## Conclusion:
|
||||||
|
|
||||||
|
Heating, Ventilation, and Air Conditioning is undeniably a skilled trade that goes beyond the
|
||||||
|
perception of a labor job. Labor jobs are also very important to the function of society and I have
|
||||||
|
proudly done these jobs myself. The technical proficiency, problem-solving abilities, adaptability,
|
||||||
|
and commitment to safety make HVAC professionals essential contributors to the creation of
|
||||||
|
comfortable and efficient indoor environments. It is crucial to recognize and appreciate the skill
|
||||||
|
set inherent in the HVAC trade, as it plays a vital role in shaping the quality of life for
|
||||||
|
individuals and the functionality of diverse spaces.
|
||||||
|
|
||||||
|
- Ty Branaman
|
||||||
128
content/articles/2024-03-15-unvr-as-nas.md
Normal file
128
content/articles/2024-03-15-unvr-as-nas.md
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
---
|
||||||
|
tags: programming, networking, nas, how-to
|
||||||
|
---
|
||||||
|
|
||||||
|
# UNVR as NAS
|
||||||
|
|
||||||
|
In this post, I'm going to show how to setup a Samba server on a Ubiquity UNVR so that it can be
|
||||||
|
used as NAS (network attached storage). Be aware that this should be done with caution and may void
|
||||||
|
any warranty on your UNVR as we are using it for purposes beyond it's original intent. It's also
|
||||||
|
possible that this setup will break when / if updating the UNVR software. With that said, let's jump
|
||||||
|
in.
|
||||||
|
|
||||||
|
This post follows along with
|
||||||
|
[this reddit post](https://www.reddit.com/r/Ubiquiti/comments/11o7v8l/how_to_use_the_unvr_as_a_nas_instructions/),
|
||||||
|
with some adaptations to get it to work on the latest Unifi-OS release of `3.2.12`.
|
||||||
|
|
||||||
|
## Step One - Setup SSH & Login
|
||||||
|
|
||||||
|
In your unifi network console you need to enable the `SSH` login option and set a secure password
|
||||||
|
for the root user to login to the UNVR.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Once that is complete you can login to your UNVR using your terminal and the IP address of your UNVR
|
||||||
|
on your network.
|
||||||
|
|
||||||
|
`ssh root@192.168.1.10`
|
||||||
|
|
||||||
|
## Step Two - Install Samba
|
||||||
|
|
||||||
|
First, we'll update the package registry information.
|
||||||
|
|
||||||
|
`apt-get update`
|
||||||
|
|
||||||
|
Next, install samba.
|
||||||
|
|
||||||
|
`apt-get install samba`
|
||||||
|
|
||||||
|
## Step Three - Setup Samba
|
||||||
|
|
||||||
|
In order to edit the configuration we are going to need to install your terminal based text editor
|
||||||
|
of choice (generally nano or vim), for me I will install vim.
|
||||||
|
|
||||||
|
`apt-get install vim`
|
||||||
|
|
||||||
|
Create a backup of the default configuration.
|
||||||
|
|
||||||
|
`cp /etc/samba/smb.conf /etc/samba/smb.conf.bak`
|
||||||
|
|
||||||
|
Open the configuration file to be edited.
|
||||||
|
|
||||||
|
`vim /etc/samba/smb.conf`
|
||||||
|
|
||||||
|
Just above the `Share Definitions` section of the configuration, I added some global settings to
|
||||||
|
make the samba server act better for time machine backups.
|
||||||
|
|
||||||
|
```
|
||||||
|
#======================= MacOS Client Optimizations =======================
|
||||||
|
vfs objects = fruit streams_xattr
|
||||||
|
fruit:metadata = stream
|
||||||
|
fruit:model = MacSamba
|
||||||
|
fruit:posix_rename = yes
|
||||||
|
fruit:veto_appledouble = no
|
||||||
|
fruit:nfs_aces = no
|
||||||
|
fruit:wipe_intentionally_left_blank_rfork = yes
|
||||||
|
fruit:delete_empty_adfiles = yes
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Also because we want users we create to be able to read and write to their home directories created
|
||||||
|
on the samba server, we need to change the option under the `[homes]` share definition to be
|
||||||
|
`read only = no`.
|
||||||
|
|
||||||
|
That is our primary configuration. You can add more share definitions at the bottom of the file to
|
||||||
|
suit your use case, there are decent examples of this in the original reddit post, linked in the
|
||||||
|
beginning.
|
||||||
|
|
||||||
|
Save and exit the file.
|
||||||
|
|
||||||
|
`:wq`
|
||||||
|
|
||||||
|
## Step Four - Start Samba
|
||||||
|
|
||||||
|
Use the following command to start the samba server.
|
||||||
|
|
||||||
|
`sudo service smbd start`
|
||||||
|
|
||||||
|
You can check the status, by running the following command.
|
||||||
|
|
||||||
|
`systemctl status smbd`
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Enable the samba server to start on boot.
|
||||||
|
|
||||||
|
`systemctl enable smbd.service`
|
||||||
|
|
||||||
|
## Step Five - Create Users
|
||||||
|
|
||||||
|
Create a user with a home directory that they can use.
|
||||||
|
|
||||||
|
`useradd --create-home michael`
|
||||||
|
|
||||||
|
Give the user a password to login to the samba server.
|
||||||
|
|
||||||
|
`smbpasswd michael`
|
||||||
|
|
||||||
|
## Step Six - Login to Samba Server from Client
|
||||||
|
|
||||||
|
In the `Finder` app on macOS you can type `⌘k` to connect to a server.
|
||||||
|
|
||||||
|
In the text field enter `smb://<USER>@<UNVR_IP>` to connect to the samba server.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
You can also automatically connect to the server when you login to your client device, for this to
|
||||||
|
work you need the credentials to be stored in your keychain (ticking the box in the step above when
|
||||||
|
you first connect to the server).
|
||||||
|
|
||||||
|
This is found in `System Settings -> General -> Login Items -> Open at Login`. Click the plus button
|
||||||
|
and select the volume you would like to mount at login.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Once you have it setup so that the server is connected on login, you can also set it up as location
|
||||||
|
for Time Machine Backups. `System Settings -> General -> Time Machine`
|
||||||
|
|
||||||
|

|
||||||
101
content/articles/2024-04-04-pgp-encryption-introduction.md
Normal file
101
content/articles/2024-04-04-pgp-encryption-introduction.md
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
---
|
||||||
|
image: 2024-04-04-pgp-encryption-introduction.gif
|
||||||
|
tags: programming, security, PGP, GnuPGP
|
||||||
|
---
|
||||||
|
|
||||||
|
# PGP Encryption Introduction
|
||||||
|
|
||||||
|
In this article I introduce PGP and show a use case for me, which perhaps you can use as well.
|
||||||
|
|
||||||
|
## What is PGP
|
||||||
|
|
||||||
|
PGP stands for **Pretty Good Privacy**, it was first developed in 1991 by Phil Zimmermann. PGP uses
|
||||||
|
cryptographic privacy and authentication and is generally used in data communication.
|
||||||
|
|
||||||
|
According to [Wikipedia](https://en.wikipedia.org/wiki/Pretty_Good_Privacy) it's name was inspired
|
||||||
|
by a grocery store named, "Ralph's Pretty Goody Grocery" featured in radio host's Garrison Keillor's
|
||||||
|
fictional town of Lake Wobegon.
|
||||||
|
|
||||||
|
PGP is commonly used in software development to "sign" software commits or files to help ensure both
|
||||||
|
who the commits were from as well as make sure they were not modified from the original versions.
|
||||||
|
|
||||||
|
It should also be noted that when people say PGP they are often referring to OpenPGP or GnuPGP which
|
||||||
|
are implementations of the PGP standard protocol.
|
||||||
|
|
||||||
|
## What it does
|
||||||
|
|
||||||
|
> Note: I am in no way a cyber-security expert, I am a layman and only describing things in terms
|
||||||
|
> that I understand / make sense to me. Do what I do at your own risk!
|
||||||
|
|
||||||
|
PGP offers both symmetrical encryption (uses a session key and password) or asymmetrical encryption
|
||||||
|
(uses a session key and a private key). Asymmetrical encryption is more secure but is more resource
|
||||||
|
intensive (which is generally not a problem with computers of today).
|
||||||
|
|
||||||
|
Generally speaking PGP uses what are known as public and private key pairs. The public portion of
|
||||||
|
the key par is meant to be shared with others freely, while the private portion needs to be secured
|
||||||
|
/ not shared with anyone **EVER**. It is best practice to generate your keys on a computer that is
|
||||||
|
"air gapped", meaning it is not connected to any network / internet, and does not save a history of
|
||||||
|
commands performed on it.
|
||||||
|
|
||||||
|
PGP encrypts data (files, messages, etc.) for one or more recipients, using the recipients public
|
||||||
|
key. The recipients private key is required to decrypt the data once it's been encrypted.
|
||||||
|
|
||||||
|
Your key pair is tied to your identity / person, generally by your name and email(s). The key can
|
||||||
|
also have multiple "subkeys", meaning that if you have more than one public email, alias, etc. it
|
||||||
|
can be tied to your same private key. This is useful for example for work vs. activism vs. software
|
||||||
|
development.
|
||||||
|
|
||||||
|
Once your key is generated and your private key secured, you can share your public portion of the
|
||||||
|
key to a "keyserver" where other people can download it and verify messages were sent by you.
|
||||||
|
|
||||||
|
## Web of Trust
|
||||||
|
|
||||||
|
PGP also uses what is called the **"Web of Trust"**, which is used to validate that messages are
|
||||||
|
encrypted by a trusted source. There are different levels of trust depending on where a key is
|
||||||
|
retrieved from. For example, if somebody gave you their public key in person and you were able to
|
||||||
|
inspect that the identity matches their government id, then you can give it a higher trust level
|
||||||
|
than one that is sent / retrieved from a keyserver.
|
||||||
|
|
||||||
|
My understanding of this portion is that over time your key is signed by other's with their level of
|
||||||
|
certainty about you / your key, which over time increases the overall trust in your key.
|
||||||
|
|
||||||
|
## Out of the weeds
|
||||||
|
|
||||||
|
Now that we've got an understanding of some of the technical aspects, lets talk about some real use
|
||||||
|
cases of PGP encryption.
|
||||||
|
|
||||||
|
PGP encryption is used by some email clients / applications, such as
|
||||||
|
[Canary](https://canarymail.io/),
|
||||||
|
[Thunderbird](https://www.thunderbird.net/en-US/thunderbird/115.0/holidayeoy/), or
|
||||||
|
[GPGSuite](https://gpgtools.tenderapp.com/).
|
||||||
|
|
||||||
|
In my understanding, it is also what is used in devices such as a
|
||||||
|
[YubiKey](https://www.yubico.com/).
|
||||||
|
|
||||||
|
Many of the mentioned applications allow for an easier interface / adoption, as one of the reasons
|
||||||
|
it is not very popular is that it can be hard to use PGP for the average person.
|
||||||
|
|
||||||
|
Aside from using my PGP key for signing software commits, my major use case is for encrypting files
|
||||||
|
that I store in a "cloud" provider. Know that when someone says the "cloud", it is really just a
|
||||||
|
computer (in reality a gang of computers in a data center). You are solely reliant that these cloud
|
||||||
|
providers are not snooping on, inspecting, or even selling your data.
|
||||||
|
|
||||||
|
Of course, some data may not be that sensitive, so maybe you don't care. However with a little bit
|
||||||
|
of effort on your part you can at least make it very hard for anyone to know what is inside your
|
||||||
|
documents. You can be in control of the way your items are encrypted and have confidence that nobody
|
||||||
|
but you can access what is inside your documents.
|
||||||
|
|
||||||
|
Heck, I even encrypt documents that are stored on my own network / computer so that if something
|
||||||
|
get's stolen or someone breach's my network they will not be able to easily get to sensitive data.
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
This article is just meant as an overview of PGP encryption. In future articles I will show you how
|
||||||
|
to use it to encrypt your data and be in control of your privacy.
|
||||||
|
|
||||||
|
### Resources
|
||||||
|
|
||||||
|
- [GnuPG](https://gnupg.org/)
|
||||||
|
- [OpenPGP](https://www.openpgp.org/)
|
||||||
|
- [gpg.wtf](https://gpg.wtf/)
|
||||||
|
- [RFC4880](https://www.ietf.org/rfc/rfc4880.html)
|
||||||
103
content/articles/2024-04-09-free-as-in-freedom.md
Normal file
103
content/articles/2024-04-09-free-as-in-freedom.md
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
---
|
||||||
|
tags: general, open-source, software
|
||||||
|
summary: Salute to open-source software engineers
|
||||||
|
---
|
||||||
|
|
||||||
|
# Free As In Freedom
|
||||||
|
|
||||||
|
This is a hot take kind of article, but here it goes the rant.
|
||||||
|
|
||||||
|
## This applies to me and you.
|
||||||
|
|
||||||
|
I'm writing this to remind myself somethings that I too often take for granted. I am going to
|
||||||
|
preface this whole article by saying that everything I'm going to lay out / mention is something
|
||||||
|
that I am personally guilty of. This is an open reminder and call out of things that I feel should
|
||||||
|
change.
|
||||||
|
|
||||||
|
# Our perspective is flawed
|
||||||
|
|
||||||
|
Nobody can dispute that the advances in technology have greatly improved our lives. Like anything,
|
||||||
|
though, there is a trade off.
|
||||||
|
|
||||||
|
## What is FOSS
|
||||||
|
|
||||||
|
FOSS is an acronym for "Free and Open Source Software". It is generally about how software is
|
||||||
|
licensed, meaning that the source code is available in the public for review, allowing a broader
|
||||||
|
spectrum of people than the originators of the code to have input, look for bugs, redistribute the
|
||||||
|
software, contribute, etc. It does not however mean that the software should be no cost to the end
|
||||||
|
user.
|
||||||
|
|
||||||
|
This is where the word "freedom" comes into it. Overtime, as a society, we generally now think of
|
||||||
|
FOSS as "free" software. This takes what was originally a noble / courageous idea and devalues it to
|
||||||
|
the point that we now expect things to be free. It encourages corporate greed to take advantage of
|
||||||
|
people who created something to solve a particular need, or as a hobby, expecting the creator to
|
||||||
|
handle the burden of maintaining / patching bugs while they profit from it. Don't get me wrong,
|
||||||
|
these corporations will also contribute back, sometimes even donate money to the creators. I am not
|
||||||
|
at all opposed to capitalism, nor saying that these corporations are in the wrong. At the end of the
|
||||||
|
day, **_we_** created this problem.
|
||||||
|
|
||||||
|
## Current state and how we got here
|
||||||
|
|
||||||
|
Software services / giants create applications that we come to rely on. They tempt / bait us with
|
||||||
|
them being "free" or cheap, but that is because **_we_** are their target. They bloat the software
|
||||||
|
with tracking and telemetry to capture data about us and sell us more products and services. Once
|
||||||
|
again, if you're pro-capitalism, it's somewhat hard to blame them for this. We're the gullible sheep
|
||||||
|
who will blindly eat out their grain bins.
|
||||||
|
|
||||||
|
I can remember back in the day when there were music pirating services on the internet (napster is
|
||||||
|
the one that comes to mind). As a giant music buff, I quickly jumped on board with services like
|
||||||
|
these. Back in those days, I was young, didn't make very much money, so it was hard to afford the
|
||||||
|
latest and greatest tunes. I also remember back in this time frame a lawsuit from the metal giants
|
||||||
|
Metallica (other's words not mine ;)). At the time I remember thinking, like many others, that
|
||||||
|
Metallica didn't need the money, but then a comment from Lars Ulrich the band's drummer struck a
|
||||||
|
cord with me (pun intended). I'll will paraphrase here, but it was something along the lines of
|
||||||
|
"We're not pursuing this for us, but for all of those (musicians) that come after us". After this
|
||||||
|
and reflection, I decided that I would not pirate music anymore.
|
||||||
|
|
||||||
|
Fast forward, now the majority do not purchases music / albums, we typically utilize streaming
|
||||||
|
services (myself included), sure it may be more fair to the artists than pirating was, it can be
|
||||||
|
argued that it's easier today for independent artists to become known / discovered, I'm also in no
|
||||||
|
way saying the old school music industry wasn't a giant pile of dog poo, but I am saying that who is
|
||||||
|
really winning(?), it's the Spotify's and Apple Music's of the world, that's who.
|
||||||
|
|
||||||
|
I'm also reminded of the great "MeasureQuick is now charging for services" that happened in the HVAC
|
||||||
|
industry. I have personally never complained and have always supported this decision, because it is
|
||||||
|
not sustainable to run a software company and not charge for services, generally. Sure, you may not
|
||||||
|
like their pricing model, etc. Where I think they went wrong was not charging from the beginning, as
|
||||||
|
it sets the wrong expectation that is presumably hard to recover from. There are those who took some
|
||||||
|
of Jim's words / opinions in a way different from how I do / did, which is fine, we're all entitled
|
||||||
|
to our opinions. What is often forgotten is that we're all also entitled to change those opinions.
|
||||||
|
Heck, I will probably be shouting a different story tomorrow, so be it!
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
What I would like to encourage people to do is to support software development. If an application is
|
||||||
|
free, but has a donate button consider giving a donation. If an application is free and they don't
|
||||||
|
want to charge that's fine too, however I would say to be suspicous, meaning is it free because
|
||||||
|
**_you_** are the product?!?
|
||||||
|
|
||||||
|
I would also encourage you to be active in communities and organizations that foster community (HVAC
|
||||||
|
School is a great example). Show appreciation and encouragement, but at the same time don't be
|
||||||
|
afraid to be critical or speak up.
|
||||||
|
|
||||||
|
At the end of the day, I hope to lift up my brothers and sisters, help to fight against the
|
||||||
|
corporations who abuse the little guy's and hopefully feel good about my decisions.
|
||||||
|
|
||||||
|
Over the last few weeks, I have been going through my software and services and looking for those
|
||||||
|
donation buttons and giving back a little bit for the software that makes my life better. Help
|
||||||
|
change the narrative and remember that it's about **_Freedom not Free_**.
|
||||||
|
|
||||||
|
### Links
|
||||||
|
|
||||||
|
- [Open-source Software](https://en.wikipedia.org/wiki/Open-source_software)
|
||||||
|
- [Free Software Fondation](https://en.wikipedia.org/wiki/Free_Software_Foundation)
|
||||||
|
- [Electronic Frontier Foundation](https://www.eff.org/)
|
||||||
|
|
||||||
|
### Software used in this blog.
|
||||||
|
|
||||||
|
- [Neovim](https://neovim.io/)
|
||||||
|
- [Hugo](https://gohugo.io/)
|
||||||
|
- [Hugo Theme](https://themes.gohugo.io/themes/poison/)
|
||||||
|
|
||||||
|
> **Note:** I do not use any trackers or analytics on this site to respect your privacy. So feel
|
||||||
|
> free to contact me directly to share feedback or let me know how I'm doing.
|
||||||
514
content/articles/2025-01-05-vapor-htmx-todo-app.md
Normal file
514
content/articles/2025-01-05-vapor-htmx-todo-app.md
Normal file
@@ -0,0 +1,514 @@
|
|||||||
|
---
|
||||||
|
tags: general, software, programming
|
||||||
|
summary: Build an example application using Vapor and HTMX.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Vapor + HTMX
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
This post is a quick example of creating a very basic todo web application using `Vapor` a swift web
|
||||||
|
framework and `Htmx`, with no custom javascript required.
|
||||||
|
|
||||||
|
[Vapor](https://docs.vapor.codes)
|
||||||
|
|
||||||
|
[Htmx](https://htmx.org)
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
To get started you must install the vapor command-line tool that will generate our project.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
brew install vapor
|
||||||
|
```
|
||||||
|
|
||||||
|
Next, generate the project using the vapor command-line tool.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
```bash
|
||||||
|
vapor new todo-htmx --fluent.db sqlite --leaf
|
||||||
|
```
|
||||||
|
|
||||||
|
The above command will generate a new project that uses an `SQLite` database along with vapor's
|
||||||
|
`Leaf` templating engine. You can move into the project directory and browse around the files that
|
||||||
|
are generated.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd todo-htmx
|
||||||
|
```
|
||||||
|
|
||||||
|
## Update the Controller
|
||||||
|
|
||||||
|
Open the `Sources/App/Controllers/TodoController.swift` file. This file handles the api routes for
|
||||||
|
our `Todo` database model. Personally I like to prefix these routes with `api`.
|
||||||
|
|
||||||
|
Update the first line in the `boot(routes: RoutesBuilder)` function to look like this.
|
||||||
|
|
||||||
|
```swift
|
||||||
|
let todos = routes.grouped("api", "todos")
|
||||||
|
```
|
||||||
|
|
||||||
|
Everything else can stay the same. This changes these routes to be exposed at
|
||||||
|
`http://localhost:8080/api/todos`, which will allow our routes that return html views to be able to
|
||||||
|
be exposed at `http://localhost:8080/todos`.
|
||||||
|
|
||||||
|
## Update the Todo Model
|
||||||
|
|
||||||
|
A todo is not very valuable without a way to tell if it needs to be completed or not. So, let's add
|
||||||
|
a field to our database model (`Sources/App/Models/Todo.swift`).
|
||||||
|
|
||||||
|
Update the file to include the following:
|
||||||
|
|
||||||
|
```swift
|
||||||
|
import Fluent
|
||||||
|
import struct Foundation.UUID
|
||||||
|
|
||||||
|
/// Property wrappers interact poorly with `Sendable` checking, causing a warning for the `@ID` property
|
||||||
|
/// It is recommended you write your model with sendability checking on and then suppress the warning
|
||||||
|
/// afterwards with `@unchecked Sendable`.
|
||||||
|
final class Todo: Model, @unchecked Sendable {
|
||||||
|
static let schema = "todos"
|
||||||
|
|
||||||
|
@ID(key: .id)
|
||||||
|
var id: UUID?
|
||||||
|
|
||||||
|
@Field(key: "title")
|
||||||
|
var title: String
|
||||||
|
|
||||||
|
@Field(key: "complete")
|
||||||
|
var complete: Bool
|
||||||
|
|
||||||
|
init() {}
|
||||||
|
|
||||||
|
init(id: UUID? = nil, title: String, complete: Bool) {
|
||||||
|
self.id = id
|
||||||
|
self.title = title
|
||||||
|
self.complete = complete
|
||||||
|
}
|
||||||
|
|
||||||
|
func toDTO() -> TodoDTO {
|
||||||
|
.init(
|
||||||
|
id: id,
|
||||||
|
title: $title.value,
|
||||||
|
complete: $complete.value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Since we added a field to our database model, we also need to update the migration file
|
||||||
|
(`Sources/App/Migrations/CreateTodo.swift`).
|
||||||
|
|
||||||
|
```swift
|
||||||
|
import Fluent
|
||||||
|
|
||||||
|
struct CreateTodo: AsyncMigration {
|
||||||
|
func prepare(on database: Database) async throws {
|
||||||
|
try await database.schema("todos")
|
||||||
|
.id()
|
||||||
|
.field("title", .string, .required)
|
||||||
|
.field("complete", .bool, .required)
|
||||||
|
.create()
|
||||||
|
}
|
||||||
|
|
||||||
|
func revert(on database: Database) async throws {
|
||||||
|
try await database.schema("todos").delete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This just adds our new field to the database schema when we run the migrations, which we will do
|
||||||
|
later on in the tutorial.
|
||||||
|
|
||||||
|
### Update the Data Transfer Object
|
||||||
|
|
||||||
|
We also need to add the `complete` field to our data transfer object (`DTO`). This model is used as
|
||||||
|
an intermediate between our database and the user.
|
||||||
|
|
||||||
|
```swift
|
||||||
|
import Fluent
|
||||||
|
import Vapor
|
||||||
|
|
||||||
|
struct TodoDTO: Content {
|
||||||
|
var id: UUID?
|
||||||
|
var title: String?
|
||||||
|
var complete: Bool?
|
||||||
|
|
||||||
|
func toModel() -> Todo {
|
||||||
|
let model = Todo()
|
||||||
|
|
||||||
|
model.id = id
|
||||||
|
model.complete = complete ?? false
|
||||||
|
if let title = title {
|
||||||
|
model.title = title
|
||||||
|
}
|
||||||
|
return model
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Generate the View Templates
|
||||||
|
|
||||||
|
Our index template was already generated at `Resources/Views/index.leaf`, open the file and edit the
|
||||||
|
contents to match the following.
|
||||||
|
|
||||||
|
> Note: You can learn more about the
|
||||||
|
> [leaf templating engine here.](https://docs.vapor.codes/leaf/getting-started/)
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>#(title)</title>
|
||||||
|
<link rel="stylesheet" href="css/main.css" />
|
||||||
|
<script src="https://unpkg.com/htmx.org@2.0.4"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>#(title)</h1>
|
||||||
|
<div class="container">
|
||||||
|
<form hx-post="/todos" hx-target="#todos">
|
||||||
|
<label for="title">Todo</label>
|
||||||
|
<input type="text" name="title" placeholder="Title" />
|
||||||
|
<button type="submit">Submit</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<!-- Todos List -->
|
||||||
|
<table id="todos" class="todos" hx-get="/todos" hx-trigger="load"></table>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
```
|
||||||
|
|
||||||
|
The important parts here are the `<script>` tag in the head element which will include `Htmx` in our
|
||||||
|
project.
|
||||||
|
|
||||||
|
The head element also contains a link to a custom `css` stylesheet that we will create shortly.
|
||||||
|
|
||||||
|
We add a `form` element that will be used to generate a new todo item in the database. This is a
|
||||||
|
basic / standard html form, but we are using `Htmx` to post the form contents to the route
|
||||||
|
`POST http://localhost:8080/todos`, which we will create shortly.
|
||||||
|
|
||||||
|
Then there's the `table` element that will contain the contents of our todos. When the page is
|
||||||
|
loaded it will use `Htmx` to fetch the todos from `GET http://localhost:8080/todos` route, which we
|
||||||
|
will create shortly.
|
||||||
|
|
||||||
|
### Todos Table Template
|
||||||
|
|
||||||
|
Create a new view template that will return our populated table of todos.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
touch Resources/Views/todos.leaf
|
||||||
|
```
|
||||||
|
|
||||||
|
The contents of this file should be the following:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!-- Template for a list of todo's -->
|
||||||
|
<table id="todos"
|
||||||
|
class="todos">
|
||||||
|
<!-- The table header -->
|
||||||
|
<tr>
|
||||||
|
<th>Description</th>
|
||||||
|
<th>Completed</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
#for(todo in todos):
|
||||||
|
<tr>
|
||||||
|
<!-- Make the title column take up 90% of the width -->
|
||||||
|
<td style="width: 90%;">#(todo.title)</td>
|
||||||
|
<td>
|
||||||
|
<input type="checkbox"
|
||||||
|
id="todo_#(todo.id)"
|
||||||
|
hx-put="/todos/#(todo.id)"
|
||||||
|
hx-trigger="click"
|
||||||
|
hx-target="#todos"
|
||||||
|
#if(todo.complete): checked #endif>
|
||||||
|
</input>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<button hx-delete="/todos/#(todo.id)"
|
||||||
|
hx-trigger="click"
|
||||||
|
hx-target="#todos"
|
||||||
|
class="btn-delete-todo">
|
||||||
|
X
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
#endfor
|
||||||
|
</table>
|
||||||
|
```
|
||||||
|
|
||||||
|
Here, we just create a table that is 3 columns wide from a list of todos that we will pass in to the
|
||||||
|
template. We use `Htmx` to handle updating a todo if a user clicks a checkbox to mark the todo as
|
||||||
|
`complete`, we also add a button in the last column of the table that we use `Htmx` to handle
|
||||||
|
deleting a todo from the database.
|
||||||
|
|
||||||
|
## Controllers
|
||||||
|
|
||||||
|
The controllers handle the routes that our website exposes. The project template creates a
|
||||||
|
controller for us that handles `JSON` / `API` requests, but we do need to make a couple of changes
|
||||||
|
to the file (`Sources/App/Controllers/TodoController.swift`).
|
||||||
|
|
||||||
|
```swift
|
||||||
|
import Fluent
|
||||||
|
import Vapor
|
||||||
|
|
||||||
|
struct TodoController: RouteCollection {
|
||||||
|
func boot(routes: RoutesBuilder) throws {
|
||||||
|
let todos = routes.grouped("api", "todos")
|
||||||
|
|
||||||
|
todos.get(use: index)
|
||||||
|
todos.post(use: create)
|
||||||
|
todos.group(":todoID") { todo in
|
||||||
|
todo.delete(use: self.delete)
|
||||||
|
todo.put(use: self.update)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Sendable
|
||||||
|
func index(req: Request) async throws -> [TodoDTO] {
|
||||||
|
try await Todo.query(on: req.db).all().map { $0.toDTO() }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Sendable
|
||||||
|
func create(req: Request) async throws -> TodoDTO {
|
||||||
|
let todo = try req.content.decode(TodoDTO.self).toModel()
|
||||||
|
|
||||||
|
try await todo.save(on: req.db)
|
||||||
|
return todo.toDTO()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Sendable
|
||||||
|
func delete(req: Request) async throws -> HTTPStatus {
|
||||||
|
guard let todo = try await Todo.find(req.parameters.get("todoID"), on: req.db) else {
|
||||||
|
throw Abort(.notFound)
|
||||||
|
}
|
||||||
|
|
||||||
|
try await todo.delete(on: req.db)
|
||||||
|
return .noContent
|
||||||
|
}
|
||||||
|
|
||||||
|
@Sendable
|
||||||
|
func update(req: Request) async throws -> TodoDTO {
|
||||||
|
// let todo = try req.content.decode(TodoDTO.self).toModel()
|
||||||
|
guard let todo = try await Todo.find(req.parameters.get("todoID"), on: req.db) else {
|
||||||
|
throw Abort(.notFound)
|
||||||
|
}
|
||||||
|
todo.complete.toggle()
|
||||||
|
try await todo.save(on: req.db)
|
||||||
|
return todo.toDTO()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The primary changes here are to add the `update(req: Request)` function at the bottom, which handles
|
||||||
|
updating a todo that has already been created. This will be used when a user clicks on the checkbox
|
||||||
|
to mark a todo as complete or incomplete.
|
||||||
|
|
||||||
|
We also change the route in the `boot(routes: RoutesBuilder)` method to make all these routes
|
||||||
|
accessible at `/api/todos` instead of the original `/todos` as we will use the `/todos` routes for
|
||||||
|
returning our views from our view controller.
|
||||||
|
|
||||||
|
### Todo View Controller
|
||||||
|
|
||||||
|
Next we need to create our view controller, it is what will be used to handle routes that should
|
||||||
|
return `html` content for our website. This controller will actually use the api controller to do
|
||||||
|
the majority of it's work.
|
||||||
|
|
||||||
|
The easiest thing is to make a copy of the current api controller:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp Sources/App/Controllers/TodoController.swift Sources/App/Controllers/TodoViewController.swift
|
||||||
|
```
|
||||||
|
|
||||||
|
Then update the file to the following:
|
||||||
|
|
||||||
|
```swift
|
||||||
|
import Fluent
|
||||||
|
import Vapor
|
||||||
|
|
||||||
|
struct TodoViewController: RouteCollection {
|
||||||
|
|
||||||
|
private let api = TodoController()
|
||||||
|
|
||||||
|
func boot(routes: RoutesBuilder) throws {
|
||||||
|
let todos = routes.grouped("todos")
|
||||||
|
|
||||||
|
todos.get(use: index)
|
||||||
|
todos.post(use: create)
|
||||||
|
todos.group(":todoID") { todo in
|
||||||
|
todo.delete(use: self.delete)
|
||||||
|
todo.put(use: self.update)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Sendable
|
||||||
|
func index(req: Request) async throws -> View {
|
||||||
|
let todos = try await api.index(req: req)
|
||||||
|
return try await req.view.render("todos", ["todos": todos])
|
||||||
|
}
|
||||||
|
|
||||||
|
@Sendable
|
||||||
|
func create(req: Request) async throws -> View {
|
||||||
|
_ = try await api.create(req: req)
|
||||||
|
return try await index(req: req)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Sendable
|
||||||
|
func delete(req: Request) async throws -> View {
|
||||||
|
_ = try await api.delete(req: req)
|
||||||
|
return try await index(req: req)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Sendable
|
||||||
|
func update(req: Request) async throws -> View {
|
||||||
|
_ = try await api.update(req: req)
|
||||||
|
return try await index(req: req)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Here we use the api controller to do the heavy lifting of communicating with the database, then we
|
||||||
|
just always return / render the `todos.leaf` template that we created earlier, which will update our
|
||||||
|
web page with the list of todos retreived from the database.
|
||||||
|
|
||||||
|
> Note: There are better ways to handle this, however this is just a simple example.
|
||||||
|
|
||||||
|
### Update our routes
|
||||||
|
|
||||||
|
Next, we need to tell vapor to use our new view controller (`Sources/App/routes.swift`)
|
||||||
|
|
||||||
|
```swift
|
||||||
|
import Fluent
|
||||||
|
import Vapor
|
||||||
|
|
||||||
|
func routes(_ app: Application) throws {
|
||||||
|
app.get { req async throws in
|
||||||
|
try await req.view.render("index", ["title": "Todos"])
|
||||||
|
}
|
||||||
|
|
||||||
|
app.get("hello") { _ async -> String in
|
||||||
|
"Hello, world!"
|
||||||
|
}
|
||||||
|
|
||||||
|
try app.register(collection: TodoController())
|
||||||
|
try app.register(collection: TodoViewController())
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Here, we just add the `TodoViewController` at the bottom so vapor will be able to handle those
|
||||||
|
routes and also update the title to be `Todos` (in the first `app.get` near the top).
|
||||||
|
|
||||||
|
## Build and Run
|
||||||
|
|
||||||
|
At this point we should be able to build and run the application.
|
||||||
|
|
||||||
|
First, let's make sure the project builds.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
swift build
|
||||||
|
```
|
||||||
|
|
||||||
|
This may take a minute if it's the first time building the project as it has to fetch the
|
||||||
|
dependencies. If you experience problems here then make sure you don't have typos in your files.
|
||||||
|
|
||||||
|
Next, we need to run the database migrations.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
swift run App migrate
|
||||||
|
```
|
||||||
|
|
||||||
|
Finally, we can run the application.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
swift run App
|
||||||
|
```
|
||||||
|
|
||||||
|
You should be able to open your browser and type in the url: `http://localhost:8080` to view the
|
||||||
|
application. You can experiment with adding a new todo using the form.
|
||||||
|
|
||||||
|
> Note: To stop the application use `Ctrl-c`
|
||||||
|
|
||||||
|
## Bonus Styles
|
||||||
|
|
||||||
|
Hopefully you weren't blinded the first time you opened the application. You can add custom styles
|
||||||
|
by creating a `css` file (`Public/css/main.css`).
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir Public/css
|
||||||
|
touch Public/css/main.css
|
||||||
|
```
|
||||||
|
|
||||||
|
Update the file to the following:
|
||||||
|
|
||||||
|
```css
|
||||||
|
body {
|
||||||
|
background-color: #1e1e2e;
|
||||||
|
color: #ff66ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
th,
|
||||||
|
td {
|
||||||
|
border-bottom: 1px solid grey;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.todos {
|
||||||
|
transition: all ease-in 1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-delete-todo {
|
||||||
|
color: red;
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Currently vapor does not know to serve files from the `Public` directory, so we need to update the
|
||||||
|
`Sources/App/configure.swift` file, by uncommenting the line near the top.
|
||||||
|
|
||||||
|
```swift
|
||||||
|
import Fluent
|
||||||
|
import FluentSQLiteDriver
|
||||||
|
import Leaf
|
||||||
|
import NIOSSL
|
||||||
|
import Vapor
|
||||||
|
|
||||||
|
// configures your application
|
||||||
|
public func configure(_ app: Application) async throws {
|
||||||
|
// uncomment to serve files from /Public folder
|
||||||
|
app.middleware.use(FileMiddleware(publicDirectory: app.directory.publicDirectory))
|
||||||
|
|
||||||
|
app.databases.use(DatabaseConfigurationFactory.sqlite(.file("db.sqlite")), as: .sqlite)
|
||||||
|
|
||||||
|
app.migrations.add(CreateTodo())
|
||||||
|
|
||||||
|
app.views.use(.leaf)
|
||||||
|
|
||||||
|
// register routes
|
||||||
|
try routes(app)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Now you can stop and restart to see the styled website.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
swift run App
|
||||||
|
```
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
I hope you enjoyed this quick example of using `Htmx` with `Vapor`. You can view the source files at
|
||||||
|
[here](https://github.com/m-housh/todo-htmx).
|
||||||
BIN
content/articles/images/2023-09-19-calculate-seer-degradation-by-age.png
LFS
Normal file
BIN
content/articles/images/2023-09-19-calculate-seer-degradation-by-age.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-10-18-the-struggle.png
LFS
Normal file
BIN
content/articles/images/2023-10-18-the-struggle.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-10-21-markdown.png
LFS
Normal file
BIN
content/articles/images/2023-10-21-markdown.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-10-21-pandoc.gif
LFS
Normal file
BIN
content/articles/images/2023-10-21-pandoc.gif
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-10-21-you-should-learn-markdown.png
LFS
Normal file
BIN
content/articles/images/2023-10-21-you-should-learn-markdown.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-10-27-ah.png
LFS
Normal file
BIN
content/articles/images/2023-10-27-ah.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-10-27-buffers2.png
LFS
Normal file
BIN
content/articles/images/2023-10-27-buffers2.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-10-27-heat-recovery-chiller.png
LFS
Normal file
BIN
content/articles/images/2023-10-27-heat-recovery-chiller.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-10-30-hope.png
LFS
Normal file
BIN
content/articles/images/2023-10-30-hope.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-12-12-cancel-this.gif
LFS
Normal file
BIN
content/articles/images/2023-12-12-cancel-this.gif
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-12-14-most-important-job.gif
LFS
Normal file
BIN
content/articles/images/2023-12-14-most-important-job.gif
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2024-02-27-elevating-hvac.png
LFS
Normal file
BIN
content/articles/images/2024-02-27-elevating-hvac.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2024-03-15-connect.png
LFS
Normal file
BIN
content/articles/images/2024-03-15-connect.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2024-03-15-login.png
LFS
Normal file
BIN
content/articles/images/2024-03-15-login.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2024-03-15-ssh.png
LFS
Normal file
BIN
content/articles/images/2024-03-15-ssh.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2024-03-15-status.png
LFS
Normal file
BIN
content/articles/images/2024-03-15-status.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2024-03-15-time-machine.png
LFS
Normal file
BIN
content/articles/images/2024-03-15-time-machine.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2024-03-15-unvr-as-nas.png
LFS
Normal file
BIN
content/articles/images/2024-03-15-unvr-as-nas.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2024-04-04-pgp-encryption-introduction.gif
LFS
Normal file
BIN
content/articles/images/2024-04-04-pgp-encryption-introduction.gif
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2024-04-09-free-as-in-freedom.png
LFS
Normal file
BIN
content/articles/images/2024-04-09-free-as-in-freedom.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2025-01-05-vapor-htmx-todo-app.png
LFS
Normal file
BIN
content/articles/images/2025-01-05-vapor-htmx-todo-app.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2025-01-05-vapor.gif
LFS
Normal file
BIN
content/articles/images/2025-01-05-vapor.gif
LFS
Normal file
Binary file not shown.
10
content/index.md
Normal file
10
content/index.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
section: home
|
||||||
|
---
|
||||||
|
|
||||||
|
# Home
|
||||||
|
|
||||||
|
- HVAC
|
||||||
|
- Design
|
||||||
|
- Programming
|
||||||
|
- Home Performance
|
||||||
BIN
content/static/favicon.ico
Normal file
BIN
content/static/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
BIN
content/static/images/avatar.png
LFS
Normal file
BIN
content/static/images/avatar.png
LFS
Normal file
Binary file not shown.
130
content/static/input.css
Normal file
130
content/static/input.css
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
@import url('https://fonts.cdnfonts.com/css/avenir');
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Anonymous Pro";
|
||||||
|
src: local("Anonymous Pro Regular"), url(/static/AnonymousPro-Regular.ttf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* BODY */
|
||||||
|
|
||||||
|
body.home nav {
|
||||||
|
@apply lg:justify-center;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.home header img {
|
||||||
|
@apply block lg:hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.home .site-footer {
|
||||||
|
@apply hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.home .images img {
|
||||||
|
@apply inline m-5 h-[28px];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LINKS */
|
||||||
|
|
||||||
|
nav a {
|
||||||
|
@apply block border-b-2 border-transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a:hover {
|
||||||
|
@apply border-orange;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a.active {
|
||||||
|
@apply border-orange text-white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gray-links a {
|
||||||
|
@apply underline text-inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gray-links a:hover {
|
||||||
|
@apply text-white;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.orange {
|
||||||
|
@apply text-orange;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.orange:hover {
|
||||||
|
@apply underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
a[href^="https://github.com"].app {
|
||||||
|
background: transparent url("images/github.svg") no-repeat;
|
||||||
|
background-size: 1em 1em;
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a[href^="https://itunes.apple.com"].app, a[href^="https://apps.apple.com"].app {
|
||||||
|
background: transparent url("images/apple.svg") no-repeat;
|
||||||
|
background-size: 1em 1em;
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PROSE */
|
||||||
|
|
||||||
|
.prose {
|
||||||
|
@apply prose-code:before:hidden prose-code:after:hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose code {
|
||||||
|
@apply font-normal text-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose pre {
|
||||||
|
@apply shadow-lg shadow-nav;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose hr {
|
||||||
|
margin-left: 140px;
|
||||||
|
margin-right: 140px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-regular {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SCREENSHOTS */
|
||||||
|
|
||||||
|
.screenshots.break_1 span {
|
||||||
|
@apply flex-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.screenshots.break_2 span {
|
||||||
|
@apply flex-[0_0_50%] lg:flex-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.screenshots.break_3 span {
|
||||||
|
@apply flex-[0_0_33%] lg:flex-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.screenshots img {
|
||||||
|
padding: 3px 3px 0 0;
|
||||||
|
border-radius: 0px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.screenshots.rounded img {
|
||||||
|
border-radius: 10%/4.7%;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 860px) {
|
||||||
|
.prose pre {
|
||||||
|
margin-left: -20px;
|
||||||
|
width: 840px;
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.projects .bg-sub {
|
||||||
|
margin-left: -20px;
|
||||||
|
width: 840px;
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
1
content/static/output.css
Normal file
1
content/static/output.css
Normal file
File diff suppressed because one or more lines are too long
142
content/static/prism.css
Normal file
142
content/static/prism.css
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
/* PrismJS 1.23.0
|
||||||
|
https://prismjs.com/download.html#themes=prism&languages=css+clike+javascript+c+objectivec+python+swift */
|
||||||
|
/**
|
||||||
|
* prism.js default theme for JavaScript, CSS and HTML
|
||||||
|
* Based on dabblet (http://dabblet.com)
|
||||||
|
* @author Lea Verou
|
||||||
|
*/
|
||||||
|
|
||||||
|
code[class*="language-"],
|
||||||
|
pre[class*="language-"] {
|
||||||
|
color: black;
|
||||||
|
background: none;
|
||||||
|
text-shadow: 0 1px white;
|
||||||
|
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||||
|
font-size: 1em;
|
||||||
|
text-align: left;
|
||||||
|
white-space: pre;
|
||||||
|
word-spacing: normal;
|
||||||
|
word-break: normal;
|
||||||
|
word-wrap: normal;
|
||||||
|
line-height: 1.5;
|
||||||
|
|
||||||
|
-moz-tab-size: 4;
|
||||||
|
-o-tab-size: 4;
|
||||||
|
tab-size: 4;
|
||||||
|
|
||||||
|
-webkit-hyphens: none;
|
||||||
|
-moz-hyphens: none;
|
||||||
|
-ms-hyphens: none;
|
||||||
|
hyphens: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
|
||||||
|
code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
|
||||||
|
text-shadow: none;
|
||||||
|
background: #b3d4fc;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
|
||||||
|
code[class*="language-"]::selection, code[class*="language-"] ::selection {
|
||||||
|
text-shadow: none;
|
||||||
|
background: #b3d4fc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
code[class*="language-"],
|
||||||
|
pre[class*="language-"] {
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code blocks */
|
||||||
|
pre[class*="language-"] {
|
||||||
|
padding: 1em;
|
||||||
|
margin: .5em 0;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
:not(pre) > code[class*="language-"],
|
||||||
|
pre[class*="language-"] {
|
||||||
|
background: #f5f2f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Inline code */
|
||||||
|
:not(pre) > code[class*="language-"] {
|
||||||
|
padding: .1em;
|
||||||
|
border-radius: .3em;
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.comment,
|
||||||
|
.token.prolog,
|
||||||
|
.token.doctype,
|
||||||
|
.token.cdata {
|
||||||
|
color: slategray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.punctuation {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.namespace {
|
||||||
|
opacity: .7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.property,
|
||||||
|
.token.tag,
|
||||||
|
.token.boolean,
|
||||||
|
.token.number,
|
||||||
|
.token.constant,
|
||||||
|
.token.symbol,
|
||||||
|
.token.deleted {
|
||||||
|
color: #905;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.selector,
|
||||||
|
.token.attr-name,
|
||||||
|
.token.string,
|
||||||
|
.token.char,
|
||||||
|
.token.builtin,
|
||||||
|
.token.inserted {
|
||||||
|
color: #690;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.operator,
|
||||||
|
.token.entity,
|
||||||
|
.token.url,
|
||||||
|
.language-css .token.string,
|
||||||
|
.style .token.string {
|
||||||
|
color: #9a6e3a;
|
||||||
|
/* This background color was intended by the author of this theme. */
|
||||||
|
background: hsla(0, 0%, 100%, .5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.atrule,
|
||||||
|
.token.attr-value,
|
||||||
|
.token.keyword {
|
||||||
|
color: #07a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.function,
|
||||||
|
.token.class-name {
|
||||||
|
color: #DD4A68;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.regex,
|
||||||
|
.token.important,
|
||||||
|
.token.variable {
|
||||||
|
color: #e90;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.important,
|
||||||
|
.token.bold {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.token.italic {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.entity {
|
||||||
|
cursor: help;
|
||||||
|
}
|
||||||
10
content/static/style.css
Normal file
10
content/static/style.css
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
body {
|
||||||
|
font-family: Helvetica;
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
-ms-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
88
deploy/about/index.html
Normal file
88
deploy/about/index.html
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en-US">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta content="#0e1112" media="(prefers-color-scheme: dark)" name="theme-color"/>
|
||||||
|
<meta content="#566B78" media="(prefers-color-scheme: light)" name="theme-color"/>
|
||||||
|
<meta content="Michael Housh" name="author"/>
|
||||||
|
<meta content="Mhoush" name="apple-mobile-web-app-title"/>
|
||||||
|
<meta content="initial-scale=1.0, width=device-width" name="viewport"/>
|
||||||
|
<meta content="telephone=no" name="format-detection"/>
|
||||||
|
<meta content="True" name="HandheldFriendly"/>
|
||||||
|
<meta content="320" name="MobileOptimized"/>
|
||||||
|
<meta content="Mhoush" name="og:site_name"/>
|
||||||
|
<meta content="hvac, developer, swift, home-performance, design" name="keywords"/>
|
||||||
|
<title>
|
||||||
|
mhoush: About - Michael Housh
|
||||||
|
</title>
|
||||||
|
<link href="/static/favicon.ico" rel="shortcut icon"/>
|
||||||
|
<link href="/static/output.css" rel="stylesheet"/>
|
||||||
|
<link href="/static/style.css" rel="stylesheet"/>
|
||||||
|
<link href="/articles/feed.xml" rel="alternate" title="mhoush" type="application/rss+xml"/>
|
||||||
|
</head>
|
||||||
|
<body class="bg-page text-white pb-5 font-avenir about">
|
||||||
|
<header class="bg-nav text-gray py-4 text-base/6 lg:fixed w-full lg:h-[62px]">
|
||||||
|
<nav class="container flex gap-x-5 lg:gap-x-y items-center">
|
||||||
|
<ul class="flex flex-wrap gap-x-2 lg:gap-x-5">
|
||||||
|
<li>
|
||||||
|
<a class href="/">Home</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class href="/articles/">Articles</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="active" href="/about/">About</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<div class="container pt-12 lg:pt-28">
|
||||||
|
<article>
|
||||||
|
<div class="prose">
|
||||||
|
<p>Michael is a third generation HVAC technician / owner located in Monroe, Ohio. He is the president<br />
|
||||||
|
of <a href="https://www.houshhomeenergy.com">Housh - The Home Energy Experts</a>, where they focus on high<br />
|
||||||
|
performance HVAC systems, indoor air quality, and home performance upgrades.</p>
|
||||||
|
<p>Michael is passionate about helping the HVAC trade grow in skill and integrity. He is also<br />
|
||||||
|
passionate about programming solutions (primarily in Swift) for the HVAC industry to automate his<br />
|
||||||
|
business and help others automate theirs.</p>
|
||||||
|
<p>Michael likes to think deeply about where the industry has been and where it is going. Coming up<br />
|
||||||
|
with innovative solutions to common problems that are faced, with a primary focus on residential<br />
|
||||||
|
HVAC and Home Performance.</p>
|
||||||
|
<p><strong>Michael’s Favorite Quote:</strong></p>
|
||||||
|
<pre><code>Integrity is doing the right thing, even when no one is watching!
|
||||||
|
|
||||||
|
~ C.S. Lewis
|
||||||
|
</code></pre>
|
||||||
|
<p>Michael is a proud contributor to many online groups / podcasts:</p>
|
||||||
|
<pre><code>HVAC School
|
||||||
|
The HVAC Grapevine
|
||||||
|
HVAC Overtime
|
||||||
|
</code></pre>
|
||||||
|
<p>Michael’s PGP Fingerprint</p>
|
||||||
|
<p>B86F487BF0A715D016DB140A37F1B52C60D8C24B</p>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
<div class="site-footer container text-gray gray-links border-t border-light text-center pt-6 mt-8 text-sm">
|
||||||
|
<p>
|
||||||
|
Copyright © Michael Housh 2023-2025.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Built in Swift using
|
||||||
|
<a href="https://github.com/loopwerk/Saga" rel="nofollow" target="_blank">Saga</a>
|
||||||
|
(<a href="https://github.com/m-housh/mhoush.com" rel="nofollow" target="_blank">source</a>).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="http://localhost:3000/articles/feed.xml" rel="nofollow" target="_blank">RSS</a>
|
||||||
|
|
|
||||||
|
<a href="https://github.com/m-housh" rel="nofollow" target="_blank">Github</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.youtube.com/channel/UCb58SeURd5bObfTiL0KoliA" rel="nofollow" target="_blank">Youtube</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.facebook.com/michael.housh" rel="nofollow" target="_blank">Facebook</a>
|
||||||
|
|
|
||||||
|
<a href="mailto:michael@mhoush.com" rel="nofollow">Email</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,193 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en-US">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta content="#0e1112" media="(prefers-color-scheme: dark)" name="theme-color"/>
|
||||||
|
<meta content="#566B78" media="(prefers-color-scheme: light)" name="theme-color"/>
|
||||||
|
<meta content="Michael Housh" name="author"/>
|
||||||
|
<meta content="Mhoush" name="apple-mobile-web-app-title"/>
|
||||||
|
<meta content="initial-scale=1.0, width=device-width" name="viewport"/>
|
||||||
|
<meta content="telephone=no" name="format-detection"/>
|
||||||
|
<meta content="True" name="HandheldFriendly"/>
|
||||||
|
<meta content="320" name="MobileOptimized"/>
|
||||||
|
<meta content="Mhoush" name="og:site_name"/>
|
||||||
|
<meta content="hvac, developer, swift, home-performance, design" name="keywords"/>
|
||||||
|
<title>
|
||||||
|
mhoush: Calculate SEER Degradation by Age
|
||||||
|
</title>
|
||||||
|
<link href="/static/favicon.ico" rel="shortcut icon"/>
|
||||||
|
<link href="/static/output.css" rel="stylesheet"/>
|
||||||
|
<link href="/static/style.css" rel="stylesheet"/>
|
||||||
|
<link href="/articles/feed.xml" rel="alternate" title="mhoush" type="application/rss+xml"/>
|
||||||
|
<link href="/static/prism.css" rel="stylesheet"/>
|
||||||
|
<meta content="This is a quick tech-tip to learn how to calculate the degradation of SEER based
|
||||||
|
on age.
|
||||||
|
The degradation of SEER is due to fouling of the evaporator coil with dirt and
|
||||||
|
refrigerant charge losses. It should be noted that this is not true for..." name="description"/>
|
||||||
|
<meta content="summary_large_image" name="twitter:card"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images/2023-09-19-calculate-seer-degradation-by-age.png" name="twitter:image"/>
|
||||||
|
<meta content="Calculate SEER Degradation by Age" name="twitter:image:alt"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images//articles/2023/calculate-seer-degradation-by-age/" name="og:url"/>
|
||||||
|
<meta content="Calculate SEER Degradation by Age" name="og:title"/>
|
||||||
|
<meta content="This is a quick tech-tip to learn how to calculate the degradation of SEER based
|
||||||
|
on age.
|
||||||
|
The degradation of SEER is due to fouling of the evaporator coil with dirt and
|
||||||
|
refrigerant charge losses. It should be noted that this is not true for..." name="og:description"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images/2023-09-19-calculate-seer-degradation-by-age.png" name="og:image"/>
|
||||||
|
<meta content="1014" name="og:image:width"/>
|
||||||
|
<meta content="530" name="og:image:height"/>
|
||||||
|
<script crossorigin="anonymous" src="https://kit.fontawesome.com/f209982030.js">
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body class="bg-page text-white pb-5 font-avenir articles">
|
||||||
|
<header class="bg-nav text-gray py-4 text-base/6 lg:fixed w-full lg:h-[62px]">
|
||||||
|
<nav class="container flex gap-x-5 lg:gap-x-y items-center">
|
||||||
|
<ul class="flex flex-wrap gap-x-2 lg:gap-x-5">
|
||||||
|
<li>
|
||||||
|
<a class href="/">Home</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="active" href="/articles/">Articles</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class href="/about/">About</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<div class="container pt-12 lg:pt-28">
|
||||||
|
<article class="prose">
|
||||||
|
<h1>
|
||||||
|
Calculate SEER Degradation by Age
|
||||||
|
</h1>
|
||||||
|
<div class="-mt-6">
|
||||||
|
<div class="text-gray gray-links text-sm">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">September 19, 2023</span>395 words, posted in <a href="/articles/tag/hvac/">HVAC</a>, <a href="/articles/tag/formulas/">formulas</a> and <a href="/articles/tag/tech-tip/">tech-tip</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2023-09-19-calculate-seer-degradation-by-age.png"/>
|
||||||
|
<p>This is a quick tech-tip to learn how to calculate the degradation of SEER based<br />
|
||||||
|
on age.</p>
|
||||||
|
<p>The degradation of SEER is due to fouling of the evaporator coil with dirt and<br />
|
||||||
|
refrigerant charge losses. It should be noted that this is not true for all<br />
|
||||||
|
applications, but is used as an estimation based on research done by the <code>DOE</code><br />
|
||||||
|
of the average degradation based on systems tested.</p>
|
||||||
|
<h2>Formula</h2>
|
||||||
|
<p>This is the formula used to calculate the SEER based on age of the evaporator<br />
|
||||||
|
coil / air handler.</p>
|
||||||
|
<p>$$ SEER_d = SEER_n \times (1 - M)^{age} $$</p>
|
||||||
|
<p>| Where | |<br />
|
||||||
|
| –––– | —————————————— | — |<br />
|
||||||
|
| $SEER_d$ | Degradated SEER rating |<br />
|
||||||
|
| $SEER_n$ | Nominal SEER rating when equipment was new | |<br />
|
||||||
|
| M | Maintenance factor, 0.01-0.03 |<br />
|
||||||
|
| age | The age of the equipment, in years |</p>
|
||||||
|
<p>The maintenance factor of 0.01 is for expertly maintained equipment and 0.03 is<br />
|
||||||
|
for unmaintained. The maintenance factor in essence is based on 1%-3%<br />
|
||||||
|
degradation per year, however there are some<br />
|
||||||
|
<a href="https://publications.energyresearch.ucf.edu/wp-content/uploads/2018/09/FSEC-PF-474-18.pdf">studies</a><br />
|
||||||
|
that show that this can actually be as high as 5% or above depending on climate.<br />
|
||||||
|
We could use up to 0.05 as the maintenance factor, just to see what the “range”<br />
|
||||||
|
of degradation would be.</p>
|
||||||
|
<p>Interestingly, the study linked also shows that the degradation is higher the<br />
|
||||||
|
higher the tonnage of the equipment. It also shows that the degradation is lower<br />
|
||||||
|
per year the higher the nominal SEER rating of the system (which is corelated to<br />
|
||||||
|
using TXV’s and lower airflow rates because of the equipment having multiple<br />
|
||||||
|
stages).</p>
|
||||||
|
<h2>Example</h2>
|
||||||
|
<p>Let’s consider that we have a 13 SEER piece of equipment that was matched when<br />
|
||||||
|
installed and the system is 15 years old.</p>
|
||||||
|
<p>Plugging those numbers into our formula.</p>
|
||||||
|
<hr />
|
||||||
|
<h4>Lowest Range (1% degradation / year)</h4>
|
||||||
|
<p>$$ SEER_d = 13 \times (1 - 0.01)^{15} = 11.2 $$</p>
|
||||||
|
<hr />
|
||||||
|
<h4>Highest Rage (5% degradation / year)</h4>
|
||||||
|
<p>$$ SEER_d = 13 \times (1 - 0.05)^{15} = 6 $$</p>
|
||||||
|
<hr />
|
||||||
|
<p>An expertly maintained system may not have degraded that much, with an 11.2 SEER<br />
|
||||||
|
vs. a poorly maintained / dirty system that also suffers from refrigerant charge<br />
|
||||||
|
losses can be as low as 6 SEER.</p>
|
||||||
|
<p>Thanks for learning how to estimate SEER degradation based on equipment age!</p>
|
||||||
|
</article>
|
||||||
|
<div class="border-t border-light mt-8 pt-8">
|
||||||
|
<h2 class="text-4xl font-extrabold mb-8">
|
||||||
|
Written by
|
||||||
|
</h2>
|
||||||
|
<div class="flex flex-col lg:flex-row gap-8">
|
||||||
|
<div class="flex-[0_0_120px]">
|
||||||
|
<img class="w-[120px] h-[120px] rounded-full" src="/static/images/avatar.png"/>
|
||||||
|
</div>
|
||||||
|
<div class="prose">
|
||||||
|
<h3 class="!m-0">
|
||||||
|
Michael Housh
|
||||||
|
</h3>
|
||||||
|
<p class="text-gray">
|
||||||
|
HVAC business owner with over 27 years of experience. Writes articles about HVAC,
|
||||||
|
Programming, Home-Performance, and Building Science
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-16">
|
||||||
|
<h2 class="text-4xl font-extrabold mb-8">
|
||||||
|
More articles
|
||||||
|
</h2>
|
||||||
|
<div class="grid lg:grid-cols-2 gap-10">
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2025/vapor-htmx-todo-app/">Vapor + HTMX</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">January 05, 2025</span><a href="/articles/tag/general/">general</a>, <a href="/articles/tag/programming/">programming</a> and <a href="/articles/tag/software/">software</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2025/vapor-htmx-todo-app/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2025-01-05-vapor-htmx-todo-app.png"/>
|
||||||
|
Build an example application using Vapor and HTMX.
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2024/free-as-in-freedom/">Free As In Freedom</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">April 09, 2024</span><a href="/articles/tag/general/">general</a>, <a href="/articles/tag/open-source/">open-source</a> and <a href="/articles/tag/software/">software</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2024/free-as-in-freedom/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2024-04-09-free-as-in-freedom.png"/>
|
||||||
|
Salute to open-source software engineers
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<p class="prose mt-8">
|
||||||
|
<a href="/articles/">› See all articles</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="site-footer container text-gray gray-links border-t border-light text-center pt-6 mt-8 text-sm">
|
||||||
|
<p>
|
||||||
|
Copyright © Michael Housh 2023-2025.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Built in Swift using
|
||||||
|
<a href="https://github.com/loopwerk/Saga" rel="nofollow" target="_blank">Saga</a>
|
||||||
|
(<a href="https://github.com/m-housh/mhoush.com" rel="nofollow" target="_blank">source</a>).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="http://localhost:3000/articles/feed.xml" rel="nofollow" target="_blank">RSS</a>
|
||||||
|
|
|
||||||
|
<a href="https://github.com/m-housh" rel="nofollow" target="_blank">Github</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.youtube.com/channel/UCb58SeURd5bObfTiL0KoliA" rel="nofollow" target="_blank">Youtube</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.facebook.com/michael.housh" rel="nofollow" target="_blank">Facebook</a>
|
||||||
|
|
|
||||||
|
<a href="mailto:michael@mhoush.com" rel="nofollow">Email</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
195
deploy/articles/2023/cancel-this/index.html
Normal file
195
deploy/articles/2023/cancel-this/index.html
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en-US">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta content="#0e1112" media="(prefers-color-scheme: dark)" name="theme-color"/>
|
||||||
|
<meta content="#566B78" media="(prefers-color-scheme: light)" name="theme-color"/>
|
||||||
|
<meta content="Michael Housh" name="author"/>
|
||||||
|
<meta content="Mhoush" name="apple-mobile-web-app-title"/>
|
||||||
|
<meta content="initial-scale=1.0, width=device-width" name="viewport"/>
|
||||||
|
<meta content="telephone=no" name="format-detection"/>
|
||||||
|
<meta content="True" name="HandheldFriendly"/>
|
||||||
|
<meta content="320" name="MobileOptimized"/>
|
||||||
|
<meta content="Mhoush" name="og:site_name"/>
|
||||||
|
<meta content="hvac, developer, swift, home-performance, design" name="keywords"/>
|
||||||
|
<title>
|
||||||
|
mhoush: Cancel This
|
||||||
|
</title>
|
||||||
|
<link href="/static/favicon.ico" rel="shortcut icon"/>
|
||||||
|
<link href="/static/output.css" rel="stylesheet"/>
|
||||||
|
<link href="/static/style.css" rel="stylesheet"/>
|
||||||
|
<link href="/articles/feed.xml" rel="alternate" title="mhoush" type="application/rss+xml"/>
|
||||||
|
<link href="/static/prism.css" rel="stylesheet"/>
|
||||||
|
<meta content="This post is going to be hard to put into words, it’s going to seem egotistical at points, but know
|
||||||
|
that my actions / feelings online are the same as they are if you met me in person. The problem with
|
||||||
|
online interactions is tone and other subtleties..." name="description"/>
|
||||||
|
<meta content="summary_large_image" name="twitter:card"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images/2023-12-12-cancel-this.gif" name="twitter:image"/>
|
||||||
|
<meta content="Cancel This" name="twitter:image:alt"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images//articles/2023/cancel-this/" name="og:url"/>
|
||||||
|
<meta content="Cancel This" name="og:title"/>
|
||||||
|
<meta content="This post is going to be hard to put into words, it’s going to seem egotistical at points, but know
|
||||||
|
that my actions / feelings online are the same as they are if you met me in person. The problem with
|
||||||
|
online interactions is tone and other subtleties..." name="og:description"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images/2023-12-12-cancel-this.gif" name="og:image"/>
|
||||||
|
<meta content="1014" name="og:image:width"/>
|
||||||
|
<meta content="530" name="og:image:height"/>
|
||||||
|
<script crossorigin="anonymous" src="https://kit.fontawesome.com/f209982030.js">
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body class="bg-page text-white pb-5 font-avenir articles">
|
||||||
|
<header class="bg-nav text-gray py-4 text-base/6 lg:fixed w-full lg:h-[62px]">
|
||||||
|
<nav class="container flex gap-x-5 lg:gap-x-y items-center">
|
||||||
|
<ul class="flex flex-wrap gap-x-2 lg:gap-x-5">
|
||||||
|
<li>
|
||||||
|
<a class href="/">Home</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="active" href="/articles/">Articles</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class href="/about/">About</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<div class="container pt-12 lg:pt-28">
|
||||||
|
<article class="prose">
|
||||||
|
<h1>
|
||||||
|
Cancel This
|
||||||
|
</h1>
|
||||||
|
<div class="-mt-6">
|
||||||
|
<div class="text-gray gray-links text-sm">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">December 12, 2023</span>758 words, posted in <a href="/articles/tag/hvac/">HVAC</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2023-12-12-cancel-this.gif"/>
|
||||||
|
<p>This post is going to be hard to put into words, it’s going to seem egotistical at points, but know<br />
|
||||||
|
that my actions / feelings online are the same as they are if you met me in person. The problem with<br />
|
||||||
|
online interactions is tone and other subtleties do not come across, so it’s hard to tell when<br />
|
||||||
|
someone is joking or being serious.</p>
|
||||||
|
<h2>The Meat</h2>
|
||||||
|
<p>It has been brought to my attention that someone out there thinks that I’m sexist and should not<br />
|
||||||
|
speak at the HVAC School symposium because of it. They are holding a curse word against me that I<br />
|
||||||
|
said two years ago, in the moment A) it was fitting and B) it was one of those times that my mouth<br />
|
||||||
|
was working faster than my brain (raise your hand if that’s ever happened to you).</p>
|
||||||
|
<p>I am an open book, I am not afraid of showing failures and strengths. I’ve never claimed to be<br />
|
||||||
|
perfect (well, actually I have but it’s always a joke). I’m not at all condoning what I’ve said in<br />
|
||||||
|
the past, nor will I repeat it out of context now, but I communicate with people like adults and I<br />
|
||||||
|
look at people as piers. We do not always have to agree with one another, conflict helps us learn<br />
|
||||||
|
where to grow, but we also can not expect people to change to fit our wants / needs, that’s just not<br />
|
||||||
|
how it works.</p>
|
||||||
|
<p>I do not at all agree with the tactics used by whomever is behind this. I would happily discuss this<br />
|
||||||
|
in private or out in the open. You can find all my contact / social information in the sidebar of<br />
|
||||||
|
this website and I’ve offered up my cell phone number in private groups that we are all probably a<br />
|
||||||
|
part of.</p>
|
||||||
|
<h2>The Potatoes</h2>
|
||||||
|
<p>I am a father of 3 girls, I have a sister, talk crap about my mom and you’ll find out who I am! I<br />
|
||||||
|
love women, I have no problem with women in the trades, I encourage women who are in the trades. I<br />
|
||||||
|
try to help every person that I can, if I can. I have failed more times than you can imagine! I am<br />
|
||||||
|
self taught in about everything I do, so I give of it freely. I have all kinds of work to do to grow<br />
|
||||||
|
into the man that I should be, but at the same time, I am not afraid to be the man that I am today.<br />
|
||||||
|
I will greet you by whatever pronoun you want to be referred as.</p>
|
||||||
|
<p>I would love to say that I don’t judge people, but I do, just as I’m being judged! I am fine with<br />
|
||||||
|
someone judging me and having opinions about me, I mean that is our right. I will not say that<br />
|
||||||
|
person is wrong, because in their mind they’re right. What I will not do is stop being myself. I<br />
|
||||||
|
know for a fact that I’ve helped more people than this person has gotten “cancelled”. I will<br />
|
||||||
|
continue to help people in the trades, homeowners, or people in need. I also will not remain quiet!<br />
|
||||||
|
I will give my opinion like it or not. There are people in my corner that really know me and my<br />
|
||||||
|
intentions.</p>
|
||||||
|
<h2>Final Words</h2>
|
||||||
|
<p>The trades are rough around the edges, just as am I. The trades are a slow turning ship (just look<br />
|
||||||
|
at how many still do not follow proper practices, etc. even with the capabilities and resources<br />
|
||||||
|
available today).</p>
|
||||||
|
<p>If you are new / coming into the trades then I hope you are not overly sensitive to foul language<br />
|
||||||
|
and other inappropriate comments. Thick skin is valuable in the trades, but at the same time don’t<br />
|
||||||
|
be afraid to speak up if something offends you. Remember we are adults, we can handle disagreements<br />
|
||||||
|
like adults (well, some of us can). Adults can learn from those of any age, they can reflect on<br />
|
||||||
|
their own behavior and make their own decisions.</p>
|
||||||
|
<p>I personally think that being offended is not a bad thing, it causes us to reflect / repair our<br />
|
||||||
|
foundational beliefs. I hope that we can stop with this “cancel culture” of today, stop hiding<br />
|
||||||
|
behind a keyboard, and be a diverse community.</p>
|
||||||
|
<p>To wrap things up, I just want to reiterate that I am not at all mad at whomever is behind this. To<br />
|
||||||
|
everyone out there who has shown me love and support, I greatly appreciate it.</p>
|
||||||
|
</article>
|
||||||
|
<div class="border-t border-light mt-8 pt-8">
|
||||||
|
<h2 class="text-4xl font-extrabold mb-8">
|
||||||
|
Written by
|
||||||
|
</h2>
|
||||||
|
<div class="flex flex-col lg:flex-row gap-8">
|
||||||
|
<div class="flex-[0_0_120px]">
|
||||||
|
<img class="w-[120px] h-[120px] rounded-full" src="/static/images/avatar.png"/>
|
||||||
|
</div>
|
||||||
|
<div class="prose">
|
||||||
|
<h3 class="!m-0">
|
||||||
|
Michael Housh
|
||||||
|
</h3>
|
||||||
|
<p class="text-gray">
|
||||||
|
HVAC business owner with over 27 years of experience. Writes articles about HVAC,
|
||||||
|
Programming, Home-Performance, and Building Science
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-16">
|
||||||
|
<h2 class="text-4xl font-extrabold mb-8">
|
||||||
|
More articles
|
||||||
|
</h2>
|
||||||
|
<div class="grid lg:grid-cols-2 gap-10">
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2025/vapor-htmx-todo-app/">Vapor + HTMX</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">January 05, 2025</span><a href="/articles/tag/general/">general</a>, <a href="/articles/tag/programming/">programming</a> and <a href="/articles/tag/software/">software</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2025/vapor-htmx-todo-app/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2025-01-05-vapor-htmx-todo-app.png"/>
|
||||||
|
Build an example application using Vapor and HTMX.
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2024/free-as-in-freedom/">Free As In Freedom</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">April 09, 2024</span><a href="/articles/tag/general/">general</a>, <a href="/articles/tag/open-source/">open-source</a> and <a href="/articles/tag/software/">software</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2024/free-as-in-freedom/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2024-04-09-free-as-in-freedom.png"/>
|
||||||
|
Salute to open-source software engineers
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<p class="prose mt-8">
|
||||||
|
<a href="/articles/">› See all articles</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="site-footer container text-gray gray-links border-t border-light text-center pt-6 mt-8 text-sm">
|
||||||
|
<p>
|
||||||
|
Copyright © Michael Housh 2023-2025.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Built in Swift using
|
||||||
|
<a href="https://github.com/loopwerk/Saga" rel="nofollow" target="_blank">Saga</a>
|
||||||
|
(<a href="https://github.com/m-housh/mhoush.com" rel="nofollow" target="_blank">source</a>).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="http://localhost:3000/articles/feed.xml" rel="nofollow" target="_blank">RSS</a>
|
||||||
|
|
|
||||||
|
<a href="https://github.com/m-housh" rel="nofollow" target="_blank">Github</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.youtube.com/channel/UCb58SeURd5bObfTiL0KoliA" rel="nofollow" target="_blank">Youtube</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.facebook.com/michael.housh" rel="nofollow" target="_blank">Facebook</a>
|
||||||
|
|
|
||||||
|
<a href="mailto:michael@mhoush.com" rel="nofollow">Email</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
223
deploy/articles/2023/heat-recovery-chiller/index.html
Normal file
223
deploy/articles/2023/heat-recovery-chiller/index.html
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en-US">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta content="#0e1112" media="(prefers-color-scheme: dark)" name="theme-color"/>
|
||||||
|
<meta content="#566B78" media="(prefers-color-scheme: light)" name="theme-color"/>
|
||||||
|
<meta content="Michael Housh" name="author"/>
|
||||||
|
<meta content="Mhoush" name="apple-mobile-web-app-title"/>
|
||||||
|
<meta content="initial-scale=1.0, width=device-width" name="viewport"/>
|
||||||
|
<meta content="telephone=no" name="format-detection"/>
|
||||||
|
<meta content="True" name="HandheldFriendly"/>
|
||||||
|
<meta content="320" name="MobileOptimized"/>
|
||||||
|
<meta content="Mhoush" name="og:site_name"/>
|
||||||
|
<meta content="hvac, developer, swift, home-performance, design" name="keywords"/>
|
||||||
|
<title>
|
||||||
|
mhoush: Heat Recovery Chiller
|
||||||
|
</title>
|
||||||
|
<link href="/static/favicon.ico" rel="shortcut icon"/>
|
||||||
|
<link href="/static/output.css" rel="stylesheet"/>
|
||||||
|
<link href="/static/style.css" rel="stylesheet"/>
|
||||||
|
<link href="/articles/feed.xml" rel="alternate" title="mhoush" type="application/rss+xml"/>
|
||||||
|
<link href="/static/prism.css" rel="stylesheet"/>
|
||||||
|
<meta content="This is an article that I wrote back in 2020, but I don’t believe that I published it anywhere, so
|
||||||
|
I’m doing it now. I did discuss this on
|
||||||
|
this episode of the HVAC School Podcast.
|
||||||
|
Heat Recovery Chillers
|
||||||
|
I have always had a love and passion for..." name="description"/>
|
||||||
|
<meta content="summary_large_image" name="twitter:card"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images/2023-10-27-heat-recovery-chiller.png" name="twitter:image"/>
|
||||||
|
<meta content="Heat Recovery Chiller" name="twitter:image:alt"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images//articles/2023/heat-recovery-chiller/" name="og:url"/>
|
||||||
|
<meta content="Heat Recovery Chiller" name="og:title"/>
|
||||||
|
<meta content="This is an article that I wrote back in 2020, but I don’t believe that I published it anywhere, so
|
||||||
|
I’m doing it now. I did discuss this on
|
||||||
|
this episode of the HVAC School Podcast.
|
||||||
|
Heat Recovery Chillers
|
||||||
|
I have always had a love and passion for..." name="og:description"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images/2023-10-27-heat-recovery-chiller.png" name="og:image"/>
|
||||||
|
<meta content="1014" name="og:image:width"/>
|
||||||
|
<meta content="530" name="og:image:height"/>
|
||||||
|
<script crossorigin="anonymous" src="https://kit.fontawesome.com/f209982030.js">
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body class="bg-page text-white pb-5 font-avenir articles">
|
||||||
|
<header class="bg-nav text-gray py-4 text-base/6 lg:fixed w-full lg:h-[62px]">
|
||||||
|
<nav class="container flex gap-x-5 lg:gap-x-y items-center">
|
||||||
|
<ul class="flex flex-wrap gap-x-2 lg:gap-x-5">
|
||||||
|
<li>
|
||||||
|
<a class href="/">Home</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="active" href="/articles/">Articles</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class href="/about/">About</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<div class="container pt-12 lg:pt-28">
|
||||||
|
<article class="prose">
|
||||||
|
<h1>
|
||||||
|
Heat Recovery Chiller
|
||||||
|
</h1>
|
||||||
|
<div class="-mt-6">
|
||||||
|
<div class="text-gray gray-links text-sm">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">October 27, 2023</span>811 words, posted in <a href="/articles/tag/hvac/">HVAC</a>, <a href="/articles/tag/chiller/">chiller</a> and <a href="/articles/tag/hydronics/">hydronics</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2023-10-27-heat-recovery-chiller.png"/>
|
||||||
|
<p>This is an article that I wrote back in 2020, but I don’t believe that I published it anywhere, so<br />
|
||||||
|
I’m doing it now. I did discuss this on<br />
|
||||||
|
<a href="https://hvacrschool.com/podcasts/is-the-future-of-air-conditioning-self-contained-propane-chillers/">this episode of the HVAC School Podcast.</a></p>
|
||||||
|
<h2>Heat Recovery Chillers</h2>
|
||||||
|
<p>I have always had a love and passion for hydronic systems, perhaps it’s because they are not that<br />
|
||||||
|
common in most areas. The designs tend to be elegant and the flexibility is unparalleled by most<br />
|
||||||
|
equipment choices currently available in the U.S. I’m going to try to not get too far into the weeds<br />
|
||||||
|
in this article, but offer an overview of what I feel would be my dream system.</p>
|
||||||
|
<h2>The Source</h2>
|
||||||
|
<p>A heat recovery chiller will do simultaneous heating and cooling, as opposed to a traditional<br />
|
||||||
|
heat-pump or reverse cycle chiller that can only operate in one mode at a time. This system would<br />
|
||||||
|
have a second refrigerant to water heat exchanger and utilize the air-source when we don’t need to<br />
|
||||||
|
bank / store heat, or are running in heat only mode. There are several benefits to this style<br />
|
||||||
|
system, the main being that while operating simultaneous heating / cooling mode the COP of the<br />
|
||||||
|
system doubles. For example, the <a href="https://multiaqua.com/mhrc2/">Multi-Aqua MHRC2</a> shows a COP of<br />
|
||||||
|
about 8, which is approximately equivalent to 30 EER or 34 SEER. This gives us geothermal level<br />
|
||||||
|
performance without the need of a field.</p>
|
||||||
|
<h2>Indoor Portion</h2>
|
||||||
|
<p>The indoor portion of the system, we would utilize buffer tanks as thermal storage for the chiller.<br />
|
||||||
|
The buffer tanks give us several benefits, including longer run times for the chiller, load<br />
|
||||||
|
matching, and the ability to size for larger load (heating or cooling) without some of the problems<br />
|
||||||
|
that occur when over-sizing a traditional system. The buffer tanks also allow sizing more<br />
|
||||||
|
aggressively by having storage during peak load conditions.</p>
|
||||||
|
<p><img src="/articles/images/2023-10-27-buffers2.png" alt="buffer" /></p>
|
||||||
|
<p>This shows a cooling buffer tank as well as a heating buffer tank. The horizontal pumps are what<br />
|
||||||
|
circulate water through the chiller, while the vertical pumps are what distribute the water to the<br />
|
||||||
|
load / emitters. This configuration allows for water to be used for the loads first and extra<br />
|
||||||
|
capacity to go into the buffer tanks. The buffer tanks also offer hydraulic separation for the pumps<br />
|
||||||
|
(meaning that they won’t interfere with each other if / when there are different flow rates).<br />
|
||||||
|
Another advantage of the buffer tanks is that you can connect multiple heating or cooling sources in<br />
|
||||||
|
parallel to the system. This is shown by the extra tees in the hot buffer tank where we could<br />
|
||||||
|
connect something such as solar water collectors, pellet or wood boiler, or a conventional boiler.<br />
|
||||||
|
You’ll also notice on the right side of the hot buffer tank, that I am showing a brazed plate heat<br />
|
||||||
|
exchanger that would be used to supply domestic hot water.</p>
|
||||||
|
<h2>Distribution System</h2>
|
||||||
|
<p>This could be a number of things, from radiant panels, in-floor, high-output baseboard radiators,<br />
|
||||||
|
however I’m going to model it as a 4-pipe hydronic air handler.</p>
|
||||||
|
<p><img src="/articles/images/2023-10-27-ah.png" alt="ah" /></p>
|
||||||
|
<p>The hydronic air handler is able to provide cooling, heating, and re-heat dehumidification, all in<br />
|
||||||
|
one package. With a hydronic system, it would be very easy to load match by controlling the fan<br />
|
||||||
|
speed and utilizing a Delta-T pump or outdoor reset controls. These air handlers are available from<br />
|
||||||
|
several manufacturers and come in different styles from traditional (as shown), small duct high<br />
|
||||||
|
velocity systems, and even ductless styles.</p>
|
||||||
|
<h2>Disadvantages</h2>
|
||||||
|
<ol>
|
||||||
|
<li>Not highly available in the U.S.</li>
|
||||||
|
<li>When the chiller is down nothing works (not much different than traditional)</li>
|
||||||
|
<li>Lack of understanding / technicians afraid to work on this style system.</li>
|
||||||
|
<li>Potentially higher upfront costs.</li>
|
||||||
|
<li>Lack of design or planning could cause unhappy clients (same with traditional)</li>
|
||||||
|
<li>Distribution systems need to be designed around low water temperatures (not a drop in replacement<br />
|
||||||
|
for traditional boiler systems)</li>
|
||||||
|
</ol>
|
||||||
|
<h2>Advantages</h2>
|
||||||
|
<ol>
|
||||||
|
<li>Central plant for heating, cooling, and DHW (also a disadvantage)</li>
|
||||||
|
<li>Flexible distribution options / methods.</li>
|
||||||
|
<li>Self contained refrigerant circuit</li>
|
||||||
|
<li>Ability to produce / store thermal energy during off peak electrical hours</li>
|
||||||
|
<li>Ability to move BTU’s more efficiently through water than air</li>
|
||||||
|
<li>Long life for distribution system (50-100+ years)</li>
|
||||||
|
<li>Easier transition to natural / flammable refrigerants</li>
|
||||||
|
</ol>
|
||||||
|
<h2>Conclusion</h2>
|
||||||
|
<p>In conclusion, there are many advantages to this style system, as well as disadvantages. One of the<br />
|
||||||
|
main points is to think of the system in 3 distinct components, the source(s), thermal storage, and<br />
|
||||||
|
distribution. As mentioned, this only one concept, but in reality, there are many ways to accomplish<br />
|
||||||
|
this, which is one of it’s advantages. For example, perhaps in certain scenarios it makes sense to<br />
|
||||||
|
dump excess heat into a pool, create ice storage during off peak hours, cascade into another water<br />
|
||||||
|
-> water heat pump for higher temperature distribution, incorporate solar collectors, and so on.</p>
|
||||||
|
<p>Thank you for reading all the way to the end!</p>
|
||||||
|
</article>
|
||||||
|
<div class="border-t border-light mt-8 pt-8">
|
||||||
|
<h2 class="text-4xl font-extrabold mb-8">
|
||||||
|
Written by
|
||||||
|
</h2>
|
||||||
|
<div class="flex flex-col lg:flex-row gap-8">
|
||||||
|
<div class="flex-[0_0_120px]">
|
||||||
|
<img class="w-[120px] h-[120px] rounded-full" src="/static/images/avatar.png"/>
|
||||||
|
</div>
|
||||||
|
<div class="prose">
|
||||||
|
<h3 class="!m-0">
|
||||||
|
Michael Housh
|
||||||
|
</h3>
|
||||||
|
<p class="text-gray">
|
||||||
|
HVAC business owner with over 27 years of experience. Writes articles about HVAC,
|
||||||
|
Programming, Home-Performance, and Building Science
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-16">
|
||||||
|
<h2 class="text-4xl font-extrabold mb-8">
|
||||||
|
More articles
|
||||||
|
</h2>
|
||||||
|
<div class="grid lg:grid-cols-2 gap-10">
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2025/vapor-htmx-todo-app/">Vapor + HTMX</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">January 05, 2025</span><a href="/articles/tag/general/">general</a>, <a href="/articles/tag/programming/">programming</a> and <a href="/articles/tag/software/">software</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2025/vapor-htmx-todo-app/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2025-01-05-vapor-htmx-todo-app.png"/>
|
||||||
|
Build an example application using Vapor and HTMX.
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2024/free-as-in-freedom/">Free As In Freedom</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">April 09, 2024</span><a href="/articles/tag/general/">general</a>, <a href="/articles/tag/open-source/">open-source</a> and <a href="/articles/tag/software/">software</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2024/free-as-in-freedom/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2024-04-09-free-as-in-freedom.png"/>
|
||||||
|
Salute to open-source software engineers
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<p class="prose mt-8">
|
||||||
|
<a href="/articles/">› See all articles</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="site-footer container text-gray gray-links border-t border-light text-center pt-6 mt-8 text-sm">
|
||||||
|
<p>
|
||||||
|
Copyright © Michael Housh 2023-2025.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Built in Swift using
|
||||||
|
<a href="https://github.com/loopwerk/Saga" rel="nofollow" target="_blank">Saga</a>
|
||||||
|
(<a href="https://github.com/m-housh/mhoush.com" rel="nofollow" target="_blank">source</a>).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="http://localhost:3000/articles/feed.xml" rel="nofollow" target="_blank">RSS</a>
|
||||||
|
|
|
||||||
|
<a href="https://github.com/m-housh" rel="nofollow" target="_blank">Github</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.youtube.com/channel/UCb58SeURd5bObfTiL0KoliA" rel="nofollow" target="_blank">Youtube</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.facebook.com/michael.housh" rel="nofollow" target="_blank">Facebook</a>
|
||||||
|
|
|
||||||
|
<a href="mailto:michael@mhoush.com" rel="nofollow">Email</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
195
deploy/articles/2023/hope/index.html
Normal file
195
deploy/articles/2023/hope/index.html
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en-US">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta content="#0e1112" media="(prefers-color-scheme: dark)" name="theme-color"/>
|
||||||
|
<meta content="#566B78" media="(prefers-color-scheme: light)" name="theme-color"/>
|
||||||
|
<meta content="Michael Housh" name="author"/>
|
||||||
|
<meta content="Mhoush" name="apple-mobile-web-app-title"/>
|
||||||
|
<meta content="initial-scale=1.0, width=device-width" name="viewport"/>
|
||||||
|
<meta content="telephone=no" name="format-detection"/>
|
||||||
|
<meta content="True" name="HandheldFriendly"/>
|
||||||
|
<meta content="320" name="MobileOptimized"/>
|
||||||
|
<meta content="Mhoush" name="og:site_name"/>
|
||||||
|
<meta content="hvac, developer, swift, home-performance, design" name="keywords"/>
|
||||||
|
<title>
|
||||||
|
mhoush: Hope
|
||||||
|
</title>
|
||||||
|
<link href="/static/favicon.ico" rel="shortcut icon"/>
|
||||||
|
<link href="/static/output.css" rel="stylesheet"/>
|
||||||
|
<link href="/static/style.css" rel="stylesheet"/>
|
||||||
|
<link href="/articles/feed.xml" rel="alternate" title="mhoush" type="application/rss+xml"/>
|
||||||
|
<link href="/static/prism.css" rel="stylesheet"/>
|
||||||
|
<meta content="This is a piggy-back article off of
|
||||||
|
The Struggle article that I had recently.
|
||||||
|
I was a bit of a “Debbie Downer” in that article, which is okay, I get that way sometimes. In this
|
||||||
|
article I’d like to take a minute to layout some of the things that give..." name="description"/>
|
||||||
|
<meta content="summary_large_image" name="twitter:card"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images/2023-10-30-hope.png" name="twitter:image"/>
|
||||||
|
<meta content="Hope" name="twitter:image:alt"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images//articles/2023/hope/" name="og:url"/>
|
||||||
|
<meta content="Hope" name="og:title"/>
|
||||||
|
<meta content="This is a piggy-back article off of
|
||||||
|
The Struggle article that I had recently.
|
||||||
|
I was a bit of a “Debbie Downer” in that article, which is okay, I get that way sometimes. In this
|
||||||
|
article I’d like to take a minute to layout some of the things that give..." name="og:description"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images/2023-10-30-hope.png" name="og:image"/>
|
||||||
|
<meta content="1014" name="og:image:width"/>
|
||||||
|
<meta content="530" name="og:image:height"/>
|
||||||
|
<script crossorigin="anonymous" src="https://kit.fontawesome.com/f209982030.js">
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body class="bg-page text-white pb-5 font-avenir articles">
|
||||||
|
<header class="bg-nav text-gray py-4 text-base/6 lg:fixed w-full lg:h-[62px]">
|
||||||
|
<nav class="container flex gap-x-5 lg:gap-x-y items-center">
|
||||||
|
<ul class="flex flex-wrap gap-x-2 lg:gap-x-5">
|
||||||
|
<li>
|
||||||
|
<a class href="/">Home</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="active" href="/articles/">Articles</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class href="/about/">About</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<div class="container pt-12 lg:pt-28">
|
||||||
|
<article class="prose">
|
||||||
|
<h1>
|
||||||
|
Hope
|
||||||
|
</h1>
|
||||||
|
<div class="-mt-6">
|
||||||
|
<div class="text-gray gray-links text-sm">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">October 30, 2023</span>633 words, posted in <a href="/articles/tag/general/">general</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2023-10-30-hope.png"/>
|
||||||
|
<p>This is a piggy-back article off of<br />
|
||||||
|
<a href="https://mhoush.com/posts/20231018224631-the-struggle/">The Struggle</a> article that I had recently.</p>
|
||||||
|
<p>I was a bit of a “Debbie Downer” in that article, which is okay, I get that way sometimes. In this<br />
|
||||||
|
article I’d like to take a minute to layout some of the things that give me hope, things that I<br />
|
||||||
|
focus on to try and kick myself out of the rut I can get into sometimes.</p>
|
||||||
|
<p>I believe it’s important to have <strong>hope</strong>, to realize that feeling down is normal / part of being<br />
|
||||||
|
human. It’s just as important to have hope. For some it is a harder thing to focus on, it may be<br />
|
||||||
|
easy for us to try and dwell in negative feelings, to some that may feel more comfortable. When<br />
|
||||||
|
we’re feeling cynical, it’s easy to feed the negativity, although it’s rarely helpful.</p>
|
||||||
|
<h2>Hope</h2>
|
||||||
|
<p>One of the things that I try to focus on is that I’m human, it brings me hope to realize that I’m<br />
|
||||||
|
not the only one who feels the way that I do. This was evident by the feedback on my previous<br />
|
||||||
|
article.</p>
|
||||||
|
<blockquote>
|
||||||
|
<p>My problems are very much “first world problems”.</p>
|
||||||
|
</blockquote>
|
||||||
|
<p>Make no mistake, I’m selfish, but it’s the selfishness that makes me feel distant or disconnected.<br />
|
||||||
|
The times that I feel connected are without a doubt the times that I let go of my ego and focus on<br />
|
||||||
|
things outside of myself.</p>
|
||||||
|
<p>It’s the feeling I get from going to customers home and feeling truly appreciated. There’s no push<br />
|
||||||
|
back on price, no one telling me how I should run my business, no “the part only costs $x on<br />
|
||||||
|
amazon”, etc.</p>
|
||||||
|
<p>The feeling of seeing your child smile. The safety you feel when getting a hug from your mother or<br />
|
||||||
|
father. When you’re looking up at the stars and realize how small you actually are.</p>
|
||||||
|
<p>When you’re out with friends and trick the DJ into playing a Mr. Bungle song and no one else<br />
|
||||||
|
appreciates it, but you. The times when your guard is completely down and you laugh with abandon.</p>
|
||||||
|
<p>The smell of your lover’s hair when you’re holding them close. The joy you receive from sitting with<br />
|
||||||
|
your pets. The songs of nature, insects, birds, etc. The sounds of waves / water in the distance.</p>
|
||||||
|
<p>The feeling when you’ve helped someone learn a new skill, when something finally clicks and makes<br />
|
||||||
|
sense. When a complex topic is understood at a fundamental level. The breakthrough of a problem<br />
|
||||||
|
you’ve pondered for days / months / years.</p>
|
||||||
|
<h2>Conclusion</h2>
|
||||||
|
<p>There are so many things to be grateful for. This does not mean that there will not be hard times,<br />
|
||||||
|
there surely will be. This does not mean that you are wrong for having negative feelings, for<br />
|
||||||
|
feeling depressed or anxious. There are many around you that likely feel similar (they may just not<br />
|
||||||
|
be able to express it in the same way). You never truly know what the person next to you is dealing<br />
|
||||||
|
with. Be compassionate (including showing yourself compassion).</p>
|
||||||
|
<p>When you are feeling down, try to do something for someone else. Make your own list of things to be<br />
|
||||||
|
thankful for. Maybe my non-exhaustive list above will give you some ideas. Write those items down<br />
|
||||||
|
regularly so that you can look back on them when you feel out of balance.</p>
|
||||||
|
<p>There is plenty of negative energy in this world, be true and genuine and you will receive rewards.<br />
|
||||||
|
When you focus on blessings then the negativity will fade.</p>
|
||||||
|
<p>What impact are you going to leave with what little time we have?</p>
|
||||||
|
<p>I hope that you enjoyed this short article. Know that you are <em>NOT</em> alone, you are important, and<br />
|
||||||
|
that I appreciate <em>you!</em></p>
|
||||||
|
</article>
|
||||||
|
<div class="border-t border-light mt-8 pt-8">
|
||||||
|
<h2 class="text-4xl font-extrabold mb-8">
|
||||||
|
Written by
|
||||||
|
</h2>
|
||||||
|
<div class="flex flex-col lg:flex-row gap-8">
|
||||||
|
<div class="flex-[0_0_120px]">
|
||||||
|
<img class="w-[120px] h-[120px] rounded-full" src="/static/images/avatar.png"/>
|
||||||
|
</div>
|
||||||
|
<div class="prose">
|
||||||
|
<h3 class="!m-0">
|
||||||
|
Michael Housh
|
||||||
|
</h3>
|
||||||
|
<p class="text-gray">
|
||||||
|
HVAC business owner with over 27 years of experience. Writes articles about HVAC,
|
||||||
|
Programming, Home-Performance, and Building Science
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-16">
|
||||||
|
<h2 class="text-4xl font-extrabold mb-8">
|
||||||
|
More articles
|
||||||
|
</h2>
|
||||||
|
<div class="grid lg:grid-cols-2 gap-10">
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2025/vapor-htmx-todo-app/">Vapor + HTMX</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">January 05, 2025</span><a href="/articles/tag/general/">general</a>, <a href="/articles/tag/programming/">programming</a> and <a href="/articles/tag/software/">software</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2025/vapor-htmx-todo-app/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2025-01-05-vapor-htmx-todo-app.png"/>
|
||||||
|
Build an example application using Vapor and HTMX.
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2024/free-as-in-freedom/">Free As In Freedom</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">April 09, 2024</span><a href="/articles/tag/general/">general</a>, <a href="/articles/tag/open-source/">open-source</a> and <a href="/articles/tag/software/">software</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2024/free-as-in-freedom/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2024-04-09-free-as-in-freedom.png"/>
|
||||||
|
Salute to open-source software engineers
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<p class="prose mt-8">
|
||||||
|
<a href="/articles/">› See all articles</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="site-footer container text-gray gray-links border-t border-light text-center pt-6 mt-8 text-sm">
|
||||||
|
<p>
|
||||||
|
Copyright © Michael Housh 2023-2025.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Built in Swift using
|
||||||
|
<a href="https://github.com/loopwerk/Saga" rel="nofollow" target="_blank">Saga</a>
|
||||||
|
(<a href="https://github.com/m-housh/mhoush.com" rel="nofollow" target="_blank">source</a>).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="http://localhost:3000/articles/feed.xml" rel="nofollow" target="_blank">RSS</a>
|
||||||
|
|
|
||||||
|
<a href="https://github.com/m-housh" rel="nofollow" target="_blank">Github</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.youtube.com/channel/UCb58SeURd5bObfTiL0KoliA" rel="nofollow" target="_blank">Youtube</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.facebook.com/michael.housh" rel="nofollow" target="_blank">Facebook</a>
|
||||||
|
|
|
||||||
|
<a href="mailto:michael@mhoush.com" rel="nofollow">Email</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
163
deploy/articles/2023/index.html
Normal file
163
deploy/articles/2023/index.html
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en-US">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta content="#0e1112" media="(prefers-color-scheme: dark)" name="theme-color"/>
|
||||||
|
<meta content="#566B78" media="(prefers-color-scheme: light)" name="theme-color"/>
|
||||||
|
<meta content="Michael Housh" name="author"/>
|
||||||
|
<meta content="Mhoush" name="apple-mobile-web-app-title"/>
|
||||||
|
<meta content="initial-scale=1.0, width=device-width" name="viewport"/>
|
||||||
|
<meta content="telephone=no" name="format-detection"/>
|
||||||
|
<meta content="True" name="HandheldFriendly"/>
|
||||||
|
<meta content="320" name="MobileOptimized"/>
|
||||||
|
<meta content="Mhoush" name="og:site_name"/>
|
||||||
|
<meta content="hvac, developer, swift, home-performance, design" name="keywords"/>
|
||||||
|
<title>
|
||||||
|
mhoush: Articles in 2023
|
||||||
|
</title>
|
||||||
|
<link href="/static/favicon.ico" rel="shortcut icon"/>
|
||||||
|
<link href="/static/output.css" rel="stylesheet"/>
|
||||||
|
<link href="/static/style.css" rel="stylesheet"/>
|
||||||
|
<link href="/articles/feed.xml" rel="alternate" title="mhoush" type="application/rss+xml"/>
|
||||||
|
</head>
|
||||||
|
<body class="bg-page text-white pb-5 font-avenir articles">
|
||||||
|
<header class="bg-nav text-gray py-4 text-base/6 lg:fixed w-full lg:h-[62px]">
|
||||||
|
<nav class="container flex gap-x-5 lg:gap-x-y items-center">
|
||||||
|
<ul class="flex flex-wrap gap-x-2 lg:gap-x-5">
|
||||||
|
<li>
|
||||||
|
<a class href="/">Home</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="active" href="/articles/">Articles</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class href="/about/">About</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<div class="container pt-12 lg:pt-28">
|
||||||
|
<section class="mb-10">
|
||||||
|
<h1 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2023/most-important-job/">Most Important Job</a>
|
||||||
|
</h1>
|
||||||
|
<div class="text-gray gray-links text-sm">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">December 14, 2023</span>294 words, posted in <a href="/articles/tag/hvac/">HVAC</a> and <a href="/articles/tag/tech-tip/">tech-tip</a>
|
||||||
|
</div>
|
||||||
|
<p class="mt-4">
|
||||||
|
<a href="/articles/2023/most-important-job/">This short tech tip is about something one of my good friends in the trade told me a long time ago,
|
||||||
|
that has stuck with me through the years. It is a simple phrase / mindset.
|
||||||
|
|
||||||
|
“The current job you’re on, is the most important job of your day”.
|
||||||
|
|
||||||
|
This...</a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section class="mb-10">
|
||||||
|
<h1 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2023/cancel-this/">Cancel This</a>
|
||||||
|
</h1>
|
||||||
|
<div class="text-gray gray-links text-sm">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">December 12, 2023</span>758 words, posted in <a href="/articles/tag/hvac/">HVAC</a>
|
||||||
|
</div>
|
||||||
|
<p class="mt-4">
|
||||||
|
<a href="/articles/2023/cancel-this/">This post is going to be hard to put into words, it’s going to seem egotistical at points, but know
|
||||||
|
that my actions / feelings online are the same as they are if you met me in person. The problem with
|
||||||
|
online interactions is tone and other subtleties...</a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section class="mb-10">
|
||||||
|
<h1 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2023/hope/">Hope</a>
|
||||||
|
</h1>
|
||||||
|
<div class="text-gray gray-links text-sm">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">October 30, 2023</span>633 words, posted in <a href="/articles/tag/general/">general</a>
|
||||||
|
</div>
|
||||||
|
<p class="mt-4">
|
||||||
|
<a href="/articles/2023/hope/">This is a piggy-back article off of
|
||||||
|
The Struggle article that I had recently.
|
||||||
|
I was a bit of a “Debbie Downer” in that article, which is okay, I get that way sometimes. In this
|
||||||
|
article I’d like to take a minute to layout some of the things that give...</a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section class="mb-10">
|
||||||
|
<h1 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2023/heat-recovery-chiller/">Heat Recovery Chiller</a>
|
||||||
|
</h1>
|
||||||
|
<div class="text-gray gray-links text-sm">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">October 27, 2023</span>811 words, posted in <a href="/articles/tag/hvac/">HVAC</a>, <a href="/articles/tag/chiller/">chiller</a> and <a href="/articles/tag/hydronics/">hydronics</a>
|
||||||
|
</div>
|
||||||
|
<p class="mt-4">
|
||||||
|
<a href="/articles/2023/heat-recovery-chiller/">This is an article that I wrote back in 2020, but I don’t believe that I published it anywhere, so
|
||||||
|
I’m doing it now. I did discuss this on
|
||||||
|
this episode of the HVAC School Podcast.
|
||||||
|
Heat Recovery Chillers
|
||||||
|
I have always had a love and passion for...</a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section class="mb-10">
|
||||||
|
<h1 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2023/you-should-learn-markdown/">You Should Learn Markdown</a>
|
||||||
|
</h1>
|
||||||
|
<div class="text-gray gray-links text-sm">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">October 21, 2023</span>364 words, posted in <a href="/articles/tag/hvac/">HVAC</a>, <a href="/articles/tag/general/">general</a> and <a href="/articles/tag/programming/">programming</a>
|
||||||
|
</div>
|
||||||
|
<p class="mt-4">
|
||||||
|
<a href="/articles/2023/you-should-learn-markdown/">This is a quick article about why you should learn markdown.
|
||||||
|
What is markdown
|
||||||
|
Markdown is a “mark-up” language. It allows you to write content in plain text that can be easily
|
||||||
|
converted to other formats, such as html, pdf, docx, and many more. All...</a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section class="mb-10">
|
||||||
|
<h1 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2023/the-struggle/">The Struggle</a>
|
||||||
|
</h1>
|
||||||
|
<div class="text-gray gray-links text-sm">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">October 18, 2023</span>1520 words, posted in <a href="/articles/tag/article/">article</a> and <a href="/articles/tag/general/">general</a>
|
||||||
|
</div>
|
||||||
|
<p class="mt-4">
|
||||||
|
<a href="/articles/2023/the-struggle/">This is a get stuff of my chest article. Probably going to be a mixture of ranting and whining. If
|
||||||
|
that is not your cup of tea then feel free to skip this article.
|
||||||
|
The struggle
|
||||||
|
It has been one of those “when it rains, it pours” type of weeks. As...</a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section class="mb-10">
|
||||||
|
<h1 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2023/calculate-seer-degradation-by-age/">Calculate SEER Degradation by Age</a>
|
||||||
|
</h1>
|
||||||
|
<div class="text-gray gray-links text-sm">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">September 19, 2023</span>395 words, posted in <a href="/articles/tag/hvac/">HVAC</a>, <a href="/articles/tag/formulas/">formulas</a> and <a href="/articles/tag/tech-tip/">tech-tip</a>
|
||||||
|
</div>
|
||||||
|
<p class="mt-4">
|
||||||
|
<a href="/articles/2023/calculate-seer-degradation-by-age/">This is a quick tech-tip to learn how to calculate the degradation of SEER based
|
||||||
|
on age.
|
||||||
|
The degradation of SEER is due to fouling of the evaporator coil with dirt and
|
||||||
|
refrigerant charge losses. It should be noted that this is not true for...</a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<div class="site-footer container text-gray gray-links border-t border-light text-center pt-6 mt-8 text-sm">
|
||||||
|
<p>
|
||||||
|
Copyright © Michael Housh 2023-2025.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Built in Swift using
|
||||||
|
<a href="https://github.com/loopwerk/Saga" rel="nofollow" target="_blank">Saga</a>
|
||||||
|
(<a href="https://github.com/m-housh/mhoush.com" rel="nofollow" target="_blank">source</a>).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="http://localhost:3000/articles/feed.xml" rel="nofollow" target="_blank">RSS</a>
|
||||||
|
|
|
||||||
|
<a href="https://github.com/m-housh" rel="nofollow" target="_blank">Github</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.youtube.com/channel/UCb58SeURd5bObfTiL0KoliA" rel="nofollow" target="_blank">Youtube</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.facebook.com/michael.housh" rel="nofollow" target="_blank">Facebook</a>
|
||||||
|
|
|
||||||
|
<a href="mailto:michael@mhoush.com" rel="nofollow">Email</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
175
deploy/articles/2023/most-important-job/index.html
Normal file
175
deploy/articles/2023/most-important-job/index.html
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en-US">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta content="#0e1112" media="(prefers-color-scheme: dark)" name="theme-color"/>
|
||||||
|
<meta content="#566B78" media="(prefers-color-scheme: light)" name="theme-color"/>
|
||||||
|
<meta content="Michael Housh" name="author"/>
|
||||||
|
<meta content="Mhoush" name="apple-mobile-web-app-title"/>
|
||||||
|
<meta content="initial-scale=1.0, width=device-width" name="viewport"/>
|
||||||
|
<meta content="telephone=no" name="format-detection"/>
|
||||||
|
<meta content="True" name="HandheldFriendly"/>
|
||||||
|
<meta content="320" name="MobileOptimized"/>
|
||||||
|
<meta content="Mhoush" name="og:site_name"/>
|
||||||
|
<meta content="hvac, developer, swift, home-performance, design" name="keywords"/>
|
||||||
|
<title>
|
||||||
|
mhoush: Most Important Job
|
||||||
|
</title>
|
||||||
|
<link href="/static/favicon.ico" rel="shortcut icon"/>
|
||||||
|
<link href="/static/output.css" rel="stylesheet"/>
|
||||||
|
<link href="/static/style.css" rel="stylesheet"/>
|
||||||
|
<link href="/articles/feed.xml" rel="alternate" title="mhoush" type="application/rss+xml"/>
|
||||||
|
<link href="/static/prism.css" rel="stylesheet"/>
|
||||||
|
<meta content="This short tech tip is about something one of my good friends in the trade told me a long time ago,
|
||||||
|
that has stuck with me through the years. It is a simple phrase / mindset.
|
||||||
|
|
||||||
|
“The current job you’re on, is the most important job of your day”.
|
||||||
|
|
||||||
|
This..." name="description"/>
|
||||||
|
<meta content="summary_large_image" name="twitter:card"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images/2023-12-14-most-important-job.gif" name="twitter:image"/>
|
||||||
|
<meta content="Most Important Job" name="twitter:image:alt"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images//articles/2023/most-important-job/" name="og:url"/>
|
||||||
|
<meta content="Most Important Job" name="og:title"/>
|
||||||
|
<meta content="This short tech tip is about something one of my good friends in the trade told me a long time ago,
|
||||||
|
that has stuck with me through the years. It is a simple phrase / mindset.
|
||||||
|
|
||||||
|
“The current job you’re on, is the most important job of your day”.
|
||||||
|
|
||||||
|
This..." name="og:description"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images/2023-12-14-most-important-job.gif" name="og:image"/>
|
||||||
|
<meta content="1014" name="og:image:width"/>
|
||||||
|
<meta content="530" name="og:image:height"/>
|
||||||
|
<script crossorigin="anonymous" src="https://kit.fontawesome.com/f209982030.js">
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body class="bg-page text-white pb-5 font-avenir articles">
|
||||||
|
<header class="bg-nav text-gray py-4 text-base/6 lg:fixed w-full lg:h-[62px]">
|
||||||
|
<nav class="container flex gap-x-5 lg:gap-x-y items-center">
|
||||||
|
<ul class="flex flex-wrap gap-x-2 lg:gap-x-5">
|
||||||
|
<li>
|
||||||
|
<a class href="/">Home</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="active" href="/articles/">Articles</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class href="/about/">About</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<div class="container pt-12 lg:pt-28">
|
||||||
|
<article class="prose">
|
||||||
|
<h1>
|
||||||
|
Most Important Job
|
||||||
|
</h1>
|
||||||
|
<div class="-mt-6">
|
||||||
|
<div class="text-gray gray-links text-sm">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">December 14, 2023</span>294 words, posted in <a href="/articles/tag/hvac/">HVAC</a> and <a href="/articles/tag/tech-tip/">tech-tip</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2023-12-14-most-important-job.gif"/>
|
||||||
|
<p>This short tech tip is about something one of my good friends in the trade told me a long time ago,<br />
|
||||||
|
that has stuck with me through the years. It is a simple phrase / mindset.</p>
|
||||||
|
<blockquote>
|
||||||
|
<p>“The current job you’re on, is the most important job of your day”.</p>
|
||||||
|
</blockquote>
|
||||||
|
<p>This mindset should be carried from the dispatcher, manager, and technician to make this successful.<br />
|
||||||
|
I’m not gonna lie and say this is always easy, or even always possible, but if you strive to use<br />
|
||||||
|
this mindset then you will gain lifelong customers and satisfaction of not having loose ends hanging<br />
|
||||||
|
out there.</p>
|
||||||
|
<p>I do think it’s also important to acknowledge that there are times that a technician has exhausted<br />
|
||||||
|
all their options, maybe they just don’t have the mental capacity anymore to continue with a problem<br />
|
||||||
|
job, or need a break to come back another day with a fresh set of eyes, etc… This is also an<br />
|
||||||
|
important thing for a technician to realize, and hopefully those type of instances are much more few<br />
|
||||||
|
and far between, but I do want to acknowledge that scenario does also exist.</p>
|
||||||
|
<p>If you are a business owner, then this is something to consider instilling in your operations.<br />
|
||||||
|
Empower your technicians and dispatchers to understand when things need to be shuffled around in<br />
|
||||||
|
order to accommodate taking care of the customer at hand. It costs a lot of money to get a<br />
|
||||||
|
technician to job, so minimizing truck rolls to the same job is important from a business<br />
|
||||||
|
standpoint.</p>
|
||||||
|
<p>This was just a quick tech tip of something that has been rolling around in my mind lately. I hope<br />
|
||||||
|
you find it helpful and it sticks with you through your career as it has mine.</p>
|
||||||
|
</article>
|
||||||
|
<div class="border-t border-light mt-8 pt-8">
|
||||||
|
<h2 class="text-4xl font-extrabold mb-8">
|
||||||
|
Written by
|
||||||
|
</h2>
|
||||||
|
<div class="flex flex-col lg:flex-row gap-8">
|
||||||
|
<div class="flex-[0_0_120px]">
|
||||||
|
<img class="w-[120px] h-[120px] rounded-full" src="/static/images/avatar.png"/>
|
||||||
|
</div>
|
||||||
|
<div class="prose">
|
||||||
|
<h3 class="!m-0">
|
||||||
|
Michael Housh
|
||||||
|
</h3>
|
||||||
|
<p class="text-gray">
|
||||||
|
HVAC business owner with over 27 years of experience. Writes articles about HVAC,
|
||||||
|
Programming, Home-Performance, and Building Science
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-16">
|
||||||
|
<h2 class="text-4xl font-extrabold mb-8">
|
||||||
|
More articles
|
||||||
|
</h2>
|
||||||
|
<div class="grid lg:grid-cols-2 gap-10">
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2025/vapor-htmx-todo-app/">Vapor + HTMX</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">January 05, 2025</span><a href="/articles/tag/general/">general</a>, <a href="/articles/tag/programming/">programming</a> and <a href="/articles/tag/software/">software</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2025/vapor-htmx-todo-app/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2025-01-05-vapor-htmx-todo-app.png"/>
|
||||||
|
Build an example application using Vapor and HTMX.
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2024/free-as-in-freedom/">Free As In Freedom</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">April 09, 2024</span><a href="/articles/tag/general/">general</a>, <a href="/articles/tag/open-source/">open-source</a> and <a href="/articles/tag/software/">software</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2024/free-as-in-freedom/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2024-04-09-free-as-in-freedom.png"/>
|
||||||
|
Salute to open-source software engineers
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<p class="prose mt-8">
|
||||||
|
<a href="/articles/">› See all articles</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="site-footer container text-gray gray-links border-t border-light text-center pt-6 mt-8 text-sm">
|
||||||
|
<p>
|
||||||
|
Copyright © Michael Housh 2023-2025.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Built in Swift using
|
||||||
|
<a href="https://github.com/loopwerk/Saga" rel="nofollow" target="_blank">Saga</a>
|
||||||
|
(<a href="https://github.com/m-housh/mhoush.com" rel="nofollow" target="_blank">source</a>).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="http://localhost:3000/articles/feed.xml" rel="nofollow" target="_blank">RSS</a>
|
||||||
|
|
|
||||||
|
<a href="https://github.com/m-housh" rel="nofollow" target="_blank">Github</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.youtube.com/channel/UCb58SeURd5bObfTiL0KoliA" rel="nofollow" target="_blank">Youtube</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.facebook.com/michael.housh" rel="nofollow" target="_blank">Facebook</a>
|
||||||
|
|
|
||||||
|
<a href="mailto:michael@mhoush.com" rel="nofollow">Email</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
292
deploy/articles/2023/the-struggle/index.html
Normal file
292
deploy/articles/2023/the-struggle/index.html
Normal file
@@ -0,0 +1,292 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en-US">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta content="#0e1112" media="(prefers-color-scheme: dark)" name="theme-color"/>
|
||||||
|
<meta content="#566B78" media="(prefers-color-scheme: light)" name="theme-color"/>
|
||||||
|
<meta content="Michael Housh" name="author"/>
|
||||||
|
<meta content="Mhoush" name="apple-mobile-web-app-title"/>
|
||||||
|
<meta content="initial-scale=1.0, width=device-width" name="viewport"/>
|
||||||
|
<meta content="telephone=no" name="format-detection"/>
|
||||||
|
<meta content="True" name="HandheldFriendly"/>
|
||||||
|
<meta content="320" name="MobileOptimized"/>
|
||||||
|
<meta content="Mhoush" name="og:site_name"/>
|
||||||
|
<meta content="hvac, developer, swift, home-performance, design" name="keywords"/>
|
||||||
|
<title>
|
||||||
|
mhoush: The Struggle
|
||||||
|
</title>
|
||||||
|
<link href="/static/favicon.ico" rel="shortcut icon"/>
|
||||||
|
<link href="/static/output.css" rel="stylesheet"/>
|
||||||
|
<link href="/static/style.css" rel="stylesheet"/>
|
||||||
|
<link href="/articles/feed.xml" rel="alternate" title="mhoush" type="application/rss+xml"/>
|
||||||
|
<link href="/static/prism.css" rel="stylesheet"/>
|
||||||
|
<meta content="This is a get stuff of my chest article. Probably going to be a mixture of ranting and whining. If
|
||||||
|
that is not your cup of tea then feel free to skip this article.
|
||||||
|
The struggle
|
||||||
|
It has been one of those “when it rains, it pours” type of weeks. As..." name="description"/>
|
||||||
|
<meta content="summary_large_image" name="twitter:card"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images/2023-10-18-the-struggle.png" name="twitter:image"/>
|
||||||
|
<meta content="The Struggle" name="twitter:image:alt"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images//articles/2023/the-struggle/" name="og:url"/>
|
||||||
|
<meta content="The Struggle" name="og:title"/>
|
||||||
|
<meta content="This is a get stuff of my chest article. Probably going to be a mixture of ranting and whining. If
|
||||||
|
that is not your cup of tea then feel free to skip this article.
|
||||||
|
The struggle
|
||||||
|
It has been one of those “when it rains, it pours” type of weeks. As..." name="og:description"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images/2023-10-18-the-struggle.png" name="og:image"/>
|
||||||
|
<meta content="1014" name="og:image:width"/>
|
||||||
|
<meta content="530" name="og:image:height"/>
|
||||||
|
<script crossorigin="anonymous" src="https://kit.fontawesome.com/f209982030.js">
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body class="bg-page text-white pb-5 font-avenir articles">
|
||||||
|
<header class="bg-nav text-gray py-4 text-base/6 lg:fixed w-full lg:h-[62px]">
|
||||||
|
<nav class="container flex gap-x-5 lg:gap-x-y items-center">
|
||||||
|
<ul class="flex flex-wrap gap-x-2 lg:gap-x-5">
|
||||||
|
<li>
|
||||||
|
<a class href="/">Home</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="active" href="/articles/">Articles</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class href="/about/">About</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<div class="container pt-12 lg:pt-28">
|
||||||
|
<article class="prose">
|
||||||
|
<h1>
|
||||||
|
The Struggle
|
||||||
|
</h1>
|
||||||
|
<div class="-mt-6">
|
||||||
|
<div class="text-gray gray-links text-sm">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">October 18, 2023</span>1520 words, posted in <a href="/articles/tag/article/">article</a> and <a href="/articles/tag/general/">general</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2023-10-18-the-struggle.png"/>
|
||||||
|
<p>This is a get stuff of my chest article. Probably going to be a mixture of ranting and whining. If<br />
|
||||||
|
that is not your cup of tea then feel free to skip this article.</p>
|
||||||
|
<h2>The struggle</h2>
|
||||||
|
<p>It has been one of those “when it rains, it pours” type of weeks. As write this, I feel like a baby<br />
|
||||||
|
/ complainer, which is not my intention, but here it goes.</p>
|
||||||
|
<p>My aunt had a stroke and is likely not going to make it through the week. My aunt has always lived<br />
|
||||||
|
in Florida during my life / memory, but has always come to visit. She is my mom’s oldest sister (9<br />
|
||||||
|
years apart), so she helped raise my mother growing up. They’ve always had a close relationship and<br />
|
||||||
|
are like two peas in a pod. They would always visit us, especially while my grand-parents were still<br />
|
||||||
|
alive. She is currently not really awake or expected to make it. She does not eat / drink and<br />
|
||||||
|
they’ve basically just been making her comfortable.</p>
|
||||||
|
<p>One of my employees broke his neck over the weekend. I don’t have a ton of details on this subject,<br />
|
||||||
|
but he had surgery to fuse some discs back together and should eventually be ok, however it will be<br />
|
||||||
|
a long recovery time.</p>
|
||||||
|
<p>A few weeks ago, I commited one of the deadly sins of running a blower door test without checking /<br />
|
||||||
|
asking about the fireplaces, which caused lord knows how much damage from the soot that was spread<br />
|
||||||
|
throughout the living room(s).</p>
|
||||||
|
<p>An online friend lost her mother.</p>
|
||||||
|
<p>All of these things have just got me emotional.</p>
|
||||||
|
<h2>My secrets</h2>
|
||||||
|
<p>I am an emotional person, sometimes to my detriment. I’m prone to fits of anger and depression. I<br />
|
||||||
|
spent many years masking things through alcohol abuse and many other idiotic tendencies. I still<br />
|
||||||
|
drink on occasion, but not as I once did.</p>
|
||||||
|
<p>I often put my faith in folks, even if I haven’t met them in person, this can often lead to being<br />
|
||||||
|
let down. I guess I struggle sometimes with the reality of online relationships. I think that people<br />
|
||||||
|
are genuine, because I’m that way (how I act online is the same as I act in person for the most<br />
|
||||||
|
part). I will happily show / share the good and the bad, in hopes that someone may learn. This is<br />
|
||||||
|
not at all something to be ashamed of, or anything that I’d like to change, however it does on<br />
|
||||||
|
occasion lead me into turmoil when I find out some true identity / personality of someone.</p>
|
||||||
|
<p>I hold grudges, like forever grudges. It is very hard for me to get over somethings, even if I want<br />
|
||||||
|
to. I can sometimes put things out of my mind, but when I’m spinning, they will resurface. I want to<br />
|
||||||
|
forgive people, but it is just not the way it works for me often times. It takes a lot to get me<br />
|
||||||
|
beyond my breaking point, but once someone has gotten me there, there is likely no turning back for<br />
|
||||||
|
that person. Luckily, I can count on one hand the number of folks that I’ve had to cut out of my<br />
|
||||||
|
life for these reasons. I’d love to say that I’m a bigger / better person, that I forgive them, but<br />
|
||||||
|
truthfully I do not.</p>
|
||||||
|
<p>My emotions sometimes make me say things publicly that I should keep to myself. I don’t have a lot<br />
|
||||||
|
of regret around these things, because I generally mean what I say, and also feel we are entitled to<br />
|
||||||
|
opinions as well as entitled to change those opinions as often as we see fit. Although I don’t<br />
|
||||||
|
regret them per-se, it does make me wonder what type of impression it leaves (something for future<br />
|
||||||
|
pondering, perhaps).</p>
|
||||||
|
<p>I’m one of those that says “I don’t care what they think about me”, when I really do care what<br />
|
||||||
|
people think about me. This often leads to fear and anxiety, especially in social settings. I’m not<br />
|
||||||
|
the greatest at conversation, I’m better at writing or some interaction that gives me a bit of time<br />
|
||||||
|
to think before responding. Therefore, I’m quick to make a joke or something rather than having<br />
|
||||||
|
thoughtful / genuine responses.</p>
|
||||||
|
<h2>Community</h2>
|
||||||
|
<p>All of these things have just got me thinking about community. Community is an aspect that seems<br />
|
||||||
|
distant nowadays, even though we have more opportunity than ever. We call ourselves part of<br />
|
||||||
|
communities, especially online, but I’m not convinced that it is really community (or at least not<br />
|
||||||
|
most of the time, not saying it can’t be / in absolute terms).</p>
|
||||||
|
<p>I have met a lot of folks online that I consider true friends. Friends that I would do anything for<br />
|
||||||
|
and feel they would do anything for me, just like my real life friends who have stuck with me for<br />
|
||||||
|
many years. These are people that challenge me and how I think on a regular basis. They do their<br />
|
||||||
|
best to lift me up when I’m down.</p>
|
||||||
|
<p>It’s easy to hide when so much of our interactions are not really in person, to feel like the<br />
|
||||||
|
relationships we do have are not genuine, but that’s awfully cynical. I prefer to give people the<br />
|
||||||
|
benefit / trust they deserve until, at least until they don’t then see my part about holding grudges<br />
|
||||||
|
;)</p>
|
||||||
|
<p>Do you ever feel the same? Instead of being cynical and down, today, I’m trying to be positive. I’m<br />
|
||||||
|
trying to share a little bit of what I feel community should be. Although, I’ve never met HVAChicks<br />
|
||||||
|
Jennifer in real life, I read today about her mom and decided to take an hour or so to put together<br />
|
||||||
|
a website for the <a href="https://hvachicks.com">HVAChicks Community</a>, hoping it would bring a moment of<br />
|
||||||
|
happiness to her day. While I’ve deployed several websites in the past, this one for some reason was<br />
|
||||||
|
a total PITA, but I got through it. I could feel how grateful she was when I shared it with her (and<br />
|
||||||
|
it’s basic AF), but that truly made me feel useful / great after being down in the dumps for a bit.</p>
|
||||||
|
<h2>Conclusion</h2>
|
||||||
|
<p>I’ve probably rambled enough and am losing direction here, so I will end with a few things.</p>
|
||||||
|
<ol>
|
||||||
|
<li>Build the community around you that you want / deserve.</li>
|
||||||
|
<li>Don’t be so quick to pass judgment.</li>
|
||||||
|
<li>Spend time with your loved ones, while you can.</li>
|
||||||
|
<li>Tell someone you love them.</li>
|
||||||
|
</ol>
|
||||||
|
<p>Finally, I’d like to shout out some people that I’m grateful for. This is non-exhaustive list, if I<br />
|
||||||
|
left you off, I’m sorry and please do not take it personally.</p>
|
||||||
|
<ol>
|
||||||
|
<li>Bryan Orr
|
||||||
|
<ul>
|
||||||
|
<li>Bryan has cultivated an awesome group / community that I’m proud to be a part of. His time and<br />
|
||||||
|
commitment to the HVAC industry is something that I hope he himself is proud of. Without Bryan,<br />
|
||||||
|
mostly all the following names would not even be in my vocabulary.</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Ty Branaman (forget exactly how to spell his last name).
|
||||||
|
<ul>
|
||||||
|
<li>Ty has such a great personality during his videos / training and I’m sure it’s a struggle to be<br />
|
||||||
|
positive all the time, however it brings me hope and joy everytime!</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Dustin (mother f’n) Cole
|
||||||
|
<ul>
|
||||||
|
<li>Dustin is like a brother that I never had, he’s a true master of his craft and I know that I<br />
|
||||||
|
can rely on him anytime I need it!</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Genry Garcia
|
||||||
|
<ul>
|
||||||
|
<li>The cuban crusader who has taught me so much about home performance, and especially ZPD (baby,<br />
|
||||||
|
baby)!</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Chris Hughes
|
||||||
|
<ul>
|
||||||
|
<li>It’s hard to put into words here, but I know that Chris is there to talk when I need it and<br />
|
||||||
|
he’s a great motivator because of his action items :)</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Eric Kaiser
|
||||||
|
<ul>
|
||||||
|
<li>I think genuine when I think of Eric, I hear his voice in my head when I write reports because<br />
|
||||||
|
of guidance he has given in the past. He truly wants to help teach people.</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Michael Cianfracco (??)
|
||||||
|
<ul>
|
||||||
|
<li>Man does he make me laugh and we share a passion for the 4-Roses.</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>HVAChicks Jennifer (I’ll butcher her last name from memory)
|
||||||
|
<ul>
|
||||||
|
<li>Jennifer is inspiring with her goals and everything she does to help anyone in the industry. I<br />
|
||||||
|
can’t wait to meet her in person one day soon!</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>HVAC Overtime Crew
|
||||||
|
<ul>
|
||||||
|
<li>I’m lumping these guys together because I truly enjoy when I’m able to make their live stream<br />
|
||||||
|
on Friday’s. And I interact with A-Team a lot and really appreciate him / them!</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Alicia Hollon
|
||||||
|
<ul>
|
||||||
|
<li>Alicia is so awesome to me, I mean she just made my favorite pancakes and sausage for dinner,<br />
|
||||||
|
love you babe!</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
<p>Lastly, I have to shout out to my mom. I know she’s going through a rough time with my aunt<br />
|
||||||
|
currently. My mother is the kindest gentlest soul that I’ve ever met. I look up to all 5’ of her!</p>
|
||||||
|
<p>At any rate, thanks for sticking it out to the end through my ramblings. Be kind to someone today<br />
|
||||||
|
and tomorrow!</p>
|
||||||
|
</article>
|
||||||
|
<div class="border-t border-light mt-8 pt-8">
|
||||||
|
<h2 class="text-4xl font-extrabold mb-8">
|
||||||
|
Written by
|
||||||
|
</h2>
|
||||||
|
<div class="flex flex-col lg:flex-row gap-8">
|
||||||
|
<div class="flex-[0_0_120px]">
|
||||||
|
<img class="w-[120px] h-[120px] rounded-full" src="/static/images/avatar.png"/>
|
||||||
|
</div>
|
||||||
|
<div class="prose">
|
||||||
|
<h3 class="!m-0">
|
||||||
|
Michael Housh
|
||||||
|
</h3>
|
||||||
|
<p class="text-gray">
|
||||||
|
HVAC business owner with over 27 years of experience. Writes articles about HVAC,
|
||||||
|
Programming, Home-Performance, and Building Science
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-16">
|
||||||
|
<h2 class="text-4xl font-extrabold mb-8">
|
||||||
|
More articles
|
||||||
|
</h2>
|
||||||
|
<div class="grid lg:grid-cols-2 gap-10">
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2025/vapor-htmx-todo-app/">Vapor + HTMX</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">January 05, 2025</span><a href="/articles/tag/general/">general</a>, <a href="/articles/tag/programming/">programming</a> and <a href="/articles/tag/software/">software</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2025/vapor-htmx-todo-app/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2025-01-05-vapor-htmx-todo-app.png"/>
|
||||||
|
Build an example application using Vapor and HTMX.
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2024/free-as-in-freedom/">Free As In Freedom</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">April 09, 2024</span><a href="/articles/tag/general/">general</a>, <a href="/articles/tag/open-source/">open-source</a> and <a href="/articles/tag/software/">software</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2024/free-as-in-freedom/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2024-04-09-free-as-in-freedom.png"/>
|
||||||
|
Salute to open-source software engineers
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<p class="prose mt-8">
|
||||||
|
<a href="/articles/">› See all articles</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="site-footer container text-gray gray-links border-t border-light text-center pt-6 mt-8 text-sm">
|
||||||
|
<p>
|
||||||
|
Copyright © Michael Housh 2023-2025.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Built in Swift using
|
||||||
|
<a href="https://github.com/loopwerk/Saga" rel="nofollow" target="_blank">Saga</a>
|
||||||
|
(<a href="https://github.com/m-housh/mhoush.com" rel="nofollow" target="_blank">source</a>).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="http://localhost:3000/articles/feed.xml" rel="nofollow" target="_blank">RSS</a>
|
||||||
|
|
|
||||||
|
<a href="https://github.com/m-housh" rel="nofollow" target="_blank">Github</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.youtube.com/channel/UCb58SeURd5bObfTiL0KoliA" rel="nofollow" target="_blank">Youtube</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.facebook.com/michael.housh" rel="nofollow" target="_blank">Facebook</a>
|
||||||
|
|
|
||||||
|
<a href="mailto:michael@mhoush.com" rel="nofollow">Email</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
205
deploy/articles/2023/you-should-learn-markdown/index.html
Normal file
205
deploy/articles/2023/you-should-learn-markdown/index.html
Normal file
@@ -0,0 +1,205 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en-US">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta content="#0e1112" media="(prefers-color-scheme: dark)" name="theme-color"/>
|
||||||
|
<meta content="#566B78" media="(prefers-color-scheme: light)" name="theme-color"/>
|
||||||
|
<meta content="Michael Housh" name="author"/>
|
||||||
|
<meta content="Mhoush" name="apple-mobile-web-app-title"/>
|
||||||
|
<meta content="initial-scale=1.0, width=device-width" name="viewport"/>
|
||||||
|
<meta content="telephone=no" name="format-detection"/>
|
||||||
|
<meta content="True" name="HandheldFriendly"/>
|
||||||
|
<meta content="320" name="MobileOptimized"/>
|
||||||
|
<meta content="Mhoush" name="og:site_name"/>
|
||||||
|
<meta content="hvac, developer, swift, home-performance, design" name="keywords"/>
|
||||||
|
<title>
|
||||||
|
mhoush: You Should Learn Markdown
|
||||||
|
</title>
|
||||||
|
<link href="/static/favicon.ico" rel="shortcut icon"/>
|
||||||
|
<link href="/static/output.css" rel="stylesheet"/>
|
||||||
|
<link href="/static/style.css" rel="stylesheet"/>
|
||||||
|
<link href="/articles/feed.xml" rel="alternate" title="mhoush" type="application/rss+xml"/>
|
||||||
|
<link href="/static/prism.css" rel="stylesheet"/>
|
||||||
|
<meta content="This is a quick article about why you should learn markdown.
|
||||||
|
What is markdown
|
||||||
|
Markdown is a “mark-up” language. It allows you to write content in plain text that can be easily
|
||||||
|
converted to other formats, such as html, pdf, docx, and many more. All..." name="description"/>
|
||||||
|
<meta content="summary_large_image" name="twitter:card"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images/2023-10-21-you-should-learn-markdown.png" name="twitter:image"/>
|
||||||
|
<meta content="You Should Learn Markdown" name="twitter:image:alt"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images//articles/2023/you-should-learn-markdown/" name="og:url"/>
|
||||||
|
<meta content="You Should Learn Markdown" name="og:title"/>
|
||||||
|
<meta content="This is a quick article about why you should learn markdown.
|
||||||
|
What is markdown
|
||||||
|
Markdown is a “mark-up” language. It allows you to write content in plain text that can be easily
|
||||||
|
converted to other formats, such as html, pdf, docx, and many more. All..." name="og:description"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images/2023-10-21-you-should-learn-markdown.png" name="og:image"/>
|
||||||
|
<meta content="1014" name="og:image:width"/>
|
||||||
|
<meta content="530" name="og:image:height"/>
|
||||||
|
<script crossorigin="anonymous" src="https://kit.fontawesome.com/f209982030.js">
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body class="bg-page text-white pb-5 font-avenir articles">
|
||||||
|
<header class="bg-nav text-gray py-4 text-base/6 lg:fixed w-full lg:h-[62px]">
|
||||||
|
<nav class="container flex gap-x-5 lg:gap-x-y items-center">
|
||||||
|
<ul class="flex flex-wrap gap-x-2 lg:gap-x-5">
|
||||||
|
<li>
|
||||||
|
<a class href="/">Home</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="active" href="/articles/">Articles</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class href="/about/">About</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<div class="container pt-12 lg:pt-28">
|
||||||
|
<article class="prose">
|
||||||
|
<h1>
|
||||||
|
You Should Learn Markdown
|
||||||
|
</h1>
|
||||||
|
<div class="-mt-6">
|
||||||
|
<div class="text-gray gray-links text-sm">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">October 21, 2023</span>364 words, posted in <a href="/articles/tag/hvac/">HVAC</a>, <a href="/articles/tag/general/">general</a> and <a href="/articles/tag/programming/">programming</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2023-10-21-you-should-learn-markdown.png"/>
|
||||||
|
<p>This is a quick article about why you should learn markdown.</p>
|
||||||
|
<h2>What is markdown</h2>
|
||||||
|
<p>Markdown is a “mark-up” language. It allows you to write content in plain text that can be easily<br />
|
||||||
|
converted to other formats, such as <strong>html, pdf, docx</strong>, and many more. All the articles written on<br />
|
||||||
|
this website are written in markdown, here’s an image of this article written in markdown.</p>
|
||||||
|
<p><img src="/articles/images/2023-10-21-markdown.png" alt="markdown" /></p>
|
||||||
|
<p>The reason you should learn markdown is that it allows you to focus on the content / text of your<br />
|
||||||
|
content with simple concepts for formatting. Markdown is used heavily in documenting software<br />
|
||||||
|
projects, which is how I got introduced to it, however it can scale all the way up to writing<br />
|
||||||
|
research papers or even books.</p>
|
||||||
|
<p>I use markdown for probably 80% of all the text documents I need to write, from company documents,<br />
|
||||||
|
web / software documentation, and so on. It allows me to get content out quickly without having to<br />
|
||||||
|
click around with formatting options in a program like <strong>Word</strong> or <strong>Pages</strong>. To be clear, a lot of<br />
|
||||||
|
the reports and things I generate for my <strong>Home Performance Assessments</strong> are written using<br />
|
||||||
|
<strong>Pages</strong> (for now at least) because I have templates that make the documents look more<br />
|
||||||
|
professional, however I am working on solutions to migrate those to be markdown based.</p>
|
||||||
|
<p>Markdown is supported in mostly all the <strong>Google</strong> tools, as well as the <strong>Outlook</strong> email client<br />
|
||||||
|
(which is one of my least favorite tools, BTW). It makes it simple to create tables, lists, and many<br />
|
||||||
|
common document related tasks.</p>
|
||||||
|
<h2>Resources</h2>
|
||||||
|
<p>You can learn more about the syntax used for markdown at<br />
|
||||||
|
<a href="https://www.markdownguide.org/basic-syntax/">markdownguide.org</a>.</p>
|
||||||
|
<h3>A non-exhaustive list of where you can use Markdown and editors.</h3>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Platform</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Google</td>
|
||||||
|
<td>Most goggle tools support markdown, docs, sheets, etc.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Outlook</td>
|
||||||
|
<td>Although I hate outlook email client, it does support markdown.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Dillinger.io</td>
|
||||||
|
<td>An online tool for writing / previewing markdown</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>MarkText</td>
|
||||||
|
<td>A multi-platform editor for writing markdown</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p>You can use tools such as <a href="https://pandoc.org/#">pandoc</a> to convert Markdown files to other formats.</p>
|
||||||
|
<p><img src="/articles/images/2023-10-21-pandoc.gif" alt="pandoc" /></p>
|
||||||
|
<h2>Conclusion</h2>
|
||||||
|
<p>I hope that you take the time to research and see if Markdown is good fit for your document /<br />
|
||||||
|
content creation.</p>
|
||||||
|
<p>Thanks for reading until the end!</p>
|
||||||
|
</article>
|
||||||
|
<div class="border-t border-light mt-8 pt-8">
|
||||||
|
<h2 class="text-4xl font-extrabold mb-8">
|
||||||
|
Written by
|
||||||
|
</h2>
|
||||||
|
<div class="flex flex-col lg:flex-row gap-8">
|
||||||
|
<div class="flex-[0_0_120px]">
|
||||||
|
<img class="w-[120px] h-[120px] rounded-full" src="/static/images/avatar.png"/>
|
||||||
|
</div>
|
||||||
|
<div class="prose">
|
||||||
|
<h3 class="!m-0">
|
||||||
|
Michael Housh
|
||||||
|
</h3>
|
||||||
|
<p class="text-gray">
|
||||||
|
HVAC business owner with over 27 years of experience. Writes articles about HVAC,
|
||||||
|
Programming, Home-Performance, and Building Science
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-16">
|
||||||
|
<h2 class="text-4xl font-extrabold mb-8">
|
||||||
|
More articles
|
||||||
|
</h2>
|
||||||
|
<div class="grid lg:grid-cols-2 gap-10">
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2025/vapor-htmx-todo-app/">Vapor + HTMX</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">January 05, 2025</span><a href="/articles/tag/general/">general</a>, <a href="/articles/tag/programming/">programming</a> and <a href="/articles/tag/software/">software</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2025/vapor-htmx-todo-app/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2025-01-05-vapor-htmx-todo-app.png"/>
|
||||||
|
Build an example application using Vapor and HTMX.
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2024/free-as-in-freedom/">Free As In Freedom</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">April 09, 2024</span><a href="/articles/tag/general/">general</a>, <a href="/articles/tag/open-source/">open-source</a> and <a href="/articles/tag/software/">software</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2024/free-as-in-freedom/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2024-04-09-free-as-in-freedom.png"/>
|
||||||
|
Salute to open-source software engineers
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<p class="prose mt-8">
|
||||||
|
<a href="/articles/">› See all articles</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="site-footer container text-gray gray-links border-t border-light text-center pt-6 mt-8 text-sm">
|
||||||
|
<p>
|
||||||
|
Copyright © Michael Housh 2023-2025.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Built in Swift using
|
||||||
|
<a href="https://github.com/loopwerk/Saga" rel="nofollow" target="_blank">Saga</a>
|
||||||
|
(<a href="https://github.com/m-housh/mhoush.com" rel="nofollow" target="_blank">source</a>).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="http://localhost:3000/articles/feed.xml" rel="nofollow" target="_blank">RSS</a>
|
||||||
|
|
|
||||||
|
<a href="https://github.com/m-housh" rel="nofollow" target="_blank">Github</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.youtube.com/channel/UCb58SeURd5bObfTiL0KoliA" rel="nofollow" target="_blank">Youtube</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.facebook.com/michael.housh" rel="nofollow" target="_blank">Facebook</a>
|
||||||
|
|
|
||||||
|
<a href="mailto:michael@mhoush.com" rel="nofollow">Email</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
200
deploy/articles/2024/elevating-hvac/index.html
Normal file
200
deploy/articles/2024/elevating-hvac/index.html
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en-US">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta content="#0e1112" media="(prefers-color-scheme: dark)" name="theme-color"/>
|
||||||
|
<meta content="#566B78" media="(prefers-color-scheme: light)" name="theme-color"/>
|
||||||
|
<meta content="Michael Housh" name="author"/>
|
||||||
|
<meta content="Mhoush" name="apple-mobile-web-app-title"/>
|
||||||
|
<meta content="initial-scale=1.0, width=device-width" name="viewport"/>
|
||||||
|
<meta content="telephone=no" name="format-detection"/>
|
||||||
|
<meta content="True" name="HandheldFriendly"/>
|
||||||
|
<meta content="320" name="MobileOptimized"/>
|
||||||
|
<meta content="Mhoush" name="og:site_name"/>
|
||||||
|
<meta content="hvac, developer, swift, home-performance, design" name="keywords"/>
|
||||||
|
<title>
|
||||||
|
mhoush: Elevating HVAC: A Skilled Trade Beyond Labor
|
||||||
|
</title>
|
||||||
|
<link href="/static/favicon.ico" rel="shortcut icon"/>
|
||||||
|
<link href="/static/output.css" rel="stylesheet"/>
|
||||||
|
<link href="/static/style.css" rel="stylesheet"/>
|
||||||
|
<link href="/articles/feed.xml" rel="alternate" title="mhoush" type="application/rss+xml"/>
|
||||||
|
<link href="/static/prism.css" rel="stylesheet"/>
|
||||||
|
<meta content="This is a guest post from my good friend, Ty Branaman.
|
||||||
|
Introduction:
|
||||||
|
Heating, Ventilation, and Air Conditioning (HVAC) is often mistakenly categorized as a simple labor
|
||||||
|
job, overshadowing the intricate skill set and technical expertise required in..." name="description"/>
|
||||||
|
<meta content="summary_large_image" name="twitter:card"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images/2024-02-27-elevating-hvac.png" name="twitter:image"/>
|
||||||
|
<meta content="Elevating HVAC: A Skilled Trade Beyond Labor" name="twitter:image:alt"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images//articles/2024/elevating-hvac/" name="og:url"/>
|
||||||
|
<meta content="Elevating HVAC: A Skilled Trade Beyond Labor" name="og:title"/>
|
||||||
|
<meta content="This is a guest post from my good friend, Ty Branaman.
|
||||||
|
Introduction:
|
||||||
|
Heating, Ventilation, and Air Conditioning (HVAC) is often mistakenly categorized as a simple labor
|
||||||
|
job, overshadowing the intricate skill set and technical expertise required in..." name="og:description"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images/2024-02-27-elevating-hvac.png" name="og:image"/>
|
||||||
|
<meta content="1014" name="og:image:width"/>
|
||||||
|
<meta content="530" name="og:image:height"/>
|
||||||
|
<script crossorigin="anonymous" src="https://kit.fontawesome.com/f209982030.js">
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body class="bg-page text-white pb-5 font-avenir articles">
|
||||||
|
<header class="bg-nav text-gray py-4 text-base/6 lg:fixed w-full lg:h-[62px]">
|
||||||
|
<nav class="container flex gap-x-5 lg:gap-x-y items-center">
|
||||||
|
<ul class="flex flex-wrap gap-x-2 lg:gap-x-5">
|
||||||
|
<li>
|
||||||
|
<a class href="/">Home</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="active" href="/articles/">Articles</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class href="/about/">About</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<div class="container pt-12 lg:pt-28">
|
||||||
|
<article class="prose">
|
||||||
|
<h1>
|
||||||
|
Elevating HVAC: A Skilled Trade Beyond Labor
|
||||||
|
</h1>
|
||||||
|
<div class="-mt-6">
|
||||||
|
<div class="text-gray gray-links text-sm">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">February 27, 2024</span>535 words, posted in <a href="/articles/tag/hvac/">HVAC</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2024-02-27-elevating-hvac.png"/>
|
||||||
|
<p>This is a guest post from my good friend, <strong>Ty Branaman</strong>.</p>
|
||||||
|
<h2>Introduction:</h2>
|
||||||
|
<p>Heating, Ventilation, and Air Conditioning (HVAC) is often mistakenly categorized as a simple labor<br />
|
||||||
|
job, overshadowing the intricate skill set and technical expertise required in this field. Labor<br />
|
||||||
|
jobs are also very important positions needed to keep society running. HVAC, like other skilled<br />
|
||||||
|
trades, demands a high level of knowledge, precision, and adaptability. This article aims to shed<br />
|
||||||
|
light on the misconception surrounding HVAC, emphasizing its status as a skilled trade that plays a<br />
|
||||||
|
pivotal role in creating comfortable and efficient living and working environments.</p>
|
||||||
|
<h2>Technical Proficiency:</h2>
|
||||||
|
<p>One of the defining features that distinguish HVAC as a skilled trade is the level of technical<br />
|
||||||
|
proficiency required. HVAC professionals must have a deep understanding of thermodynamics, fluid<br />
|
||||||
|
mechanics, electrical circuits, Psychrometrics and air properties. This knowledge is essential for<br />
|
||||||
|
designing, installing, and maintaining HVAC systems that operate seamlessly and efficiently.</p>
|
||||||
|
<h2>System Design and Installation:</h2>
|
||||||
|
<p>HVAC professionals are involved in the intricate process of designing and installing heating,<br />
|
||||||
|
ventilation, and air conditioning systems. This task requires not only a thorough understanding of<br />
|
||||||
|
the physical principles governing HVAC but also the ability to tailor solutions to meet the unique<br />
|
||||||
|
needs of each space. Proper system design and installation are crucial for achieving optimal energy<br />
|
||||||
|
efficiency and performance.</p>
|
||||||
|
<h2>Diagnostic Skills:</h2>
|
||||||
|
<p>Troubleshooting and diagnosing issues in HVAC systems require a keen analytical mind and<br />
|
||||||
|
problem-solving skills. Skilled HVAC technicians possess the ability to identify and rectify<br />
|
||||||
|
problems efficiently, ensuring minimal downtime and disruption to the comfort of occupants. This<br />
|
||||||
|
diagnostic acumen is a hallmark of a trade that goes beyond routine labor.</p>
|
||||||
|
<h2>Adaptability to Advanced Technologies:</h2>
|
||||||
|
<p>The HVAC industry is in a constant state of evolution, with new technologies and innovations<br />
|
||||||
|
continuously being introduced. Skilled HVAC professionals are adaptable and stay abreast of these<br />
|
||||||
|
advancements. From smart thermostats to energy-efficient systems, they integrate cutting-edge<br />
|
||||||
|
technologies to provide state-of-the-art solutions for their clients.</p>
|
||||||
|
<h2>Safety and Compliance:</h2>
|
||||||
|
<p>Safety is paramount in the HVAC trade. Professionals must adhere to strict safety protocols to<br />
|
||||||
|
protect both themselves and the occupants of the spaces they work in. Additionally, compliance with<br />
|
||||||
|
industry regulations and codes is a testament to the skilled nature of the trade, ensuring that HVAC<br />
|
||||||
|
systems meet the highest standards of safety and efficiency.</p>
|
||||||
|
<h2>Continual Learning and Certification:</h2>
|
||||||
|
<p>Unlike a labor job, HVAC professionals engage in continual learning to stay current with industry<br />
|
||||||
|
trends and technological advancements. Many pursue certifications and attend training programs to<br />
|
||||||
|
enhance their skills and expand their knowledge base. This commitment to ongoing education is a<br />
|
||||||
|
hallmark of skilled trades.</p>
|
||||||
|
<h2>Conclusion:</h2>
|
||||||
|
<p>Heating, Ventilation, and Air Conditioning is undeniably a skilled trade that goes beyond the<br />
|
||||||
|
perception of a labor job. Labor jobs are also very important to the function of society and I have<br />
|
||||||
|
proudly done these jobs myself. The technical proficiency, problem-solving abilities, adaptability,<br />
|
||||||
|
and commitment to safety make HVAC professionals essential contributors to the creation of<br />
|
||||||
|
comfortable and efficient indoor environments. It is crucial to recognize and appreciate the skill<br />
|
||||||
|
set inherent in the HVAC trade, as it plays a vital role in shaping the quality of life for<br />
|
||||||
|
individuals and the functionality of diverse spaces.</p>
|
||||||
|
<ul>
|
||||||
|
<li>Ty Branaman</li>
|
||||||
|
</ul>
|
||||||
|
</article>
|
||||||
|
<div class="border-t border-light mt-8 pt-8">
|
||||||
|
<h2 class="text-4xl font-extrabold mb-8">
|
||||||
|
Written by
|
||||||
|
</h2>
|
||||||
|
<div class="flex flex-col lg:flex-row gap-8">
|
||||||
|
<div class="flex-[0_0_120px]">
|
||||||
|
<img class="w-[120px] h-[120px] rounded-full" src="/static/images/avatar.png"/>
|
||||||
|
</div>
|
||||||
|
<div class="prose">
|
||||||
|
<h3 class="!m-0">
|
||||||
|
Michael Housh
|
||||||
|
</h3>
|
||||||
|
<p class="text-gray">
|
||||||
|
HVAC business owner with over 27 years of experience. Writes articles about HVAC,
|
||||||
|
Programming, Home-Performance, and Building Science
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-16">
|
||||||
|
<h2 class="text-4xl font-extrabold mb-8">
|
||||||
|
More articles
|
||||||
|
</h2>
|
||||||
|
<div class="grid lg:grid-cols-2 gap-10">
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2025/vapor-htmx-todo-app/">Vapor + HTMX</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">January 05, 2025</span><a href="/articles/tag/general/">general</a>, <a href="/articles/tag/programming/">programming</a> and <a href="/articles/tag/software/">software</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2025/vapor-htmx-todo-app/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2025-01-05-vapor-htmx-todo-app.png"/>
|
||||||
|
Build an example application using Vapor and HTMX.
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2024/free-as-in-freedom/">Free As In Freedom</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">April 09, 2024</span><a href="/articles/tag/general/">general</a>, <a href="/articles/tag/open-source/">open-source</a> and <a href="/articles/tag/software/">software</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2024/free-as-in-freedom/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2024-04-09-free-as-in-freedom.png"/>
|
||||||
|
Salute to open-source software engineers
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<p class="prose mt-8">
|
||||||
|
<a href="/articles/">› See all articles</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="site-footer container text-gray gray-links border-t border-light text-center pt-6 mt-8 text-sm">
|
||||||
|
<p>
|
||||||
|
Copyright © Michael Housh 2023-2025.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Built in Swift using
|
||||||
|
<a href="https://github.com/loopwerk/Saga" rel="nofollow" target="_blank">Saga</a>
|
||||||
|
(<a href="https://github.com/m-housh/mhoush.com" rel="nofollow" target="_blank">source</a>).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="http://localhost:3000/articles/feed.xml" rel="nofollow" target="_blank">RSS</a>
|
||||||
|
|
|
||||||
|
<a href="https://github.com/m-housh" rel="nofollow" target="_blank">Github</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.youtube.com/channel/UCb58SeURd5bObfTiL0KoliA" rel="nofollow" target="_blank">Youtube</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.facebook.com/michael.housh" rel="nofollow" target="_blank">Facebook</a>
|
||||||
|
|
|
||||||
|
<a href="mailto:michael@mhoush.com" rel="nofollow">Email</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
227
deploy/articles/2024/free-as-in-freedom/index.html
Normal file
227
deploy/articles/2024/free-as-in-freedom/index.html
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en-US">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta content="#0e1112" media="(prefers-color-scheme: dark)" name="theme-color"/>
|
||||||
|
<meta content="#566B78" media="(prefers-color-scheme: light)" name="theme-color"/>
|
||||||
|
<meta content="Michael Housh" name="author"/>
|
||||||
|
<meta content="Mhoush" name="apple-mobile-web-app-title"/>
|
||||||
|
<meta content="initial-scale=1.0, width=device-width" name="viewport"/>
|
||||||
|
<meta content="telephone=no" name="format-detection"/>
|
||||||
|
<meta content="True" name="HandheldFriendly"/>
|
||||||
|
<meta content="320" name="MobileOptimized"/>
|
||||||
|
<meta content="Mhoush" name="og:site_name"/>
|
||||||
|
<meta content="hvac, developer, swift, home-performance, design" name="keywords"/>
|
||||||
|
<title>
|
||||||
|
mhoush: Free As In Freedom
|
||||||
|
</title>
|
||||||
|
<link href="/static/favicon.ico" rel="shortcut icon"/>
|
||||||
|
<link href="/static/output.css" rel="stylesheet"/>
|
||||||
|
<link href="/static/style.css" rel="stylesheet"/>
|
||||||
|
<link href="/articles/feed.xml" rel="alternate" title="mhoush" type="application/rss+xml"/>
|
||||||
|
<link href="/static/prism.css" rel="stylesheet"/>
|
||||||
|
<meta content="Salute to open-source software engineers" name="description"/>
|
||||||
|
<meta content="summary_large_image" name="twitter:card"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images/2024-04-09-free-as-in-freedom.png" name="twitter:image"/>
|
||||||
|
<meta content="Free As In Freedom" name="twitter:image:alt"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images//articles/2024/free-as-in-freedom/" name="og:url"/>
|
||||||
|
<meta content="Free As In Freedom" name="og:title"/>
|
||||||
|
<meta content="Salute to open-source software engineers" name="og:description"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images/2024-04-09-free-as-in-freedom.png" name="og:image"/>
|
||||||
|
<meta content="1014" name="og:image:width"/>
|
||||||
|
<meta content="530" name="og:image:height"/>
|
||||||
|
<script crossorigin="anonymous" src="https://kit.fontawesome.com/f209982030.js">
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body class="bg-page text-white pb-5 font-avenir articles">
|
||||||
|
<header class="bg-nav text-gray py-4 text-base/6 lg:fixed w-full lg:h-[62px]">
|
||||||
|
<nav class="container flex gap-x-5 lg:gap-x-y items-center">
|
||||||
|
<ul class="flex flex-wrap gap-x-2 lg:gap-x-5">
|
||||||
|
<li>
|
||||||
|
<a class href="/">Home</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="active" href="/articles/">Articles</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class href="/about/">About</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<div class="container pt-12 lg:pt-28">
|
||||||
|
<article class="prose">
|
||||||
|
<h1>
|
||||||
|
Free As In Freedom
|
||||||
|
</h1>
|
||||||
|
<div class="-mt-6">
|
||||||
|
<div class="text-gray gray-links text-sm">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">April 09, 2024</span>1007 words, posted in <a href="/articles/tag/general/">general</a>, <a href="/articles/tag/open-source/">open-source</a> and <a href="/articles/tag/software/">software</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2024-04-09-free-as-in-freedom.png"/>
|
||||||
|
<p>This is a hot take kind of article, but here it goes the rant.</p>
|
||||||
|
<h2>This applies to me and you.</h2>
|
||||||
|
<p>I’m writing this to remind myself somethings that I too often take for granted. I am going to<br />
|
||||||
|
preface this whole article by saying that everything I’m going to lay out / mention is something<br />
|
||||||
|
that I am personally guilty of. This is an open reminder and call out of things that I feel should<br />
|
||||||
|
change.</p>
|
||||||
|
<h1>Our perspective is flawed</h1>
|
||||||
|
<p>Nobody can dispute that the advances in technology have greatly improved our lives. Like anything,<br />
|
||||||
|
though, there is a trade off.</p>
|
||||||
|
<h2>What is FOSS</h2>
|
||||||
|
<p>FOSS is an acronym for “Free and Open Source Software”. It is generally about how software is<br />
|
||||||
|
licensed, meaning that the source code is available in the public for review, allowing a broader<br />
|
||||||
|
spectrum of people than the originators of the code to have input, look for bugs, redistribute the<br />
|
||||||
|
software, contribute, etc. It does not however mean that the software should be no cost to the end<br />
|
||||||
|
user.</p>
|
||||||
|
<p>This is where the word “freedom” comes into it. Overtime, as a society, we generally now think of<br />
|
||||||
|
FOSS as “free” software. This takes what was originally a noble / courageous idea and devalues it to<br />
|
||||||
|
the point that we now expect things to be free. It encourages corporate greed to take advantage of<br />
|
||||||
|
people who created something to solve a particular need, or as a hobby, expecting the creator to<br />
|
||||||
|
handle the burden of maintaining / patching bugs while they profit from it. Don’t get me wrong,<br />
|
||||||
|
these corporations will also contribute back, sometimes even donate money to the creators. I am not<br />
|
||||||
|
at all opposed to capitalism, nor saying that these corporations are in the wrong. At the end of the<br />
|
||||||
|
day, <strong><em>we</em></strong> created this problem.</p>
|
||||||
|
<h2>Current state and how we got here</h2>
|
||||||
|
<p>Software services / giants create applications that we come to rely on. They tempt / bait us with<br />
|
||||||
|
them being “free” or cheap, but that is because <strong><em>we</em></strong> are their target. They bloat the software<br />
|
||||||
|
with tracking and telemetry to capture data about us and sell us more products and services. Once<br />
|
||||||
|
again, if you’re pro-capitalism, it’s somewhat hard to blame them for this. We’re the gullible sheep<br />
|
||||||
|
who will blindly eat out their grain bins.</p>
|
||||||
|
<p>I can remember back in the day when there were music pirating services on the internet (napster is<br />
|
||||||
|
the one that comes to mind). As a giant music buff, I quickly jumped on board with services like<br />
|
||||||
|
these. Back in those days, I was young, didn’t make very much money, so it was hard to afford the<br />
|
||||||
|
latest and greatest tunes. I also remember back in this time frame a lawsuit from the metal giants<br />
|
||||||
|
Metallica (other’s words not mine ;)). At the time I remember thinking, like many others, that<br />
|
||||||
|
Metallica didn’t need the money, but then a comment from Lars Ulrich the band’s drummer struck a<br />
|
||||||
|
cord with me (pun intended). I’ll will paraphrase here, but it was something along the lines of<br />
|
||||||
|
“We’re not pursuing this for us, but for all of those (musicians) that come after us”. After this<br />
|
||||||
|
and reflection, I decided that I would not pirate music anymore.</p>
|
||||||
|
<p>Fast forward, now the majority do not purchases music / albums, we typically utilize streaming<br />
|
||||||
|
services (myself included), sure it may be more fair to the artists than pirating was, it can be<br />
|
||||||
|
argued that it’s easier today for independent artists to become known / discovered, I’m also in no<br />
|
||||||
|
way saying the old school music industry wasn’t a giant pile of dog poo, but I am saying that who is<br />
|
||||||
|
really winning(?), it’s the Spotify’s and Apple Music’s of the world, that’s who.</p>
|
||||||
|
<p>I’m also reminded of the great “MeasureQuick is now charging for services” that happened in the HVAC<br />
|
||||||
|
industry. I have personally never complained and have always supported this decision, because it is<br />
|
||||||
|
not sustainable to run a software company and not charge for services, generally. Sure, you may not<br />
|
||||||
|
like their pricing model, etc. Where I think they went wrong was not charging from the beginning, as<br />
|
||||||
|
it sets the wrong expectation that is presumably hard to recover from. There are those who took some<br />
|
||||||
|
of Jim’s words / opinions in a way different from how I do / did, which is fine, we’re all entitled<br />
|
||||||
|
to our opinions. What is often forgotten is that we’re all also entitled to change those opinions.<br />
|
||||||
|
Heck, I will probably be shouting a different story tomorrow, so be it!</p>
|
||||||
|
<h2>Conclusion</h2>
|
||||||
|
<p>What I would like to encourage people to do is to support software development. If an application is<br />
|
||||||
|
free, but has a donate button consider giving a donation. If an application is free and they don’t<br />
|
||||||
|
want to charge that’s fine too, however I would say to be suspicous, meaning is it free because<br />
|
||||||
|
<strong><em>you</em></strong> are the product?!?</p>
|
||||||
|
<p>I would also encourage you to be active in communities and organizations that foster community (HVAC<br />
|
||||||
|
School is a great example). Show appreciation and encouragement, but at the same time don’t be<br />
|
||||||
|
afraid to be critical or speak up.</p>
|
||||||
|
<p>At the end of the day, I hope to lift up my brothers and sisters, help to fight against the<br />
|
||||||
|
corporations who abuse the little guy’s and hopefully feel good about my decisions.</p>
|
||||||
|
<p>Over the last few weeks, I have been going through my software and services and looking for those<br />
|
||||||
|
donation buttons and giving back a little bit for the software that makes my life better. Help<br />
|
||||||
|
change the narrative and remember that it’s about <strong><em>Freedom not Free</em></strong>.</p>
|
||||||
|
<h3>Links</h3>
|
||||||
|
<ul>
|
||||||
|
<li><a href="https://en.wikipedia.org/wiki/Open-source_software">Open-source Software</a></li>
|
||||||
|
<li><a href="https://en.wikipedia.org/wiki/Free_Software_Foundation">Free Software Fondation</a></li>
|
||||||
|
<li><a href="https://www.eff.org/">Electronic Frontier Foundation</a></li>
|
||||||
|
</ul>
|
||||||
|
<h3>Software used in this blog.</h3>
|
||||||
|
<ul>
|
||||||
|
<li><a href="https://neovim.io/">Neovim</a></li>
|
||||||
|
<li><a href="https://gohugo.io/">Hugo</a></li>
|
||||||
|
<li><a href="https://themes.gohugo.io/themes/poison/">Hugo Theme</a></li>
|
||||||
|
</ul>
|
||||||
|
<blockquote>
|
||||||
|
<p><strong>Note:</strong> I do not use any trackers or analytics on this site to respect your privacy. So feel<br />
|
||||||
|
free to contact me directly to share feedback or let me know how I’m doing.</p>
|
||||||
|
</blockquote>
|
||||||
|
</article>
|
||||||
|
<div class="border-t border-light mt-8 pt-8">
|
||||||
|
<h2 class="text-4xl font-extrabold mb-8">
|
||||||
|
Written by
|
||||||
|
</h2>
|
||||||
|
<div class="flex flex-col lg:flex-row gap-8">
|
||||||
|
<div class="flex-[0_0_120px]">
|
||||||
|
<img class="w-[120px] h-[120px] rounded-full" src="/static/images/avatar.png"/>
|
||||||
|
</div>
|
||||||
|
<div class="prose">
|
||||||
|
<h3 class="!m-0">
|
||||||
|
Michael Housh
|
||||||
|
</h3>
|
||||||
|
<p class="text-gray">
|
||||||
|
HVAC business owner with over 27 years of experience. Writes articles about HVAC,
|
||||||
|
Programming, Home-Performance, and Building Science
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-16">
|
||||||
|
<h2 class="text-4xl font-extrabold mb-8">
|
||||||
|
More articles
|
||||||
|
</h2>
|
||||||
|
<div class="grid lg:grid-cols-2 gap-10">
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2025/vapor-htmx-todo-app/">Vapor + HTMX</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">January 05, 2025</span><a href="/articles/tag/general/">general</a>, <a href="/articles/tag/programming/">programming</a> and <a href="/articles/tag/software/">software</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2025/vapor-htmx-todo-app/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2025-01-05-vapor-htmx-todo-app.png"/>
|
||||||
|
Build an example application using Vapor and HTMX.
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2024/pgp-encryption-introduction/">PGP Encryption Introduction</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">April 04, 2024</span><a href="/articles/tag/gnupgp/">GnuPGP</a>, <a href="/articles/tag/pgp/">PGP</a>, <a href="/articles/tag/programming/">programming</a> and <a href="/articles/tag/security/">security</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2024/pgp-encryption-introduction/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2024-04-04-pgp-encryption-introduction.gif"/>
|
||||||
|
In this article I introduce PGP and show a use case for me, which perhaps you can use as well.
|
||||||
|
What is PGP
|
||||||
|
PGP stands for Pretty Good Privacy, it was first developed in 1991 by Phil Zimmermann. PGP uses
|
||||||
|
cryptographic privacy and authentication and is...
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<p class="prose mt-8">
|
||||||
|
<a href="/articles/">› See all articles</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="site-footer container text-gray gray-links border-t border-light text-center pt-6 mt-8 text-sm">
|
||||||
|
<p>
|
||||||
|
Copyright © Michael Housh 2023-2025.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Built in Swift using
|
||||||
|
<a href="https://github.com/loopwerk/Saga" rel="nofollow" target="_blank">Saga</a>
|
||||||
|
(<a href="https://github.com/m-housh/mhoush.com" rel="nofollow" target="_blank">source</a>).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="http://localhost:3000/articles/feed.xml" rel="nofollow" target="_blank">RSS</a>
|
||||||
|
|
|
||||||
|
<a href="https://github.com/m-housh" rel="nofollow" target="_blank">Github</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.youtube.com/channel/UCb58SeURd5bObfTiL0KoliA" rel="nofollow" target="_blank">Youtube</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.facebook.com/michael.housh" rel="nofollow" target="_blank">Facebook</a>
|
||||||
|
|
|
||||||
|
<a href="mailto:michael@mhoush.com" rel="nofollow">Email</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
115
deploy/articles/2024/index.html
Normal file
115
deploy/articles/2024/index.html
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en-US">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta content="#0e1112" media="(prefers-color-scheme: dark)" name="theme-color"/>
|
||||||
|
<meta content="#566B78" media="(prefers-color-scheme: light)" name="theme-color"/>
|
||||||
|
<meta content="Michael Housh" name="author"/>
|
||||||
|
<meta content="Mhoush" name="apple-mobile-web-app-title"/>
|
||||||
|
<meta content="initial-scale=1.0, width=device-width" name="viewport"/>
|
||||||
|
<meta content="telephone=no" name="format-detection"/>
|
||||||
|
<meta content="True" name="HandheldFriendly"/>
|
||||||
|
<meta content="320" name="MobileOptimized"/>
|
||||||
|
<meta content="Mhoush" name="og:site_name"/>
|
||||||
|
<meta content="hvac, developer, swift, home-performance, design" name="keywords"/>
|
||||||
|
<title>
|
||||||
|
mhoush: Articles in 2024
|
||||||
|
</title>
|
||||||
|
<link href="/static/favicon.ico" rel="shortcut icon"/>
|
||||||
|
<link href="/static/output.css" rel="stylesheet"/>
|
||||||
|
<link href="/static/style.css" rel="stylesheet"/>
|
||||||
|
<link href="/articles/feed.xml" rel="alternate" title="mhoush" type="application/rss+xml"/>
|
||||||
|
</head>
|
||||||
|
<body class="bg-page text-white pb-5 font-avenir articles">
|
||||||
|
<header class="bg-nav text-gray py-4 text-base/6 lg:fixed w-full lg:h-[62px]">
|
||||||
|
<nav class="container flex gap-x-5 lg:gap-x-y items-center">
|
||||||
|
<ul class="flex flex-wrap gap-x-2 lg:gap-x-5">
|
||||||
|
<li>
|
||||||
|
<a class href="/">Home</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="active" href="/articles/">Articles</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class href="/about/">About</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<div class="container pt-12 lg:pt-28">
|
||||||
|
<section class="mb-10">
|
||||||
|
<h1 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2024/free-as-in-freedom/">Free As In Freedom</a>
|
||||||
|
</h1>
|
||||||
|
<div class="text-gray gray-links text-sm">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">April 09, 2024</span>1007 words, posted in <a href="/articles/tag/general/">general</a>, <a href="/articles/tag/open-source/">open-source</a> and <a href="/articles/tag/software/">software</a>
|
||||||
|
</div>
|
||||||
|
<p class="mt-4">
|
||||||
|
<a href="/articles/2024/free-as-in-freedom/">Salute to open-source software engineers</a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section class="mb-10">
|
||||||
|
<h1 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2024/pgp-encryption-introduction/">PGP Encryption Introduction</a>
|
||||||
|
</h1>
|
||||||
|
<div class="text-gray gray-links text-sm">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">April 04, 2024</span>840 words, posted in <a href="/articles/tag/gnupgp/">GnuPGP</a>, <a href="/articles/tag/pgp/">PGP</a>, <a href="/articles/tag/programming/">programming</a> and <a href="/articles/tag/security/">security</a>
|
||||||
|
</div>
|
||||||
|
<p class="mt-4">
|
||||||
|
<a href="/articles/2024/pgp-encryption-introduction/">In this article I introduce PGP and show a use case for me, which perhaps you can use as well.
|
||||||
|
What is PGP
|
||||||
|
PGP stands for Pretty Good Privacy, it was first developed in 1991 by Phil Zimmermann. PGP uses
|
||||||
|
cryptographic privacy and authentication and is...</a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section class="mb-10">
|
||||||
|
<h1 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2024/unvr-as-nas/">UNVR as NAS</a>
|
||||||
|
</h1>
|
||||||
|
<div class="text-gray gray-links text-sm">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">March 15, 2024</span>634 words, posted in <a href="/articles/tag/how-to/">how-to</a>, <a href="/articles/tag/nas/">nas</a>, <a href="/articles/tag/networking/">networking</a> and <a href="/articles/tag/programming/">programming</a>
|
||||||
|
</div>
|
||||||
|
<p class="mt-4">
|
||||||
|
<a href="/articles/2024/unvr-as-nas/">In this post, I’m going to show how to setup a Samba server on a Ubiquity UNVR so that it can be
|
||||||
|
used as NAS (network attached storage). Be aware that this should be done with caution and may void
|
||||||
|
any warranty on your UNVR as we are using it for...</a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section class="mb-10">
|
||||||
|
<h1 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2024/elevating-hvac/">Elevating HVAC: A Skilled Trade Beyond Labor</a>
|
||||||
|
</h1>
|
||||||
|
<div class="text-gray gray-links text-sm">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">February 27, 2024</span>535 words, posted in <a href="/articles/tag/hvac/">HVAC</a>
|
||||||
|
</div>
|
||||||
|
<p class="mt-4">
|
||||||
|
<a href="/articles/2024/elevating-hvac/">This is a guest post from my good friend, Ty Branaman.
|
||||||
|
Introduction:
|
||||||
|
Heating, Ventilation, and Air Conditioning (HVAC) is often mistakenly categorized as a simple labor
|
||||||
|
job, overshadowing the intricate skill set and technical expertise required in...</a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<div class="site-footer container text-gray gray-links border-t border-light text-center pt-6 mt-8 text-sm">
|
||||||
|
<p>
|
||||||
|
Copyright © Michael Housh 2023-2025.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Built in Swift using
|
||||||
|
<a href="https://github.com/loopwerk/Saga" rel="nofollow" target="_blank">Saga</a>
|
||||||
|
(<a href="https://github.com/m-housh/mhoush.com" rel="nofollow" target="_blank">source</a>).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="http://localhost:3000/articles/feed.xml" rel="nofollow" target="_blank">RSS</a>
|
||||||
|
|
|
||||||
|
<a href="https://github.com/m-housh" rel="nofollow" target="_blank">Github</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.youtube.com/channel/UCb58SeURd5bObfTiL0KoliA" rel="nofollow" target="_blank">Youtube</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.facebook.com/michael.housh" rel="nofollow" target="_blank">Facebook</a>
|
||||||
|
|
|
||||||
|
<a href="mailto:michael@mhoush.com" rel="nofollow">Email</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
221
deploy/articles/2024/pgp-encryption-introduction/index.html
Normal file
221
deploy/articles/2024/pgp-encryption-introduction/index.html
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en-US">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta content="#0e1112" media="(prefers-color-scheme: dark)" name="theme-color"/>
|
||||||
|
<meta content="#566B78" media="(prefers-color-scheme: light)" name="theme-color"/>
|
||||||
|
<meta content="Michael Housh" name="author"/>
|
||||||
|
<meta content="Mhoush" name="apple-mobile-web-app-title"/>
|
||||||
|
<meta content="initial-scale=1.0, width=device-width" name="viewport"/>
|
||||||
|
<meta content="telephone=no" name="format-detection"/>
|
||||||
|
<meta content="True" name="HandheldFriendly"/>
|
||||||
|
<meta content="320" name="MobileOptimized"/>
|
||||||
|
<meta content="Mhoush" name="og:site_name"/>
|
||||||
|
<meta content="hvac, developer, swift, home-performance, design" name="keywords"/>
|
||||||
|
<title>
|
||||||
|
mhoush: PGP Encryption Introduction
|
||||||
|
</title>
|
||||||
|
<link href="/static/favicon.ico" rel="shortcut icon"/>
|
||||||
|
<link href="/static/output.css" rel="stylesheet"/>
|
||||||
|
<link href="/static/style.css" rel="stylesheet"/>
|
||||||
|
<link href="/articles/feed.xml" rel="alternate" title="mhoush" type="application/rss+xml"/>
|
||||||
|
<link href="/static/prism.css" rel="stylesheet"/>
|
||||||
|
<meta content="In this article I introduce PGP and show a use case for me, which perhaps you can use as well.
|
||||||
|
What is PGP
|
||||||
|
PGP stands for Pretty Good Privacy, it was first developed in 1991 by Phil Zimmermann. PGP uses
|
||||||
|
cryptographic privacy and authentication and is..." name="description"/>
|
||||||
|
<meta content="summary_large_image" name="twitter:card"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images/2024-04-04-pgp-encryption-introduction.gif" name="twitter:image"/>
|
||||||
|
<meta content="PGP Encryption Introduction" name="twitter:image:alt"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images//articles/2024/pgp-encryption-introduction/" name="og:url"/>
|
||||||
|
<meta content="PGP Encryption Introduction" name="og:title"/>
|
||||||
|
<meta content="In this article I introduce PGP and show a use case for me, which perhaps you can use as well.
|
||||||
|
What is PGP
|
||||||
|
PGP stands for Pretty Good Privacy, it was first developed in 1991 by Phil Zimmermann. PGP uses
|
||||||
|
cryptographic privacy and authentication and is..." name="og:description"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images/2024-04-04-pgp-encryption-introduction.gif" name="og:image"/>
|
||||||
|
<meta content="1014" name="og:image:width"/>
|
||||||
|
<meta content="530" name="og:image:height"/>
|
||||||
|
<script crossorigin="anonymous" src="https://kit.fontawesome.com/f209982030.js">
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body class="bg-page text-white pb-5 font-avenir articles">
|
||||||
|
<header class="bg-nav text-gray py-4 text-base/6 lg:fixed w-full lg:h-[62px]">
|
||||||
|
<nav class="container flex gap-x-5 lg:gap-x-y items-center">
|
||||||
|
<ul class="flex flex-wrap gap-x-2 lg:gap-x-5">
|
||||||
|
<li>
|
||||||
|
<a class href="/">Home</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="active" href="/articles/">Articles</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class href="/about/">About</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<div class="container pt-12 lg:pt-28">
|
||||||
|
<article class="prose">
|
||||||
|
<h1>
|
||||||
|
PGP Encryption Introduction
|
||||||
|
</h1>
|
||||||
|
<div class="-mt-6">
|
||||||
|
<div class="text-gray gray-links text-sm">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">April 04, 2024</span>840 words, posted in <a href="/articles/tag/gnupgp/">GnuPGP</a>, <a href="/articles/tag/pgp/">PGP</a>, <a href="/articles/tag/programming/">programming</a> and <a href="/articles/tag/security/">security</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2024-04-04-pgp-encryption-introduction.gif"/>
|
||||||
|
<p>In this article I introduce PGP and show a use case for me, which perhaps you can use as well.</p>
|
||||||
|
<h2>What is PGP</h2>
|
||||||
|
<p>PGP stands for <strong>Pretty Good Privacy</strong>, it was first developed in 1991 by Phil Zimmermann. PGP uses<br />
|
||||||
|
cryptographic privacy and authentication and is generally used in data communication.</p>
|
||||||
|
<p>According to <a href="https://en.wikipedia.org/wiki/Pretty_Good_Privacy">Wikipedia</a> it’s name was inspired<br />
|
||||||
|
by a grocery store named, “Ralph’s Pretty Goody Grocery” featured in radio host’s Garrison Keillor’s<br />
|
||||||
|
fictional town of Lake Wobegon.</p>
|
||||||
|
<p>PGP is commonly used in software development to “sign” software commits or files to help ensure both<br />
|
||||||
|
who the commits were from as well as make sure they were not modified from the original versions.</p>
|
||||||
|
<p>It should also be noted that when people say PGP they are often referring to OpenPGP or GnuPGP which<br />
|
||||||
|
are implementations of the PGP standard protocol.</p>
|
||||||
|
<h2>What it does</h2>
|
||||||
|
<blockquote>
|
||||||
|
<p>Note: I am in no way a cyber-security expert, I am a layman and only describing things in terms<br />
|
||||||
|
that I understand / make sense to me. Do what I do at your own risk!</p>
|
||||||
|
</blockquote>
|
||||||
|
<p>PGP offers both symmetrical encryption (uses a session key and password) or asymmetrical encryption<br />
|
||||||
|
(uses a session key and a private key). Asymmetrical encryption is more secure but is more resource<br />
|
||||||
|
intensive (which is generally not a problem with computers of today).</p>
|
||||||
|
<p>Generally speaking PGP uses what are known as public and private key pairs. The public portion of<br />
|
||||||
|
the key par is meant to be shared with others freely, while the private portion needs to be secured<br />
|
||||||
|
/ not shared with anyone <strong>EVER</strong>. It is best practice to generate your keys on a computer that is<br />
|
||||||
|
“air gapped”, meaning it is not connected to any network / internet, and does not save a history of<br />
|
||||||
|
commands performed on it.</p>
|
||||||
|
<p>PGP encrypts data (files, messages, etc.) for one or more recipients, using the recipients public<br />
|
||||||
|
key. The recipients private key is required to decrypt the data once it’s been encrypted.</p>
|
||||||
|
<p>Your key pair is tied to your identity / person, generally by your name and email(s). The key can<br />
|
||||||
|
also have multiple “subkeys”, meaning that if you have more than one public email, alias, etc. it<br />
|
||||||
|
can be tied to your same private key. This is useful for example for work vs. activism vs. software<br />
|
||||||
|
development.</p>
|
||||||
|
<p>Once your key is generated and your private key secured, you can share your public portion of the<br />
|
||||||
|
key to a “keyserver” where other people can download it and verify messages were sent by you.</p>
|
||||||
|
<h2>Web of Trust</h2>
|
||||||
|
<p>PGP also uses what is called the <strong>“Web of Trust”</strong>, which is used to validate that messages are<br />
|
||||||
|
encrypted by a trusted source. There are different levels of trust depending on where a key is<br />
|
||||||
|
retrieved from. For example, if somebody gave you their public key in person and you were able to<br />
|
||||||
|
inspect that the identity matches their government id, then you can give it a higher trust level<br />
|
||||||
|
than one that is sent / retrieved from a keyserver.</p>
|
||||||
|
<p>My understanding of this portion is that over time your key is signed by other’s with their level of<br />
|
||||||
|
certainty about you / your key, which over time increases the overall trust in your key.</p>
|
||||||
|
<h2>Out of the weeds</h2>
|
||||||
|
<p>Now that we’ve got an understanding of some of the technical aspects, lets talk about some real use<br />
|
||||||
|
cases of PGP encryption.</p>
|
||||||
|
<p>PGP encryption is used by some email clients / applications, such as<br />
|
||||||
|
<a href="https://canarymail.io/">Canary</a>,<br />
|
||||||
|
<a href="https://www.thunderbird.net/en-US/thunderbird/115.0/holidayeoy/">Thunderbird</a>, or<br />
|
||||||
|
<a href="https://gpgtools.tenderapp.com/">GPGSuite</a>.</p>
|
||||||
|
<p>In my understanding, it is also what is used in devices such as a<br />
|
||||||
|
<a href="https://www.yubico.com/">YubiKey</a>.</p>
|
||||||
|
<p>Many of the mentioned applications allow for an easier interface / adoption, as one of the reasons<br />
|
||||||
|
it is not very popular is that it can be hard to use PGP for the average person.</p>
|
||||||
|
<p>Aside from using my PGP key for signing software commits, my major use case is for encrypting files<br />
|
||||||
|
that I store in a “cloud” provider. Know that when someone says the “cloud”, it is really just a<br />
|
||||||
|
computer (in reality a gang of computers in a data center). You are solely reliant that these cloud<br />
|
||||||
|
providers are not snooping on, inspecting, or even selling your data.</p>
|
||||||
|
<p>Of course, some data may not be that sensitive, so maybe you don’t care. However with a little bit<br />
|
||||||
|
of effort on your part you can at least make it very hard for anyone to know what is inside your<br />
|
||||||
|
documents. You can be in control of the way your items are encrypted and have confidence that nobody<br />
|
||||||
|
but you can access what is inside your documents.</p>
|
||||||
|
<p>Heck, I even encrypt documents that are stored on my own network / computer so that if something<br />
|
||||||
|
get’s stolen or someone breach’s my network they will not be able to easily get to sensitive data.</p>
|
||||||
|
<h2>Conclusion</h2>
|
||||||
|
<p>This article is just meant as an overview of PGP encryption. In future articles I will show you how<br />
|
||||||
|
to use it to encrypt your data and be in control of your privacy.</p>
|
||||||
|
<h3>Resources</h3>
|
||||||
|
<ul>
|
||||||
|
<li><a href="https://gnupg.org/">GnuPG</a></li>
|
||||||
|
<li><a href="https://www.openpgp.org/">OpenPGP</a></li>
|
||||||
|
<li><a href="https://gpg.wtf/">gpg.wtf</a></li>
|
||||||
|
<li><a href="https://www.ietf.org/rfc/rfc4880.html">RFC4880</a></li>
|
||||||
|
</ul>
|
||||||
|
</article>
|
||||||
|
<div class="border-t border-light mt-8 pt-8">
|
||||||
|
<h2 class="text-4xl font-extrabold mb-8">
|
||||||
|
Written by
|
||||||
|
</h2>
|
||||||
|
<div class="flex flex-col lg:flex-row gap-8">
|
||||||
|
<div class="flex-[0_0_120px]">
|
||||||
|
<img class="w-[120px] h-[120px] rounded-full" src="/static/images/avatar.png"/>
|
||||||
|
</div>
|
||||||
|
<div class="prose">
|
||||||
|
<h3 class="!m-0">
|
||||||
|
Michael Housh
|
||||||
|
</h3>
|
||||||
|
<p class="text-gray">
|
||||||
|
HVAC business owner with over 27 years of experience. Writes articles about HVAC,
|
||||||
|
Programming, Home-Performance, and Building Science
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-16">
|
||||||
|
<h2 class="text-4xl font-extrabold mb-8">
|
||||||
|
More articles
|
||||||
|
</h2>
|
||||||
|
<div class="grid lg:grid-cols-2 gap-10">
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2025/vapor-htmx-todo-app/">Vapor + HTMX</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">January 05, 2025</span><a href="/articles/tag/general/">general</a>, <a href="/articles/tag/programming/">programming</a> and <a href="/articles/tag/software/">software</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2025/vapor-htmx-todo-app/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2025-01-05-vapor-htmx-todo-app.png"/>
|
||||||
|
Build an example application using Vapor and HTMX.
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2024/free-as-in-freedom/">Free As In Freedom</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">April 09, 2024</span><a href="/articles/tag/general/">general</a>, <a href="/articles/tag/open-source/">open-source</a> and <a href="/articles/tag/software/">software</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2024/free-as-in-freedom/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2024-04-09-free-as-in-freedom.png"/>
|
||||||
|
Salute to open-source software engineers
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<p class="prose mt-8">
|
||||||
|
<a href="/articles/">› See all articles</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="site-footer container text-gray gray-links border-t border-light text-center pt-6 mt-8 text-sm">
|
||||||
|
<p>
|
||||||
|
Copyright © Michael Housh 2023-2025.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Built in Swift using
|
||||||
|
<a href="https://github.com/loopwerk/Saga" rel="nofollow" target="_blank">Saga</a>
|
||||||
|
(<a href="https://github.com/m-housh/mhoush.com" rel="nofollow" target="_blank">source</a>).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="http://localhost:3000/articles/feed.xml" rel="nofollow" target="_blank">RSS</a>
|
||||||
|
|
|
||||||
|
<a href="https://github.com/m-housh" rel="nofollow" target="_blank">Github</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.youtube.com/channel/UCb58SeURd5bObfTiL0KoliA" rel="nofollow" target="_blank">Youtube</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.facebook.com/michael.housh" rel="nofollow" target="_blank">Facebook</a>
|
||||||
|
|
|
||||||
|
<a href="mailto:michael@mhoush.com" rel="nofollow">Email</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
223
deploy/articles/2024/unvr-as-nas/index.html
Normal file
223
deploy/articles/2024/unvr-as-nas/index.html
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en-US">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta content="#0e1112" media="(prefers-color-scheme: dark)" name="theme-color"/>
|
||||||
|
<meta content="#566B78" media="(prefers-color-scheme: light)" name="theme-color"/>
|
||||||
|
<meta content="Michael Housh" name="author"/>
|
||||||
|
<meta content="Mhoush" name="apple-mobile-web-app-title"/>
|
||||||
|
<meta content="initial-scale=1.0, width=device-width" name="viewport"/>
|
||||||
|
<meta content="telephone=no" name="format-detection"/>
|
||||||
|
<meta content="True" name="HandheldFriendly"/>
|
||||||
|
<meta content="320" name="MobileOptimized"/>
|
||||||
|
<meta content="Mhoush" name="og:site_name"/>
|
||||||
|
<meta content="hvac, developer, swift, home-performance, design" name="keywords"/>
|
||||||
|
<title>
|
||||||
|
mhoush: UNVR as NAS
|
||||||
|
</title>
|
||||||
|
<link href="/static/favicon.ico" rel="shortcut icon"/>
|
||||||
|
<link href="/static/output.css" rel="stylesheet"/>
|
||||||
|
<link href="/static/style.css" rel="stylesheet"/>
|
||||||
|
<link href="/articles/feed.xml" rel="alternate" title="mhoush" type="application/rss+xml"/>
|
||||||
|
<link href="/static/prism.css" rel="stylesheet"/>
|
||||||
|
<meta content="In this post, I’m going to show how to setup a Samba server on a Ubiquity UNVR so that it can be
|
||||||
|
used as NAS (network attached storage). Be aware that this should be done with caution and may void
|
||||||
|
any warranty on your UNVR as we are using it for..." name="description"/>
|
||||||
|
<meta content="summary_large_image" name="twitter:card"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images/2024-03-15-unvr-as-nas.png" name="twitter:image"/>
|
||||||
|
<meta content="UNVR as NAS" name="twitter:image:alt"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images//articles/2024/unvr-as-nas/" name="og:url"/>
|
||||||
|
<meta content="UNVR as NAS" name="og:title"/>
|
||||||
|
<meta content="In this post, I’m going to show how to setup a Samba server on a Ubiquity UNVR so that it can be
|
||||||
|
used as NAS (network attached storage). Be aware that this should be done with caution and may void
|
||||||
|
any warranty on your UNVR as we are using it for..." name="og:description"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images/2024-03-15-unvr-as-nas.png" name="og:image"/>
|
||||||
|
<meta content="1014" name="og:image:width"/>
|
||||||
|
<meta content="530" name="og:image:height"/>
|
||||||
|
<script crossorigin="anonymous" src="https://kit.fontawesome.com/f209982030.js">
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body class="bg-page text-white pb-5 font-avenir articles">
|
||||||
|
<header class="bg-nav text-gray py-4 text-base/6 lg:fixed w-full lg:h-[62px]">
|
||||||
|
<nav class="container flex gap-x-5 lg:gap-x-y items-center">
|
||||||
|
<ul class="flex flex-wrap gap-x-2 lg:gap-x-5">
|
||||||
|
<li>
|
||||||
|
<a class href="/">Home</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="active" href="/articles/">Articles</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class href="/about/">About</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<div class="container pt-12 lg:pt-28">
|
||||||
|
<article class="prose">
|
||||||
|
<h1>
|
||||||
|
UNVR as NAS
|
||||||
|
</h1>
|
||||||
|
<div class="-mt-6">
|
||||||
|
<div class="text-gray gray-links text-sm">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">March 15, 2024</span>634 words, posted in <a href="/articles/tag/how-to/">how-to</a>, <a href="/articles/tag/nas/">nas</a>, <a href="/articles/tag/networking/">networking</a> and <a href="/articles/tag/programming/">programming</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2024-03-15-unvr-as-nas.png"/>
|
||||||
|
<p>In this post, I’m going to show how to setup a Samba server on a Ubiquity UNVR so that it can be<br />
|
||||||
|
used as NAS (network attached storage). Be aware that this should be done with caution and may void<br />
|
||||||
|
any warranty on your UNVR as we are using it for purposes beyond it’s original intent. It’s also<br />
|
||||||
|
possible that this setup will break when / if updating the UNVR software. With that said, let’s jump<br />
|
||||||
|
in.</p>
|
||||||
|
<p>This post follows along with<br />
|
||||||
|
<a href="https://www.reddit.com/r/Ubiquiti/comments/11o7v8l/how_to_use_the_unvr_as_a_nas_instructions/">this reddit post</a>,<br />
|
||||||
|
with some adaptations to get it to work on the latest Unifi-OS release of <code>3.2.12</code>.</p>
|
||||||
|
<h2>Step One - Setup SSH & Login</h2>
|
||||||
|
<p>In your unifi network console you need to enable the <code>SSH</code> login option and set a secure password<br />
|
||||||
|
for the root user to login to the UNVR.</p>
|
||||||
|
<p><img src="/articles/images/2024-03-15-ssh.png" alt="ssh.png" /></p>
|
||||||
|
<p>Once that is complete you can login to your UNVR using your terminal and the IP address of your UNVR<br />
|
||||||
|
on your network.</p>
|
||||||
|
<p><code>ssh root@192.168.1.10</code></p>
|
||||||
|
<h2>Step Two - Install Samba</h2>
|
||||||
|
<p>First, we’ll update the package registry information.</p>
|
||||||
|
<p><code>apt-get update</code></p>
|
||||||
|
<p>Next, install samba.</p>
|
||||||
|
<p><code>apt-get install samba</code></p>
|
||||||
|
<h2>Step Three - Setup Samba</h2>
|
||||||
|
<p>In order to edit the configuration we are going to need to install your terminal based text editor<br />
|
||||||
|
of choice (generally nano or vim), for me I will install vim.</p>
|
||||||
|
<p><code>apt-get install vim</code></p>
|
||||||
|
<p>Create a backup of the default configuration.</p>
|
||||||
|
<p><code>cp /etc/samba/smb.conf /etc/samba/smb.conf.bak</code></p>
|
||||||
|
<p>Open the configuration file to be edited.</p>
|
||||||
|
<p><code>vim /etc/samba/smb.conf</code></p>
|
||||||
|
<p>Just above the <code>Share Definitions</code> section of the configuration, I added some global settings to<br />
|
||||||
|
make the samba server act better for time machine backups.</p>
|
||||||
|
<pre><code>#======================= MacOS Client Optimizations =======================
|
||||||
|
vfs objects = fruit streams_xattr
|
||||||
|
fruit:metadata = stream
|
||||||
|
fruit:model = MacSamba
|
||||||
|
fruit:posix_rename = yes
|
||||||
|
fruit:veto_appledouble = no
|
||||||
|
fruit:nfs_aces = no
|
||||||
|
fruit:wipe_intentionally_left_blank_rfork = yes
|
||||||
|
fruit:delete_empty_adfiles = yes
|
||||||
|
|
||||||
|
</code></pre>
|
||||||
|
<p>Also because we want users we create to be able to read and write to their home directories created<br />
|
||||||
|
on the samba server, we need to change the option under the <code>[homes]</code> share definition to be<br />
|
||||||
|
<code>read only = no</code>.</p>
|
||||||
|
<p>That is our primary configuration. You can add more share definitions at the bottom of the file to<br />
|
||||||
|
suit your use case, there are decent examples of this in the original reddit post, linked in the<br />
|
||||||
|
beginning.</p>
|
||||||
|
<p>Save and exit the file.</p>
|
||||||
|
<p><code>:wq</code></p>
|
||||||
|
<h2>Step Four - Start Samba</h2>
|
||||||
|
<p>Use the following command to start the samba server.</p>
|
||||||
|
<p><code>sudo service smbd start</code></p>
|
||||||
|
<p>You can check the status, by running the following command.</p>
|
||||||
|
<p><code>systemctl status smbd</code></p>
|
||||||
|
<p><img src="/articles/images/2024-03-15-status.png" alt="status" /></p>
|
||||||
|
<p>Enable the samba server to start on boot.</p>
|
||||||
|
<p><code>systemctl enable smbd.service</code></p>
|
||||||
|
<h2>Step Five - Create Users</h2>
|
||||||
|
<p>Create a user with a home directory that they can use.</p>
|
||||||
|
<p><code>useradd --create-home michael</code></p>
|
||||||
|
<p>Give the user a password to login to the samba server.</p>
|
||||||
|
<p><code>smbpasswd michael</code></p>
|
||||||
|
<h2>Step Six - Login to Samba Server from Client</h2>
|
||||||
|
<p>In the <code>Finder</code> app on macOS you can type <code>⌘k</code> to connect to a server.</p>
|
||||||
|
<p>In the text field enter <code>smb://<USER>@<UNVR_IP></code> to connect to the samba server.</p>
|
||||||
|
<p><img src="/articles/images/2024-03-15-connect.png" alt="connect" /></p>
|
||||||
|
<p>You can also automatically connect to the server when you login to your client device, for this to<br />
|
||||||
|
work you need the credentials to be stored in your keychain (ticking the box in the step above when<br />
|
||||||
|
you first connect to the server).</p>
|
||||||
|
<p>This is found in <code>System Settings -> General -> Login Items -> Open at Login</code>. Click the plus button<br />
|
||||||
|
and select the volume you would like to mount at login.</p>
|
||||||
|
<p><img src="/articles/images/2024-03-15-login.png" alt="login" /></p>
|
||||||
|
<p>Once you have it setup so that the server is connected on login, you can also set it up as location<br />
|
||||||
|
for Time Machine Backups. <code>System Settings -> General -> Time Machine</code></p>
|
||||||
|
<p><img src="/articles/images/2024-03-15-time-machine.png" alt="time-machine" /></p>
|
||||||
|
</article>
|
||||||
|
<div class="border-t border-light mt-8 pt-8">
|
||||||
|
<h2 class="text-4xl font-extrabold mb-8">
|
||||||
|
Written by
|
||||||
|
</h2>
|
||||||
|
<div class="flex flex-col lg:flex-row gap-8">
|
||||||
|
<div class="flex-[0_0_120px]">
|
||||||
|
<img class="w-[120px] h-[120px] rounded-full" src="/static/images/avatar.png"/>
|
||||||
|
</div>
|
||||||
|
<div class="prose">
|
||||||
|
<h3 class="!m-0">
|
||||||
|
Michael Housh
|
||||||
|
</h3>
|
||||||
|
<p class="text-gray">
|
||||||
|
HVAC business owner with over 27 years of experience. Writes articles about HVAC,
|
||||||
|
Programming, Home-Performance, and Building Science
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-16">
|
||||||
|
<h2 class="text-4xl font-extrabold mb-8">
|
||||||
|
More articles
|
||||||
|
</h2>
|
||||||
|
<div class="grid lg:grid-cols-2 gap-10">
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2025/vapor-htmx-todo-app/">Vapor + HTMX</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">January 05, 2025</span><a href="/articles/tag/general/">general</a>, <a href="/articles/tag/programming/">programming</a> and <a href="/articles/tag/software/">software</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2025/vapor-htmx-todo-app/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2025-01-05-vapor-htmx-todo-app.png"/>
|
||||||
|
Build an example application using Vapor and HTMX.
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2024/free-as-in-freedom/">Free As In Freedom</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">April 09, 2024</span><a href="/articles/tag/general/">general</a>, <a href="/articles/tag/open-source/">open-source</a> and <a href="/articles/tag/software/">software</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2024/free-as-in-freedom/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2024-04-09-free-as-in-freedom.png"/>
|
||||||
|
Salute to open-source software engineers
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<p class="prose mt-8">
|
||||||
|
<a href="/articles/">› See all articles</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="site-footer container text-gray gray-links border-t border-light text-center pt-6 mt-8 text-sm">
|
||||||
|
<p>
|
||||||
|
Copyright © Michael Housh 2023-2025.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Built in Swift using
|
||||||
|
<a href="https://github.com/loopwerk/Saga" rel="nofollow" target="_blank">Saga</a>
|
||||||
|
(<a href="https://github.com/m-housh/mhoush.com" rel="nofollow" target="_blank">source</a>).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="http://localhost:3000/articles/feed.xml" rel="nofollow" target="_blank">RSS</a>
|
||||||
|
|
|
||||||
|
<a href="https://github.com/m-housh" rel="nofollow" target="_blank">Github</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.youtube.com/channel/UCb58SeURd5bObfTiL0KoliA" rel="nofollow" target="_blank">Youtube</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.facebook.com/michael.housh" rel="nofollow" target="_blank">Facebook</a>
|
||||||
|
|
|
||||||
|
<a href="mailto:michael@mhoush.com" rel="nofollow">Email</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
74
deploy/articles/2025/index.html
Normal file
74
deploy/articles/2025/index.html
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en-US">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta content="#0e1112" media="(prefers-color-scheme: dark)" name="theme-color"/>
|
||||||
|
<meta content="#566B78" media="(prefers-color-scheme: light)" name="theme-color"/>
|
||||||
|
<meta content="Michael Housh" name="author"/>
|
||||||
|
<meta content="Mhoush" name="apple-mobile-web-app-title"/>
|
||||||
|
<meta content="initial-scale=1.0, width=device-width" name="viewport"/>
|
||||||
|
<meta content="telephone=no" name="format-detection"/>
|
||||||
|
<meta content="True" name="HandheldFriendly"/>
|
||||||
|
<meta content="320" name="MobileOptimized"/>
|
||||||
|
<meta content="Mhoush" name="og:site_name"/>
|
||||||
|
<meta content="hvac, developer, swift, home-performance, design" name="keywords"/>
|
||||||
|
<title>
|
||||||
|
mhoush: Articles in 2025
|
||||||
|
</title>
|
||||||
|
<link href="/static/favicon.ico" rel="shortcut icon"/>
|
||||||
|
<link href="/static/output.css" rel="stylesheet"/>
|
||||||
|
<link href="/static/style.css" rel="stylesheet"/>
|
||||||
|
<link href="/articles/feed.xml" rel="alternate" title="mhoush" type="application/rss+xml"/>
|
||||||
|
</head>
|
||||||
|
<body class="bg-page text-white pb-5 font-avenir articles">
|
||||||
|
<header class="bg-nav text-gray py-4 text-base/6 lg:fixed w-full lg:h-[62px]">
|
||||||
|
<nav class="container flex gap-x-5 lg:gap-x-y items-center">
|
||||||
|
<ul class="flex flex-wrap gap-x-2 lg:gap-x-5">
|
||||||
|
<li>
|
||||||
|
<a class href="/">Home</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="active" href="/articles/">Articles</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class href="/about/">About</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<div class="container pt-12 lg:pt-28">
|
||||||
|
<section class="mb-10">
|
||||||
|
<h1 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2025/vapor-htmx-todo-app/">Vapor + HTMX</a>
|
||||||
|
</h1>
|
||||||
|
<div class="text-gray gray-links text-sm">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">January 05, 2025</span>2155 words, posted in <a href="/articles/tag/general/">general</a>, <a href="/articles/tag/programming/">programming</a> and <a href="/articles/tag/software/">software</a>
|
||||||
|
</div>
|
||||||
|
<p class="mt-4">
|
||||||
|
<a href="/articles/2025/vapor-htmx-todo-app/">Build an example application using Vapor and HTMX.</a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<div class="site-footer container text-gray gray-links border-t border-light text-center pt-6 mt-8 text-sm">
|
||||||
|
<p>
|
||||||
|
Copyright © Michael Housh 2023-2025.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Built in Swift using
|
||||||
|
<a href="https://github.com/loopwerk/Saga" rel="nofollow" target="_blank">Saga</a>
|
||||||
|
(<a href="https://github.com/m-housh/mhoush.com" rel="nofollow" target="_blank">source</a>).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="http://localhost:3000/articles/feed.xml" rel="nofollow" target="_blank">RSS</a>
|
||||||
|
|
|
||||||
|
<a href="https://github.com/m-housh" rel="nofollow" target="_blank">Github</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.youtube.com/channel/UCb58SeURd5bObfTiL0KoliA" rel="nofollow" target="_blank">Youtube</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.facebook.com/michael.housh" rel="nofollow" target="_blank">Facebook</a>
|
||||||
|
|
|
||||||
|
<a href="mailto:michael@mhoush.com" rel="nofollow">Email</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
560
deploy/articles/2025/vapor-htmx-todo-app/index.html
Normal file
560
deploy/articles/2025/vapor-htmx-todo-app/index.html
Normal file
@@ -0,0 +1,560 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en-US">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta content="#0e1112" media="(prefers-color-scheme: dark)" name="theme-color"/>
|
||||||
|
<meta content="#566B78" media="(prefers-color-scheme: light)" name="theme-color"/>
|
||||||
|
<meta content="Michael Housh" name="author"/>
|
||||||
|
<meta content="Mhoush" name="apple-mobile-web-app-title"/>
|
||||||
|
<meta content="initial-scale=1.0, width=device-width" name="viewport"/>
|
||||||
|
<meta content="telephone=no" name="format-detection"/>
|
||||||
|
<meta content="True" name="HandheldFriendly"/>
|
||||||
|
<meta content="320" name="MobileOptimized"/>
|
||||||
|
<meta content="Mhoush" name="og:site_name"/>
|
||||||
|
<meta content="hvac, developer, swift, home-performance, design" name="keywords"/>
|
||||||
|
<title>
|
||||||
|
mhoush: Vapor + HTMX
|
||||||
|
</title>
|
||||||
|
<link href="/static/favicon.ico" rel="shortcut icon"/>
|
||||||
|
<link href="/static/output.css" rel="stylesheet"/>
|
||||||
|
<link href="/static/style.css" rel="stylesheet"/>
|
||||||
|
<link href="/articles/feed.xml" rel="alternate" title="mhoush" type="application/rss+xml"/>
|
||||||
|
<link href="/static/prism.css" rel="stylesheet"/>
|
||||||
|
<meta content="Build an example application using Vapor and HTMX." name="description"/>
|
||||||
|
<meta content="summary_large_image" name="twitter:card"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images/2025-01-05-vapor-htmx-todo-app.png" name="twitter:image"/>
|
||||||
|
<meta content="Vapor + HTMX" name="twitter:image:alt"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images//articles/2025/vapor-htmx-todo-app/" name="og:url"/>
|
||||||
|
<meta content="Vapor + HTMX" name="og:title"/>
|
||||||
|
<meta content="Build an example application using Vapor and HTMX." name="og:description"/>
|
||||||
|
<meta content="http://localhost:3000/articles/images/2025-01-05-vapor-htmx-todo-app.png" name="og:image"/>
|
||||||
|
<meta content="1014" name="og:image:width"/>
|
||||||
|
<meta content="530" name="og:image:height"/>
|
||||||
|
<script crossorigin="anonymous" src="https://kit.fontawesome.com/f209982030.js">
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body class="bg-page text-white pb-5 font-avenir articles">
|
||||||
|
<header class="bg-nav text-gray py-4 text-base/6 lg:fixed w-full lg:h-[62px]">
|
||||||
|
<nav class="container flex gap-x-5 lg:gap-x-y items-center">
|
||||||
|
<ul class="flex flex-wrap gap-x-2 lg:gap-x-5">
|
||||||
|
<li>
|
||||||
|
<a class href="/">Home</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="active" href="/articles/">Articles</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class href="/about/">About</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<div class="container pt-12 lg:pt-28">
|
||||||
|
<article class="prose">
|
||||||
|
<h1>
|
||||||
|
Vapor + HTMX
|
||||||
|
</h1>
|
||||||
|
<div class="-mt-6">
|
||||||
|
<div class="text-gray gray-links text-sm">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">January 05, 2025</span>2155 words, posted in <a href="/articles/tag/general/">general</a>, <a href="/articles/tag/programming/">programming</a> and <a href="/articles/tag/software/">software</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2025-01-05-vapor-htmx-todo-app.png"/>
|
||||||
|
<h2>Introduction</h2>
|
||||||
|
<p>This post is a quick example of creating a very basic todo web application using <code>Vapor</code> a swift web<br />
|
||||||
|
framework and <code>Htmx</code>, with no custom javascript required.</p>
|
||||||
|
<p><a href="https://docs.vapor.codes">Vapor</a></p>
|
||||||
|
<p><a href="https://htmx.org">Htmx</a></p>
|
||||||
|
<h2>Getting Started</h2>
|
||||||
|
<p>To get started you must install the vapor command-line tool that will generate our project.</p>
|
||||||
|
<pre><code class="language-bash">brew install vapor
|
||||||
|
</code></pre>
|
||||||
|
<p>Next, generate the project using the vapor command-line tool.</p>
|
||||||
|
<p><img src="/articles/images/2025-01-05-vapor.gif" alt="" /></p>
|
||||||
|
<pre><code class="language-bash">vapor new todo-htmx --fluent.db sqlite --leaf
|
||||||
|
</code></pre>
|
||||||
|
<p>The above command will generate a new project that uses an <code>SQLite</code> database along with vapor’s<br />
|
||||||
|
<code>Leaf</code> templating engine. You can move into the project directory and browse around the files that<br />
|
||||||
|
are generated.</p>
|
||||||
|
<pre><code class="language-bash">cd todo-htmx
|
||||||
|
</code></pre>
|
||||||
|
<h2>Update the Controller</h2>
|
||||||
|
<p>Open the <code>Sources/App/Controllers/TodoController.swift</code> file. This file handles the api routes for<br />
|
||||||
|
our <code>Todo</code> database model. Personally I like to prefix these routes with <code>api</code>.</p>
|
||||||
|
<p>Update the first line in the <code>boot(routes: RoutesBuilder)</code> function to look like this.</p>
|
||||||
|
<pre><code class="language-swift">let todos = routes.grouped("api", "todos")
|
||||||
|
</code></pre>
|
||||||
|
<p>Everything else can stay the same. This changes these routes to be exposed at<br />
|
||||||
|
<code>http://localhost:8080/api/todos</code>, which will allow our routes that return html views to be able to<br />
|
||||||
|
be exposed at <code>http://localhost:8080/todos</code>.</p>
|
||||||
|
<h2>Update the Todo Model</h2>
|
||||||
|
<p>A todo is not very valuable without a way to tell if it needs to be completed or not. So, let’s add<br />
|
||||||
|
a field to our database model (<code>Sources/App/Models/Todo.swift</code>).</p>
|
||||||
|
<p>Update the file to include the following:</p>
|
||||||
|
<pre><code class="language-swift">import Fluent
|
||||||
|
import struct Foundation.UUID
|
||||||
|
|
||||||
|
/// Property wrappers interact poorly with `Sendable` checking, causing a warning for the `@ID` property
|
||||||
|
/// It is recommended you write your model with sendability checking on and then suppress the warning
|
||||||
|
/// afterwards with `@unchecked Sendable`.
|
||||||
|
final class Todo: Model, @unchecked Sendable {
|
||||||
|
static let schema = "todos"
|
||||||
|
|
||||||
|
@ID(key: .id)
|
||||||
|
var id: UUID?
|
||||||
|
|
||||||
|
@Field(key: "title")
|
||||||
|
var title: String
|
||||||
|
|
||||||
|
@Field(key: "complete")
|
||||||
|
var complete: Bool
|
||||||
|
|
||||||
|
init() {}
|
||||||
|
|
||||||
|
init(id: UUID? = nil, title: String, complete: Bool) {
|
||||||
|
self.id = id
|
||||||
|
self.title = title
|
||||||
|
self.complete = complete
|
||||||
|
}
|
||||||
|
|
||||||
|
func toDTO() -> TodoDTO {
|
||||||
|
.init(
|
||||||
|
id: id,
|
||||||
|
title: $title.value,
|
||||||
|
complete: $complete.value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
|
<p>Since we added a field to our database model, we also need to update the migration file<br />
|
||||||
|
(<code>Sources/App/Migrations/CreateTodo.swift</code>).</p>
|
||||||
|
<pre><code class="language-swift">import Fluent
|
||||||
|
|
||||||
|
struct CreateTodo: AsyncMigration {
|
||||||
|
func prepare(on database: Database) async throws {
|
||||||
|
try await database.schema("todos")
|
||||||
|
.id()
|
||||||
|
.field("title", .string, .required)
|
||||||
|
.field("complete", .bool, .required)
|
||||||
|
.create()
|
||||||
|
}
|
||||||
|
|
||||||
|
func revert(on database: Database) async throws {
|
||||||
|
try await database.schema("todos").delete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
|
<p>This just adds our new field to the database schema when we run the migrations, which we will do<br />
|
||||||
|
later on in the tutorial.</p>
|
||||||
|
<h3>Update the Data Transfer Object</h3>
|
||||||
|
<p>We also need to add the <code>complete</code> field to our data transfer object (<code>DTO</code>). This model is used as<br />
|
||||||
|
an intermediate between our database and the user.</p>
|
||||||
|
<pre><code class="language-swift">import Fluent
|
||||||
|
import Vapor
|
||||||
|
|
||||||
|
struct TodoDTO: Content {
|
||||||
|
var id: UUID?
|
||||||
|
var title: String?
|
||||||
|
var complete: Bool?
|
||||||
|
|
||||||
|
func toModel() -> Todo {
|
||||||
|
let model = Todo()
|
||||||
|
|
||||||
|
model.id = id
|
||||||
|
model.complete = complete ?? false
|
||||||
|
if let title = title {
|
||||||
|
model.title = title
|
||||||
|
}
|
||||||
|
return model
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
|
<h2>Generate the View Templates</h2>
|
||||||
|
<p>Our index template was already generated at <code>Resources/Views/index.leaf</code>, open the file and edit the<br />
|
||||||
|
contents to match the following.</p>
|
||||||
|
<blockquote>
|
||||||
|
<p>Note: You can learn more about the<br />
|
||||||
|
<a href="https://docs.vapor.codes/leaf/getting-started/">leaf templating engine here.</a></p>
|
||||||
|
</blockquote>
|
||||||
|
<pre><code class="language-html"><!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>#(title)</title>
|
||||||
|
<link rel="stylesheet" href="css/main.css" />
|
||||||
|
<script src="https://unpkg.com/htmx.org@2.0.4"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>#(title)</h1>
|
||||||
|
<div class="container">
|
||||||
|
<form hx-post="/todos" hx-target="#todos">
|
||||||
|
<label for="title">Todo</label>
|
||||||
|
<input type="text" name="title" placeholder="Title" />
|
||||||
|
<button type="submit">Submit</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<!-- Todos List -->
|
||||||
|
<table id="todos" class="todos" hx-get="/todos" hx-trigger="load"></table>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
</code></pre>
|
||||||
|
<p>The important parts here are the <code><script></code> tag in the head element which will include <code>Htmx</code> in our<br />
|
||||||
|
project.</p>
|
||||||
|
<p>The head element also contains a link to a custom <code>css</code> stylesheet that we will create shortly.</p>
|
||||||
|
<p>We add a <code>form</code> element that will be used to generate a new todo item in the database. This is a<br />
|
||||||
|
basic / standard html form, but we are using <code>Htmx</code> to post the form contents to the route<br />
|
||||||
|
<code>POST http://localhost:8080/todos</code>, which we will create shortly.</p>
|
||||||
|
<p>Then there’s the <code>table</code> element that will contain the contents of our todos. When the page is<br />
|
||||||
|
loaded it will use <code>Htmx</code> to fetch the todos from <code>GET http://localhost:8080/todos</code> route, which we<br />
|
||||||
|
will create shortly.</p>
|
||||||
|
<h3>Todos Table Template</h3>
|
||||||
|
<p>Create a new view template that will return our populated table of todos.</p>
|
||||||
|
<pre><code class="language-bash">touch Resources/Views/todos.leaf
|
||||||
|
</code></pre>
|
||||||
|
<p>The contents of this file should be the following:</p>
|
||||||
|
<pre><code class="language-html"><!-- Template for a list of todo's -->
|
||||||
|
<table id="todos"
|
||||||
|
class="todos">
|
||||||
|
<!-- The table header -->
|
||||||
|
<tr>
|
||||||
|
<th>Description</th>
|
||||||
|
<th>Completed</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
#for(todo in todos):
|
||||||
|
<tr>
|
||||||
|
<!-- Make the title column take up 90% of the width -->
|
||||||
|
<td style="width: 90%;">#(todo.title)</td>
|
||||||
|
<td>
|
||||||
|
<input type="checkbox"
|
||||||
|
id="todo_#(todo.id)"
|
||||||
|
hx-put="/todos/#(todo.id)"
|
||||||
|
hx-trigger="click"
|
||||||
|
hx-target="#todos"
|
||||||
|
#if(todo.complete): checked #endif>
|
||||||
|
</input>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<button hx-delete="/todos/#(todo.id)"
|
||||||
|
hx-trigger="click"
|
||||||
|
hx-target="#todos"
|
||||||
|
class="btn-delete-todo">
|
||||||
|
X
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
#endfor
|
||||||
|
</table>
|
||||||
|
</code></pre>
|
||||||
|
<p>Here, we just create a table that is 3 columns wide from a list of todos that we will pass in to the<br />
|
||||||
|
template. We use <code>Htmx</code> to handle updating a todo if a user clicks a checkbox to mark the todo as<br />
|
||||||
|
<code>complete</code>, we also add a button in the last column of the table that we use <code>Htmx</code> to handle<br />
|
||||||
|
deleting a todo from the database.</p>
|
||||||
|
<h2>Controllers</h2>
|
||||||
|
<p>The controllers handle the routes that our website exposes. The project template creates a<br />
|
||||||
|
controller for us that handles <code>JSON</code> / <code>API</code> requests, but we do need to make a couple of changes<br />
|
||||||
|
to the file (<code>Sources/App/Controllers/TodoController.swift</code>).</p>
|
||||||
|
<pre><code class="language-swift">import Fluent
|
||||||
|
import Vapor
|
||||||
|
|
||||||
|
struct TodoController: RouteCollection {
|
||||||
|
func boot(routes: RoutesBuilder) throws {
|
||||||
|
let todos = routes.grouped("api", "todos")
|
||||||
|
|
||||||
|
todos.get(use: index)
|
||||||
|
todos.post(use: create)
|
||||||
|
todos.group(":todoID") { todo in
|
||||||
|
todo.delete(use: self.delete)
|
||||||
|
todo.put(use: self.update)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Sendable
|
||||||
|
func index(req: Request) async throws -> [TodoDTO] {
|
||||||
|
try await Todo.query(on: req.db).all().map { $0.toDTO() }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Sendable
|
||||||
|
func create(req: Request) async throws -> TodoDTO {
|
||||||
|
let todo = try req.content.decode(TodoDTO.self).toModel()
|
||||||
|
|
||||||
|
try await todo.save(on: req.db)
|
||||||
|
return todo.toDTO()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Sendable
|
||||||
|
func delete(req: Request) async throws -> HTTPStatus {
|
||||||
|
guard let todo = try await Todo.find(req.parameters.get("todoID"), on: req.db) else {
|
||||||
|
throw Abort(.notFound)
|
||||||
|
}
|
||||||
|
|
||||||
|
try await todo.delete(on: req.db)
|
||||||
|
return .noContent
|
||||||
|
}
|
||||||
|
|
||||||
|
@Sendable
|
||||||
|
func update(req: Request) async throws -> TodoDTO {
|
||||||
|
// let todo = try req.content.decode(TodoDTO.self).toModel()
|
||||||
|
guard let todo = try await Todo.find(req.parameters.get("todoID"), on: req.db) else {
|
||||||
|
throw Abort(.notFound)
|
||||||
|
}
|
||||||
|
todo.complete.toggle()
|
||||||
|
try await todo.save(on: req.db)
|
||||||
|
return todo.toDTO()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
|
<p>The primary changes here are to add the <code>update(req: Request)</code> function at the bottom, which handles<br />
|
||||||
|
updating a todo that has already been created. This will be used when a user clicks on the checkbox<br />
|
||||||
|
to mark a todo as complete or incomplete.</p>
|
||||||
|
<p>We also change the route in the <code>boot(routes: RoutesBuilder)</code> method to make all these routes<br />
|
||||||
|
accessible at <code>/api/todos</code> instead of the original <code>/todos</code> as we will use the <code>/todos</code> routes for<br />
|
||||||
|
returning our views from our view controller.</p>
|
||||||
|
<h3>Todo View Controller</h3>
|
||||||
|
<p>Next we need to create our view controller, it is what will be used to handle routes that should<br />
|
||||||
|
return <code>html</code> content for our website. This controller will actually use the api controller to do<br />
|
||||||
|
the majority of it’s work.</p>
|
||||||
|
<p>The easiest thing is to make a copy of the current api controller:</p>
|
||||||
|
<pre><code class="language-bash">cp Sources/App/Controllers/TodoController.swift Sources/App/Controllers/TodoViewController.swift
|
||||||
|
</code></pre>
|
||||||
|
<p>Then update the file to the following:</p>
|
||||||
|
<pre><code class="language-swift">import Fluent
|
||||||
|
import Vapor
|
||||||
|
|
||||||
|
struct TodoViewController: RouteCollection {
|
||||||
|
|
||||||
|
private let api = TodoController()
|
||||||
|
|
||||||
|
func boot(routes: RoutesBuilder) throws {
|
||||||
|
let todos = routes.grouped("todos")
|
||||||
|
|
||||||
|
todos.get(use: index)
|
||||||
|
todos.post(use: create)
|
||||||
|
todos.group(":todoID") { todo in
|
||||||
|
todo.delete(use: self.delete)
|
||||||
|
todo.put(use: self.update)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Sendable
|
||||||
|
func index(req: Request) async throws -> View {
|
||||||
|
let todos = try await api.index(req: req)
|
||||||
|
return try await req.view.render("todos", ["todos": todos])
|
||||||
|
}
|
||||||
|
|
||||||
|
@Sendable
|
||||||
|
func create(req: Request) async throws -> View {
|
||||||
|
_ = try await api.create(req: req)
|
||||||
|
return try await index(req: req)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Sendable
|
||||||
|
func delete(req: Request) async throws -> View {
|
||||||
|
_ = try await api.delete(req: req)
|
||||||
|
return try await index(req: req)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Sendable
|
||||||
|
func update(req: Request) async throws -> View {
|
||||||
|
_ = try await api.update(req: req)
|
||||||
|
return try await index(req: req)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
|
<p>Here we use the api controller to do the heavy lifting of communicating with the database, then we<br />
|
||||||
|
just always return / render the <code>todos.leaf</code> template that we created earlier, which will update our<br />
|
||||||
|
web page with the list of todos retreived from the database.</p>
|
||||||
|
<blockquote>
|
||||||
|
<p>Note: There are better ways to handle this, however this is just a simple example.</p>
|
||||||
|
</blockquote>
|
||||||
|
<h3>Update our routes</h3>
|
||||||
|
<p>Next, we need to tell vapor to use our new view controller (<code>Sources/App/routes.swift</code>)</p>
|
||||||
|
<pre><code class="language-swift">import Fluent
|
||||||
|
import Vapor
|
||||||
|
|
||||||
|
func routes(_ app: Application) throws {
|
||||||
|
app.get { req async throws in
|
||||||
|
try await req.view.render("index", ["title": "Todos"])
|
||||||
|
}
|
||||||
|
|
||||||
|
app.get("hello") { _ async -> String in
|
||||||
|
"Hello, world!"
|
||||||
|
}
|
||||||
|
|
||||||
|
try app.register(collection: TodoController())
|
||||||
|
try app.register(collection: TodoViewController())
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
|
<p>Here, we just add the <code>TodoViewController</code> at the bottom so vapor will be able to handle those<br />
|
||||||
|
routes and also update the title to be <code>Todos</code> (in the first <code>app.get</code> near the top).</p>
|
||||||
|
<h2>Build and Run</h2>
|
||||||
|
<p>At this point we should be able to build and run the application.</p>
|
||||||
|
<p>First, let’s make sure the project builds.</p>
|
||||||
|
<pre><code class="language-bash">swift build
|
||||||
|
</code></pre>
|
||||||
|
<p>This may take a minute if it’s the first time building the project as it has to fetch the<br />
|
||||||
|
dependencies. If you experience problems here then make sure you don’t have typos in your files.</p>
|
||||||
|
<p>Next, we need to run the database migrations.</p>
|
||||||
|
<pre><code class="language-bash">swift run App migrate
|
||||||
|
</code></pre>
|
||||||
|
<p>Finally, we can run the application.</p>
|
||||||
|
<pre><code class="language-bash">swift run App
|
||||||
|
</code></pre>
|
||||||
|
<p>You should be able to open your browser and type in the url: <code>http://localhost:8080</code> to view the<br />
|
||||||
|
application. You can experiment with adding a new todo using the form.</p>
|
||||||
|
<blockquote>
|
||||||
|
<p>Note: To stop the application use <code>Ctrl-c</code></p>
|
||||||
|
</blockquote>
|
||||||
|
<h2>Bonus Styles</h2>
|
||||||
|
<p>Hopefully you weren’t blinded the first time you opened the application. You can add custom styles<br />
|
||||||
|
by creating a <code>css</code> file (<code>Public/css/main.css</code>).</p>
|
||||||
|
<pre><code class="language-bash">mkdir Public/css
|
||||||
|
touch Public/css/main.css
|
||||||
|
</code></pre>
|
||||||
|
<p>Update the file to the following:</p>
|
||||||
|
<pre><code class="language-css">body {
|
||||||
|
background-color: #1e1e2e;
|
||||||
|
color: #ff66ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
th,
|
||||||
|
td {
|
||||||
|
border-bottom: 1px solid grey;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.todos {
|
||||||
|
transition: all ease-in 1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-delete-todo {
|
||||||
|
color: red;
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
|
<p>Currently vapor does not know to serve files from the <code>Public</code> directory, so we need to update the<br />
|
||||||
|
<code>Sources/App/configure.swift</code> file, by uncommenting the line near the top.</p>
|
||||||
|
<pre><code class="language-swift">import Fluent
|
||||||
|
import FluentSQLiteDriver
|
||||||
|
import Leaf
|
||||||
|
import NIOSSL
|
||||||
|
import Vapor
|
||||||
|
|
||||||
|
// configures your application
|
||||||
|
public func configure(_ app: Application) async throws {
|
||||||
|
// uncomment to serve files from /Public folder
|
||||||
|
app.middleware.use(FileMiddleware(publicDirectory: app.directory.publicDirectory))
|
||||||
|
|
||||||
|
app.databases.use(DatabaseConfigurationFactory.sqlite(.file("db.sqlite")), as: .sqlite)
|
||||||
|
|
||||||
|
app.migrations.add(CreateTodo())
|
||||||
|
|
||||||
|
app.views.use(.leaf)
|
||||||
|
|
||||||
|
// register routes
|
||||||
|
try routes(app)
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
|
<p>Now you can stop and restart to see the styled website.</p>
|
||||||
|
<pre><code class="language-bash">swift run App
|
||||||
|
</code></pre>
|
||||||
|
<h2>Conclusion</h2>
|
||||||
|
<p>I hope you enjoyed this quick example of using <code>Htmx</code> with <code>Vapor</code>. You can view the source files at<br />
|
||||||
|
<a href="https://github.com/m-housh/todo-htmx">here</a>.</p>
|
||||||
|
</article>
|
||||||
|
<div class="border-t border-light mt-8 pt-8">
|
||||||
|
<h2 class="text-4xl font-extrabold mb-8">
|
||||||
|
Written by
|
||||||
|
</h2>
|
||||||
|
<div class="flex flex-col lg:flex-row gap-8">
|
||||||
|
<div class="flex-[0_0_120px]">
|
||||||
|
<img class="w-[120px] h-[120px] rounded-full" src="/static/images/avatar.png"/>
|
||||||
|
</div>
|
||||||
|
<div class="prose">
|
||||||
|
<h3 class="!m-0">
|
||||||
|
Michael Housh
|
||||||
|
</h3>
|
||||||
|
<p class="text-gray">
|
||||||
|
HVAC business owner with over 27 years of experience. Writes articles about HVAC,
|
||||||
|
Programming, Home-Performance, and Building Science
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-16">
|
||||||
|
<h2 class="text-4xl font-extrabold mb-8">
|
||||||
|
More articles
|
||||||
|
</h2>
|
||||||
|
<div class="grid lg:grid-cols-2 gap-10">
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2024/free-as-in-freedom/">Free As In Freedom</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">April 09, 2024</span><a href="/articles/tag/general/">general</a>, <a href="/articles/tag/open-source/">open-source</a> and <a href="/articles/tag/software/">software</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2024/free-as-in-freedom/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2024-04-09-free-as-in-freedom.png"/>
|
||||||
|
Salute to open-source software engineers
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2024/pgp-encryption-introduction/">PGP Encryption Introduction</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">April 04, 2024</span><a href="/articles/tag/gnupgp/">GnuPGP</a>, <a href="/articles/tag/pgp/">PGP</a>, <a href="/articles/tag/programming/">programming</a> and <a href="/articles/tag/security/">security</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2024/pgp-encryption-introduction/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2024-04-04-pgp-encryption-introduction.gif"/>
|
||||||
|
In this article I introduce PGP and show a use case for me, which perhaps you can use as well.
|
||||||
|
What is PGP
|
||||||
|
PGP stands for Pretty Good Privacy, it was first developed in 1991 by Phil Zimmermann. PGP uses
|
||||||
|
cryptographic privacy and authentication and is...
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<p class="prose mt-8">
|
||||||
|
<a href="/articles/">› See all articles</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="site-footer container text-gray gray-links border-t border-light text-center pt-6 mt-8 text-sm">
|
||||||
|
<p>
|
||||||
|
Copyright © Michael Housh 2023-2025.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Built in Swift using
|
||||||
|
<a href="https://github.com/loopwerk/Saga" rel="nofollow" target="_blank">Saga</a>
|
||||||
|
(<a href="https://github.com/m-housh/mhoush.com" rel="nofollow" target="_blank">source</a>).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="http://localhost:3000/articles/feed.xml" rel="nofollow" target="_blank">RSS</a>
|
||||||
|
|
|
||||||
|
<a href="https://github.com/m-housh" rel="nofollow" target="_blank">Github</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.youtube.com/channel/UCb58SeURd5bObfTiL0KoliA" rel="nofollow" target="_blank">Youtube</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.facebook.com/michael.housh" rel="nofollow" target="_blank">Facebook</a>
|
||||||
|
|
|
||||||
|
<a href="mailto:michael@mhoush.com" rel="nofollow">Email</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
694
deploy/articles/feed.xml
Normal file
694
deploy/articles/feed.xml
Normal file
@@ -0,0 +1,694 @@
|
|||||||
|
|
||||||
|
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||||
|
<id>http://localhost:3000/articles/feed.xml</id>
|
||||||
|
<title>mhoush</title>
|
||||||
|
<author>
|
||||||
|
<name>Michael Housh</name>
|
||||||
|
</author>
|
||||||
|
<link rel="self" href="http://localhost:3000"></link>
|
||||||
|
<updated>2025-02-19T21:55:31Z</updated>
|
||||||
|
<entry>
|
||||||
|
<id>http://localhost:3000/articles/2025/vapor-htmx-todo-app/</id>
|
||||||
|
<title>Vapor + HTMX</title>
|
||||||
|
<updated>2025-02-19T21:47:31Z</updated>
|
||||||
|
<summary>Build an example application using Vapor and HTMX.</summary>
|
||||||
|
<link rel="alternate" href="http://localhost:3000/articles/2025/vapor-htmx-todo-app/"></link>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<id>http://localhost:3000/articles/2024/free-as-in-freedom/</id>
|
||||||
|
<title>Free As In Freedom</title>
|
||||||
|
<updated>2025-02-19T21:39:28Z</updated>
|
||||||
|
<summary>Salute to open-source software engineers</summary>
|
||||||
|
<link rel="alternate" href="http://localhost:3000/articles/2024/free-as-in-freedom/"></link>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<id>http://localhost:3000/articles/2024/pgp-encryption-introduction/</id>
|
||||||
|
<title>PGP Encryption Introduction</title>
|
||||||
|
<updated>2025-02-19T21:36:11Z</updated>
|
||||||
|
<content type="html"><p>In this article I introduce PGP and show a use case for me, which perhaps you can use as well.</p>
|
||||||
|
<h2>What is PGP</h2>
|
||||||
|
<p>PGP stands for <strong>Pretty Good Privacy</strong>, it was first developed in 1991 by Phil Zimmermann. PGP uses<br />
|
||||||
|
cryptographic privacy and authentication and is generally used in data communication.</p>
|
||||||
|
<p>According to <a href="https://en.wikipedia.org/wiki/Pretty_Good_Privacy">Wikipedia</a> it’s name was inspired<br />
|
||||||
|
by a grocery store named, “Ralph’s Pretty Goody Grocery” featured in radio host’s Garrison Keillor’s<br />
|
||||||
|
fictional town of Lake Wobegon.</p>
|
||||||
|
<p>PGP is commonly used in software development to “sign” software commits or files to help ensure both<br />
|
||||||
|
who the commits were from as well as make sure they were not modified from the original versions.</p>
|
||||||
|
<p>It should also be noted that when people say PGP they are often referring to OpenPGP or GnuPGP which<br />
|
||||||
|
are implementations of the PGP standard protocol.</p>
|
||||||
|
<h2>What it does</h2>
|
||||||
|
<blockquote>
|
||||||
|
<p>Note: I am in no way a cyber-security expert, I am a layman and only describing things in terms<br />
|
||||||
|
that I understand / make sense to me. Do what I do at your own risk!</p>
|
||||||
|
</blockquote>
|
||||||
|
<p>PGP offers both symmetrical encryption (uses a session key and password) or asymmetrical encryption<br />
|
||||||
|
(uses a session key and a private key). Asymmetrical encryption is more secure but is more resource<br />
|
||||||
|
intensive (which is generally not a problem with computers of today).</p>
|
||||||
|
<p>Generally speaking PGP uses what are known as public and private key pairs. The public portion of<br />
|
||||||
|
the key par is meant to be shared with others freely, while the private portion needs to be secured<br />
|
||||||
|
/ not shared with anyone <strong>EVER</strong>. It is best practice to generate your keys on a computer that is<br />
|
||||||
|
“air gapped”, meaning it is not connected to any network / internet, and does not save a history of<br />
|
||||||
|
commands performed on it.</p>
|
||||||
|
<p>PGP encrypts data (files, messages, etc.) for one or more recipients, using the recipients public<br />
|
||||||
|
key. The recipients private key is required to decrypt the data once it’s been encrypted.</p>
|
||||||
|
<p>Your key pair is tied to your identity / person, generally by your name and email(s). The key can<br />
|
||||||
|
also have multiple “subkeys”, meaning that if you have more than one public email, alias, etc. it<br />
|
||||||
|
can be tied to your same private key. This is useful for example for work vs. activism vs. software<br />
|
||||||
|
development.</p>
|
||||||
|
<p>Once your key is generated and your private key secured, you can share your public portion of the<br />
|
||||||
|
key to a “keyserver” where other people can download it and verify messages were sent by you.</p>
|
||||||
|
<h2>Web of Trust</h2>
|
||||||
|
<p>PGP also uses what is called the <strong>“Web of Trust”</strong>, which is used to validate that messages are<br />
|
||||||
|
encrypted by a trusted source. There are different levels of trust depending on where a key is<br />
|
||||||
|
retrieved from. For example, if somebody gave you their public key in person and you were able to<br />
|
||||||
|
inspect that the identity matches their government id, then you can give it a higher trust level<br />
|
||||||
|
than one that is sent / retrieved from a keyserver.</p>
|
||||||
|
<p>My understanding of this portion is that over time your key is signed by other’s with their level of<br />
|
||||||
|
certainty about you / your key, which over time increases the overall trust in your key.</p>
|
||||||
|
<h2>Out of the weeds</h2>
|
||||||
|
<p>Now that we’ve got an understanding of some of the technical aspects, lets talk about some real use<br />
|
||||||
|
cases of PGP encryption.</p>
|
||||||
|
<p>PGP encryption is used by some email clients / applications, such as<br />
|
||||||
|
<a href="https://canarymail.io/">Canary</a>,<br />
|
||||||
|
<a href="https://www.thunderbird.net/en-US/thunderbird/115.0/holidayeoy/">Thunderbird</a>, or<br />
|
||||||
|
<a href="https://gpgtools.tenderapp.com/">GPGSuite</a>.</p>
|
||||||
|
<p>In my understanding, it is also what is used in devices such as a<br />
|
||||||
|
<a href="https://www.yubico.com/">YubiKey</a>.</p>
|
||||||
|
<p>Many of the mentioned applications allow for an easier interface / adoption, as one of the reasons<br />
|
||||||
|
it is not very popular is that it can be hard to use PGP for the average person.</p>
|
||||||
|
<p>Aside from using my PGP key for signing software commits, my major use case is for encrypting files<br />
|
||||||
|
that I store in a “cloud” provider. Know that when someone says the “cloud”, it is really just a<br />
|
||||||
|
computer (in reality a gang of computers in a data center). You are solely reliant that these cloud<br />
|
||||||
|
providers are not snooping on, inspecting, or even selling your data.</p>
|
||||||
|
<p>Of course, some data may not be that sensitive, so maybe you don’t care. However with a little bit<br />
|
||||||
|
of effort on your part you can at least make it very hard for anyone to know what is inside your<br />
|
||||||
|
documents. You can be in control of the way your items are encrypted and have confidence that nobody<br />
|
||||||
|
but you can access what is inside your documents.</p>
|
||||||
|
<p>Heck, I even encrypt documents that are stored on my own network / computer so that if something<br />
|
||||||
|
get’s stolen or someone breach’s my network they will not be able to easily get to sensitive data.</p>
|
||||||
|
<h2>Conclusion</h2>
|
||||||
|
<p>This article is just meant as an overview of PGP encryption. In future articles I will show you how<br />
|
||||||
|
to use it to encrypt your data and be in control of your privacy.</p>
|
||||||
|
<h3>Resources</h3>
|
||||||
|
<ul>
|
||||||
|
<li><a href="https://gnupg.org/">GnuPG</a></li>
|
||||||
|
<li><a href="https://www.openpgp.org/">OpenPGP</a></li>
|
||||||
|
<li><a href="https://gpg.wtf/">gpg.wtf</a></li>
|
||||||
|
<li><a href="https://www.ietf.org/rfc/rfc4880.html">RFC4880</a></li>
|
||||||
|
</ul></content>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<id>http://localhost:3000/articles/2024/unvr-as-nas/</id>
|
||||||
|
<title>UNVR as NAS</title>
|
||||||
|
<updated>2025-02-19T21:32:01Z</updated>
|
||||||
|
<content type="html"><p>In this post, I’m going to show how to setup a Samba server on a Ubiquity UNVR so that it can be<br />
|
||||||
|
used as NAS (network attached storage). Be aware that this should be done with caution and may void<br />
|
||||||
|
any warranty on your UNVR as we are using it for purposes beyond it’s original intent. It’s also<br />
|
||||||
|
possible that this setup will break when / if updating the UNVR software. With that said, let’s jump<br />
|
||||||
|
in.</p>
|
||||||
|
<p>This post follows along with<br />
|
||||||
|
<a href="https://www.reddit.com/r/Ubiquiti/comments/11o7v8l/how_to_use_the_unvr_as_a_nas_instructions/">this reddit post</a>,<br />
|
||||||
|
with some adaptations to get it to work on the latest Unifi-OS release of <code>3.2.12</code>.</p>
|
||||||
|
<h2>Step One - Setup SSH &amp; Login</h2>
|
||||||
|
<p>In your unifi network console you need to enable the <code>SSH</code> login option and set a secure password<br />
|
||||||
|
for the root user to login to the UNVR.</p>
|
||||||
|
<p><img src="/articles/images/2024-03-15-ssh.png" alt="ssh.png" /></p>
|
||||||
|
<p>Once that is complete you can login to your UNVR using your terminal and the IP address of your UNVR<br />
|
||||||
|
on your network.</p>
|
||||||
|
<p><code>ssh root@192.168.1.10</code></p>
|
||||||
|
<h2>Step Two - Install Samba</h2>
|
||||||
|
<p>First, we’ll update the package registry information.</p>
|
||||||
|
<p><code>apt-get update</code></p>
|
||||||
|
<p>Next, install samba.</p>
|
||||||
|
<p><code>apt-get install samba</code></p>
|
||||||
|
<h2>Step Three - Setup Samba</h2>
|
||||||
|
<p>In order to edit the configuration we are going to need to install your terminal based text editor<br />
|
||||||
|
of choice (generally nano or vim), for me I will install vim.</p>
|
||||||
|
<p><code>apt-get install vim</code></p>
|
||||||
|
<p>Create a backup of the default configuration.</p>
|
||||||
|
<p><code>cp /etc/samba/smb.conf /etc/samba/smb.conf.bak</code></p>
|
||||||
|
<p>Open the configuration file to be edited.</p>
|
||||||
|
<p><code>vim /etc/samba/smb.conf</code></p>
|
||||||
|
<p>Just above the <code>Share Definitions</code> section of the configuration, I added some global settings to<br />
|
||||||
|
make the samba server act better for time machine backups.</p>
|
||||||
|
<pre><code>#======================= MacOS Client Optimizations =======================
|
||||||
|
vfs objects = fruit streams_xattr
|
||||||
|
fruit:metadata = stream
|
||||||
|
fruit:model = MacSamba
|
||||||
|
fruit:posix_rename = yes
|
||||||
|
fruit:veto_appledouble = no
|
||||||
|
fruit:nfs_aces = no
|
||||||
|
fruit:wipe_intentionally_left_blank_rfork = yes
|
||||||
|
fruit:delete_empty_adfiles = yes
|
||||||
|
|
||||||
|
</code></pre>
|
||||||
|
<p>Also because we want users we create to be able to read and write to their home directories created<br />
|
||||||
|
on the samba server, we need to change the option under the <code>[homes]</code> share definition to be<br />
|
||||||
|
<code>read only = no</code>.</p>
|
||||||
|
<p>That is our primary configuration. You can add more share definitions at the bottom of the file to<br />
|
||||||
|
suit your use case, there are decent examples of this in the original reddit post, linked in the<br />
|
||||||
|
beginning.</p>
|
||||||
|
<p>Save and exit the file.</p>
|
||||||
|
<p><code>:wq</code></p>
|
||||||
|
<h2>Step Four - Start Samba</h2>
|
||||||
|
<p>Use the following command to start the samba server.</p>
|
||||||
|
<p><code>sudo service smbd start</code></p>
|
||||||
|
<p>You can check the status, by running the following command.</p>
|
||||||
|
<p><code>systemctl status smbd</code></p>
|
||||||
|
<p><img src="/articles/images/2024-03-15-status.png" alt="status" /></p>
|
||||||
|
<p>Enable the samba server to start on boot.</p>
|
||||||
|
<p><code>systemctl enable smbd.service</code></p>
|
||||||
|
<h2>Step Five - Create Users</h2>
|
||||||
|
<p>Create a user with a home directory that they can use.</p>
|
||||||
|
<p><code>useradd --create-home michael</code></p>
|
||||||
|
<p>Give the user a password to login to the samba server.</p>
|
||||||
|
<p><code>smbpasswd michael</code></p>
|
||||||
|
<h2>Step Six - Login to Samba Server from Client</h2>
|
||||||
|
<p>In the <code>Finder</code> app on macOS you can type <code>⌘k</code> to connect to a server.</p>
|
||||||
|
<p>In the text field enter <code>smb://&lt;USER&gt;@&lt;UNVR_IP&gt;</code> to connect to the samba server.</p>
|
||||||
|
<p><img src="/articles/images/2024-03-15-connect.png" alt="connect" /></p>
|
||||||
|
<p>You can also automatically connect to the server when you login to your client device, for this to<br />
|
||||||
|
work you need the credentials to be stored in your keychain (ticking the box in the step above when<br />
|
||||||
|
you first connect to the server).</p>
|
||||||
|
<p>This is found in <code>System Settings -&gt; General -&gt; Login Items -&gt; Open at Login</code>. Click the plus button<br />
|
||||||
|
and select the volume you would like to mount at login.</p>
|
||||||
|
<p><img src="/articles/images/2024-03-15-login.png" alt="login" /></p>
|
||||||
|
<p>Once you have it setup so that the server is connected on login, you can also set it up as location<br />
|
||||||
|
for Time Machine Backups. <code>System Settings -&gt; General -&gt; Time Machine</code></p>
|
||||||
|
<p><img src="/articles/images/2024-03-15-time-machine.png" alt="time-machine" /></p></content>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<id>http://localhost:3000/articles/2024/elevating-hvac/</id>
|
||||||
|
<title>Elevating HVAC: A Skilled Trade Beyond Labor</title>
|
||||||
|
<updated>2025-02-19T21:25:29Z</updated>
|
||||||
|
<content type="html"><p>This is a guest post from my good friend, <strong>Ty Branaman</strong>.</p>
|
||||||
|
<h2>Introduction:</h2>
|
||||||
|
<p>Heating, Ventilation, and Air Conditioning (HVAC) is often mistakenly categorized as a simple labor<br />
|
||||||
|
job, overshadowing the intricate skill set and technical expertise required in this field. Labor<br />
|
||||||
|
jobs are also very important positions needed to keep society running. HVAC, like other skilled<br />
|
||||||
|
trades, demands a high level of knowledge, precision, and adaptability. This article aims to shed<br />
|
||||||
|
light on the misconception surrounding HVAC, emphasizing its status as a skilled trade that plays a<br />
|
||||||
|
pivotal role in creating comfortable and efficient living and working environments.</p>
|
||||||
|
<h2>Technical Proficiency:</h2>
|
||||||
|
<p>One of the defining features that distinguish HVAC as a skilled trade is the level of technical<br />
|
||||||
|
proficiency required. HVAC professionals must have a deep understanding of thermodynamics, fluid<br />
|
||||||
|
mechanics, electrical circuits, Psychrometrics and air properties. This knowledge is essential for<br />
|
||||||
|
designing, installing, and maintaining HVAC systems that operate seamlessly and efficiently.</p>
|
||||||
|
<h2>System Design and Installation:</h2>
|
||||||
|
<p>HVAC professionals are involved in the intricate process of designing and installing heating,<br />
|
||||||
|
ventilation, and air conditioning systems. This task requires not only a thorough understanding of<br />
|
||||||
|
the physical principles governing HVAC but also the ability to tailor solutions to meet the unique<br />
|
||||||
|
needs of each space. Proper system design and installation are crucial for achieving optimal energy<br />
|
||||||
|
efficiency and performance.</p>
|
||||||
|
<h2>Diagnostic Skills:</h2>
|
||||||
|
<p>Troubleshooting and diagnosing issues in HVAC systems require a keen analytical mind and<br />
|
||||||
|
problem-solving skills. Skilled HVAC technicians possess the ability to identify and rectify<br />
|
||||||
|
problems efficiently, ensuring minimal downtime and disruption to the comfort of occupants. This<br />
|
||||||
|
diagnostic acumen is a hallmark of a trade that goes beyond routine labor.</p>
|
||||||
|
<h2>Adaptability to Advanced Technologies:</h2>
|
||||||
|
<p>The HVAC industry is in a constant state of evolution, with new technologies and innovations<br />
|
||||||
|
continuously being introduced. Skilled HVAC professionals are adaptable and stay abreast of these<br />
|
||||||
|
advancements. From smart thermostats to energy-efficient systems, they integrate cutting-edge<br />
|
||||||
|
technologies to provide state-of-the-art solutions for their clients.</p>
|
||||||
|
<h2>Safety and Compliance:</h2>
|
||||||
|
<p>Safety is paramount in the HVAC trade. Professionals must adhere to strict safety protocols to<br />
|
||||||
|
protect both themselves and the occupants of the spaces they work in. Additionally, compliance with<br />
|
||||||
|
industry regulations and codes is a testament to the skilled nature of the trade, ensuring that HVAC<br />
|
||||||
|
systems meet the highest standards of safety and efficiency.</p>
|
||||||
|
<h2>Continual Learning and Certification:</h2>
|
||||||
|
<p>Unlike a labor job, HVAC professionals engage in continual learning to stay current with industry<br />
|
||||||
|
trends and technological advancements. Many pursue certifications and attend training programs to<br />
|
||||||
|
enhance their skills and expand their knowledge base. This commitment to ongoing education is a<br />
|
||||||
|
hallmark of skilled trades.</p>
|
||||||
|
<h2>Conclusion:</h2>
|
||||||
|
<p>Heating, Ventilation, and Air Conditioning is undeniably a skilled trade that goes beyond the<br />
|
||||||
|
perception of a labor job. Labor jobs are also very important to the function of society and I have<br />
|
||||||
|
proudly done these jobs myself. The technical proficiency, problem-solving abilities, adaptability,<br />
|
||||||
|
and commitment to safety make HVAC professionals essential contributors to the creation of<br />
|
||||||
|
comfortable and efficient indoor environments. It is crucial to recognize and appreciate the skill<br />
|
||||||
|
set inherent in the HVAC trade, as it plays a vital role in shaping the quality of life for<br />
|
||||||
|
individuals and the functionality of diverse spaces.</p>
|
||||||
|
<ul>
|
||||||
|
<li>Ty Branaman</li>
|
||||||
|
</ul></content>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<id>http://localhost:3000/articles/2023/most-important-job/</id>
|
||||||
|
<title>Most Important Job</title>
|
||||||
|
<updated>2025-02-19T21:21:54Z</updated>
|
||||||
|
<content type="html"><p>This short tech tip is about something one of my good friends in the trade told me a long time ago,<br />
|
||||||
|
that has stuck with me through the years. It is a simple phrase / mindset.</p>
|
||||||
|
<blockquote>
|
||||||
|
<p>“The current job you’re on, is the most important job of your day”.</p>
|
||||||
|
</blockquote>
|
||||||
|
<p>This mindset should be carried from the dispatcher, manager, and technician to make this successful.<br />
|
||||||
|
I’m not gonna lie and say this is always easy, or even always possible, but if you strive to use<br />
|
||||||
|
this mindset then you will gain lifelong customers and satisfaction of not having loose ends hanging<br />
|
||||||
|
out there.</p>
|
||||||
|
<p>I do think it’s also important to acknowledge that there are times that a technician has exhausted<br />
|
||||||
|
all their options, maybe they just don’t have the mental capacity anymore to continue with a problem<br />
|
||||||
|
job, or need a break to come back another day with a fresh set of eyes, etc… This is also an<br />
|
||||||
|
important thing for a technician to realize, and hopefully those type of instances are much more few<br />
|
||||||
|
and far between, but I do want to acknowledge that scenario does also exist.</p>
|
||||||
|
<p>If you are a business owner, then this is something to consider instilling in your operations.<br />
|
||||||
|
Empower your technicians and dispatchers to understand when things need to be shuffled around in<br />
|
||||||
|
order to accommodate taking care of the customer at hand. It costs a lot of money to get a<br />
|
||||||
|
technician to job, so minimizing truck rolls to the same job is important from a business<br />
|
||||||
|
standpoint.</p>
|
||||||
|
<p>This was just a quick tech tip of something that has been rolling around in my mind lately. I hope<br />
|
||||||
|
you find it helpful and it sticks with you through your career as it has mine.</p></content>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<id>http://localhost:3000/articles/2023/cancel-this/</id>
|
||||||
|
<title>Cancel This</title>
|
||||||
|
<updated>2025-02-19T21:17:16Z</updated>
|
||||||
|
<content type="html"><p>This post is going to be hard to put into words, it’s going to seem egotistical at points, but know<br />
|
||||||
|
that my actions / feelings online are the same as they are if you met me in person. The problem with<br />
|
||||||
|
online interactions is tone and other subtleties do not come across, so it’s hard to tell when<br />
|
||||||
|
someone is joking or being serious.</p>
|
||||||
|
<h2>The Meat</h2>
|
||||||
|
<p>It has been brought to my attention that someone out there thinks that I’m sexist and should not<br />
|
||||||
|
speak at the HVAC School symposium because of it. They are holding a curse word against me that I<br />
|
||||||
|
said two years ago, in the moment A) it was fitting and B) it was one of those times that my mouth<br />
|
||||||
|
was working faster than my brain (raise your hand if that’s ever happened to you).</p>
|
||||||
|
<p>I am an open book, I am not afraid of showing failures and strengths. I’ve never claimed to be<br />
|
||||||
|
perfect (well, actually I have but it’s always a joke). I’m not at all condoning what I’ve said in<br />
|
||||||
|
the past, nor will I repeat it out of context now, but I communicate with people like adults and I<br />
|
||||||
|
look at people as piers. We do not always have to agree with one another, conflict helps us learn<br />
|
||||||
|
where to grow, but we also can not expect people to change to fit our wants / needs, that’s just not<br />
|
||||||
|
how it works.</p>
|
||||||
|
<p>I do not at all agree with the tactics used by whomever is behind this. I would happily discuss this<br />
|
||||||
|
in private or out in the open. You can find all my contact / social information in the sidebar of<br />
|
||||||
|
this website and I’ve offered up my cell phone number in private groups that we are all probably a<br />
|
||||||
|
part of.</p>
|
||||||
|
<h2>The Potatoes</h2>
|
||||||
|
<p>I am a father of 3 girls, I have a sister, talk crap about my mom and you’ll find out who I am! I<br />
|
||||||
|
love women, I have no problem with women in the trades, I encourage women who are in the trades. I<br />
|
||||||
|
try to help every person that I can, if I can. I have failed more times than you can imagine! I am<br />
|
||||||
|
self taught in about everything I do, so I give of it freely. I have all kinds of work to do to grow<br />
|
||||||
|
into the man that I should be, but at the same time, I am not afraid to be the man that I am today.<br />
|
||||||
|
I will greet you by whatever pronoun you want to be referred as.</p>
|
||||||
|
<p>I would love to say that I don’t judge people, but I do, just as I’m being judged! I am fine with<br />
|
||||||
|
someone judging me and having opinions about me, I mean that is our right. I will not say that<br />
|
||||||
|
person is wrong, because in their mind they’re right. What I will not do is stop being myself. I<br />
|
||||||
|
know for a fact that I’ve helped more people than this person has gotten “cancelled”. I will<br />
|
||||||
|
continue to help people in the trades, homeowners, or people in need. I also will not remain quiet!<br />
|
||||||
|
I will give my opinion like it or not. There are people in my corner that really know me and my<br />
|
||||||
|
intentions.</p>
|
||||||
|
<h2>Final Words</h2>
|
||||||
|
<p>The trades are rough around the edges, just as am I. The trades are a slow turning ship (just look<br />
|
||||||
|
at how many still do not follow proper practices, etc. even with the capabilities and resources<br />
|
||||||
|
available today).</p>
|
||||||
|
<p>If you are new / coming into the trades then I hope you are not overly sensitive to foul language<br />
|
||||||
|
and other inappropriate comments. Thick skin is valuable in the trades, but at the same time don’t<br />
|
||||||
|
be afraid to speak up if something offends you. Remember we are adults, we can handle disagreements<br />
|
||||||
|
like adults (well, some of us can). Adults can learn from those of any age, they can reflect on<br />
|
||||||
|
their own behavior and make their own decisions.</p>
|
||||||
|
<p>I personally think that being offended is not a bad thing, it causes us to reflect / repair our<br />
|
||||||
|
foundational beliefs. I hope that we can stop with this “cancel culture” of today, stop hiding<br />
|
||||||
|
behind a keyboard, and be a diverse community.</p>
|
||||||
|
<p>To wrap things up, I just want to reiterate that I am not at all mad at whomever is behind this. To<br />
|
||||||
|
everyone out there who has shown me love and support, I greatly appreciate it.</p></content>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<id>http://localhost:3000/articles/2023/hope/</id>
|
||||||
|
<title>Hope</title>
|
||||||
|
<updated>2025-02-19T21:13:20Z</updated>
|
||||||
|
<content type="html"><p>This is a piggy-back article off of<br />
|
||||||
|
<a href="https://mhoush.com/posts/20231018224631-the-struggle/">The Struggle</a> article that I had recently.</p>
|
||||||
|
<p>I was a bit of a “Debbie Downer” in that article, which is okay, I get that way sometimes. In this<br />
|
||||||
|
article I’d like to take a minute to layout some of the things that give me hope, things that I<br />
|
||||||
|
focus on to try and kick myself out of the rut I can get into sometimes.</p>
|
||||||
|
<p>I believe it’s important to have <strong>hope</strong>, to realize that feeling down is normal / part of being<br />
|
||||||
|
human. It’s just as important to have hope. For some it is a harder thing to focus on, it may be<br />
|
||||||
|
easy for us to try and dwell in negative feelings, to some that may feel more comfortable. When<br />
|
||||||
|
we’re feeling cynical, it’s easy to feed the negativity, although it’s rarely helpful.</p>
|
||||||
|
<h2>Hope</h2>
|
||||||
|
<p>One of the things that I try to focus on is that I’m human, it brings me hope to realize that I’m<br />
|
||||||
|
not the only one who feels the way that I do. This was evident by the feedback on my previous<br />
|
||||||
|
article.</p>
|
||||||
|
<blockquote>
|
||||||
|
<p>My problems are very much “first world problems”.</p>
|
||||||
|
</blockquote>
|
||||||
|
<p>Make no mistake, I’m selfish, but it’s the selfishness that makes me feel distant or disconnected.<br />
|
||||||
|
The times that I feel connected are without a doubt the times that I let go of my ego and focus on<br />
|
||||||
|
things outside of myself.</p>
|
||||||
|
<p>It’s the feeling I get from going to customers home and feeling truly appreciated. There’s no push<br />
|
||||||
|
back on price, no one telling me how I should run my business, no “the part only costs $x on<br />
|
||||||
|
amazon”, etc.</p>
|
||||||
|
<p>The feeling of seeing your child smile. The safety you feel when getting a hug from your mother or<br />
|
||||||
|
father. When you’re looking up at the stars and realize how small you actually are.</p>
|
||||||
|
<p>When you’re out with friends and trick the DJ into playing a Mr. Bungle song and no one else<br />
|
||||||
|
appreciates it, but you. The times when your guard is completely down and you laugh with abandon.</p>
|
||||||
|
<p>The smell of your lover’s hair when you’re holding them close. The joy you receive from sitting with<br />
|
||||||
|
your pets. The songs of nature, insects, birds, etc. The sounds of waves / water in the distance.</p>
|
||||||
|
<p>The feeling when you’ve helped someone learn a new skill, when something finally clicks and makes<br />
|
||||||
|
sense. When a complex topic is understood at a fundamental level. The breakthrough of a problem<br />
|
||||||
|
you’ve pondered for days / months / years.</p>
|
||||||
|
<h2>Conclusion</h2>
|
||||||
|
<p>There are so many things to be grateful for. This does not mean that there will not be hard times,<br />
|
||||||
|
there surely will be. This does not mean that you are wrong for having negative feelings, for<br />
|
||||||
|
feeling depressed or anxious. There are many around you that likely feel similar (they may just not<br />
|
||||||
|
be able to express it in the same way). You never truly know what the person next to you is dealing<br />
|
||||||
|
with. Be compassionate (including showing yourself compassion).</p>
|
||||||
|
<p>When you are feeling down, try to do something for someone else. Make your own list of things to be<br />
|
||||||
|
thankful for. Maybe my non-exhaustive list above will give you some ideas. Write those items down<br />
|
||||||
|
regularly so that you can look back on them when you feel out of balance.</p>
|
||||||
|
<p>There is plenty of negative energy in this world, be true and genuine and you will receive rewards.<br />
|
||||||
|
When you focus on blessings then the negativity will fade.</p>
|
||||||
|
<p>What impact are you going to leave with what little time we have?</p>
|
||||||
|
<p>I hope that you enjoyed this short article. Know that you are <em>NOT</em> alone, you are important, and<br />
|
||||||
|
that I appreciate <em>you!</em></p></content>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<id>http://localhost:3000/articles/2023/heat-recovery-chiller/</id>
|
||||||
|
<title>Heat Recovery Chiller</title>
|
||||||
|
<updated>2025-02-19T21:08:37Z</updated>
|
||||||
|
<content type="html"><p>This is an article that I wrote back in 2020, but I don’t believe that I published it anywhere, so<br />
|
||||||
|
I’m doing it now. I did discuss this on<br />
|
||||||
|
<a href="https://hvacrschool.com/podcasts/is-the-future-of-air-conditioning-self-contained-propane-chillers/">this episode of the HVAC School Podcast.</a></p>
|
||||||
|
<h2>Heat Recovery Chillers</h2>
|
||||||
|
<p>I have always had a love and passion for hydronic systems, perhaps it’s because they are not that<br />
|
||||||
|
common in most areas. The designs tend to be elegant and the flexibility is unparalleled by most<br />
|
||||||
|
equipment choices currently available in the U.S. I’m going to try to not get too far into the weeds<br />
|
||||||
|
in this article, but offer an overview of what I feel would be my dream system.</p>
|
||||||
|
<h2>The Source</h2>
|
||||||
|
<p>A heat recovery chiller will do simultaneous heating and cooling, as opposed to a traditional<br />
|
||||||
|
heat-pump or reverse cycle chiller that can only operate in one mode at a time. This system would<br />
|
||||||
|
have a second refrigerant to water heat exchanger and utilize the air-source when we don’t need to<br />
|
||||||
|
bank / store heat, or are running in heat only mode. There are several benefits to this style<br />
|
||||||
|
system, the main being that while operating simultaneous heating / cooling mode the COP of the<br />
|
||||||
|
system doubles. For example, the <a href="https://multiaqua.com/mhrc2/">Multi-Aqua MHRC2</a> shows a COP of<br />
|
||||||
|
about 8, which is approximately equivalent to 30 EER or 34 SEER. This gives us geothermal level<br />
|
||||||
|
performance without the need of a field.</p>
|
||||||
|
<h2>Indoor Portion</h2>
|
||||||
|
<p>The indoor portion of the system, we would utilize buffer tanks as thermal storage for the chiller.<br />
|
||||||
|
The buffer tanks give us several benefits, including longer run times for the chiller, load<br />
|
||||||
|
matching, and the ability to size for larger load (heating or cooling) without some of the problems<br />
|
||||||
|
that occur when over-sizing a traditional system. The buffer tanks also allow sizing more<br />
|
||||||
|
aggressively by having storage during peak load conditions.</p>
|
||||||
|
<p><img src="/articles/images/2023-10-27-buffers2.png" alt="buffer" /></p>
|
||||||
|
<p>This shows a cooling buffer tank as well as a heating buffer tank. The horizontal pumps are what<br />
|
||||||
|
circulate water through the chiller, while the vertical pumps are what distribute the water to the<br />
|
||||||
|
load / emitters. This configuration allows for water to be used for the loads first and extra<br />
|
||||||
|
capacity to go into the buffer tanks. The buffer tanks also offer hydraulic separation for the pumps<br />
|
||||||
|
(meaning that they won’t interfere with each other if / when there are different flow rates).<br />
|
||||||
|
Another advantage of the buffer tanks is that you can connect multiple heating or cooling sources in<br />
|
||||||
|
parallel to the system. This is shown by the extra tees in the hot buffer tank where we could<br />
|
||||||
|
connect something such as solar water collectors, pellet or wood boiler, or a conventional boiler.<br />
|
||||||
|
You’ll also notice on the right side of the hot buffer tank, that I am showing a brazed plate heat<br />
|
||||||
|
exchanger that would be used to supply domestic hot water.</p>
|
||||||
|
<h2>Distribution System</h2>
|
||||||
|
<p>This could be a number of things, from radiant panels, in-floor, high-output baseboard radiators,<br />
|
||||||
|
however I’m going to model it as a 4-pipe hydronic air handler.</p>
|
||||||
|
<p><img src="/articles/images/2023-10-27-ah.png" alt="ah" /></p>
|
||||||
|
<p>The hydronic air handler is able to provide cooling, heating, and re-heat dehumidification, all in<br />
|
||||||
|
one package. With a hydronic system, it would be very easy to load match by controlling the fan<br />
|
||||||
|
speed and utilizing a Delta-T pump or outdoor reset controls. These air handlers are available from<br />
|
||||||
|
several manufacturers and come in different styles from traditional (as shown), small duct high<br />
|
||||||
|
velocity systems, and even ductless styles.</p>
|
||||||
|
<h2>Disadvantages</h2>
|
||||||
|
<ol>
|
||||||
|
<li>Not highly available in the U.S.</li>
|
||||||
|
<li>When the chiller is down nothing works (not much different than traditional)</li>
|
||||||
|
<li>Lack of understanding / technicians afraid to work on this style system.</li>
|
||||||
|
<li>Potentially higher upfront costs.</li>
|
||||||
|
<li>Lack of design or planning could cause unhappy clients (same with traditional)</li>
|
||||||
|
<li>Distribution systems need to be designed around low water temperatures (not a drop in replacement<br />
|
||||||
|
for traditional boiler systems)</li>
|
||||||
|
</ol>
|
||||||
|
<h2>Advantages</h2>
|
||||||
|
<ol>
|
||||||
|
<li>Central plant for heating, cooling, and DHW (also a disadvantage)</li>
|
||||||
|
<li>Flexible distribution options / methods.</li>
|
||||||
|
<li>Self contained refrigerant circuit</li>
|
||||||
|
<li>Ability to produce / store thermal energy during off peak electrical hours</li>
|
||||||
|
<li>Ability to move BTU’s more efficiently through water than air</li>
|
||||||
|
<li>Long life for distribution system (50-100+ years)</li>
|
||||||
|
<li>Easier transition to natural / flammable refrigerants</li>
|
||||||
|
</ol>
|
||||||
|
<h2>Conclusion</h2>
|
||||||
|
<p>In conclusion, there are many advantages to this style system, as well as disadvantages. One of the<br />
|
||||||
|
main points is to think of the system in 3 distinct components, the source(s), thermal storage, and<br />
|
||||||
|
distribution. As mentioned, this only one concept, but in reality, there are many ways to accomplish<br />
|
||||||
|
this, which is one of it’s advantages. For example, perhaps in certain scenarios it makes sense to<br />
|
||||||
|
dump excess heat into a pool, create ice storage during off peak hours, cascade into another water<br />
|
||||||
|
-&gt; water heat pump for higher temperature distribution, incorporate solar collectors, and so on.</p>
|
||||||
|
<p>Thank you for reading all the way to the end!</p></content>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<id>http://localhost:3000/articles/2023/you-should-learn-markdown/</id>
|
||||||
|
<title>You Should Learn Markdown</title>
|
||||||
|
<updated>2025-02-19T20:51:49Z</updated>
|
||||||
|
<content type="html"><p>This is a quick article about why you should learn markdown.</p>
|
||||||
|
<h2>What is markdown</h2>
|
||||||
|
<p>Markdown is a “mark-up” language. It allows you to write content in plain text that can be easily<br />
|
||||||
|
converted to other formats, such as <strong>html, pdf, docx</strong>, and many more. All the articles written on<br />
|
||||||
|
this website are written in markdown, here’s an image of this article written in markdown.</p>
|
||||||
|
<p><img src="/articles/images/2023-10-21-markdown.png" alt="markdown" /></p>
|
||||||
|
<p>The reason you should learn markdown is that it allows you to focus on the content / text of your<br />
|
||||||
|
content with simple concepts for formatting. Markdown is used heavily in documenting software<br />
|
||||||
|
projects, which is how I got introduced to it, however it can scale all the way up to writing<br />
|
||||||
|
research papers or even books.</p>
|
||||||
|
<p>I use markdown for probably 80% of all the text documents I need to write, from company documents,<br />
|
||||||
|
web / software documentation, and so on. It allows me to get content out quickly without having to<br />
|
||||||
|
click around with formatting options in a program like <strong>Word</strong> or <strong>Pages</strong>. To be clear, a lot of<br />
|
||||||
|
the reports and things I generate for my <strong>Home Performance Assessments</strong> are written using<br />
|
||||||
|
<strong>Pages</strong> (for now at least) because I have templates that make the documents look more<br />
|
||||||
|
professional, however I am working on solutions to migrate those to be markdown based.</p>
|
||||||
|
<p>Markdown is supported in mostly all the <strong>Google</strong> tools, as well as the <strong>Outlook</strong> email client<br />
|
||||||
|
(which is one of my least favorite tools, BTW). It makes it simple to create tables, lists, and many<br />
|
||||||
|
common document related tasks.</p>
|
||||||
|
<h2>Resources</h2>
|
||||||
|
<p>You can learn more about the syntax used for markdown at<br />
|
||||||
|
<a href="https://www.markdownguide.org/basic-syntax/">markdownguide.org</a>.</p>
|
||||||
|
<h3>A non-exhaustive list of where you can use Markdown and editors.</h3>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Platform</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Google</td>
|
||||||
|
<td>Most goggle tools support markdown, docs, sheets, etc.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Outlook</td>
|
||||||
|
<td>Although I hate outlook email client, it does support markdown.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Dillinger.io</td>
|
||||||
|
<td>An online tool for writing / previewing markdown</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>MarkText</td>
|
||||||
|
<td>A multi-platform editor for writing markdown</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p>You can use tools such as <a href="https://pandoc.org/#">pandoc</a> to convert Markdown files to other formats.</p>
|
||||||
|
<p><img src="/articles/images/2023-10-21-pandoc.gif" alt="pandoc" /></p>
|
||||||
|
<h2>Conclusion</h2>
|
||||||
|
<p>I hope that you take the time to research and see if Markdown is good fit for your document /<br />
|
||||||
|
content creation.</p>
|
||||||
|
<p>Thanks for reading until the end!</p></content>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<id>http://localhost:3000/articles/2023/the-struggle/</id>
|
||||||
|
<title>The Struggle</title>
|
||||||
|
<updated>2025-02-19T20:53:34Z</updated>
|
||||||
|
<content type="html"><p>This is a get stuff of my chest article. Probably going to be a mixture of ranting and whining. If<br />
|
||||||
|
that is not your cup of tea then feel free to skip this article.</p>
|
||||||
|
<h2>The struggle</h2>
|
||||||
|
<p>It has been one of those “when it rains, it pours” type of weeks. As write this, I feel like a baby<br />
|
||||||
|
/ complainer, which is not my intention, but here it goes.</p>
|
||||||
|
<p>My aunt had a stroke and is likely not going to make it through the week. My aunt has always lived<br />
|
||||||
|
in Florida during my life / memory, but has always come to visit. She is my mom’s oldest sister (9<br />
|
||||||
|
years apart), so she helped raise my mother growing up. They’ve always had a close relationship and<br />
|
||||||
|
are like two peas in a pod. They would always visit us, especially while my grand-parents were still<br />
|
||||||
|
alive. She is currently not really awake or expected to make it. She does not eat / drink and<br />
|
||||||
|
they’ve basically just been making her comfortable.</p>
|
||||||
|
<p>One of my employees broke his neck over the weekend. I don’t have a ton of details on this subject,<br />
|
||||||
|
but he had surgery to fuse some discs back together and should eventually be ok, however it will be<br />
|
||||||
|
a long recovery time.</p>
|
||||||
|
<p>A few weeks ago, I commited one of the deadly sins of running a blower door test without checking /<br />
|
||||||
|
asking about the fireplaces, which caused lord knows how much damage from the soot that was spread<br />
|
||||||
|
throughout the living room(s).</p>
|
||||||
|
<p>An online friend lost her mother.</p>
|
||||||
|
<p>All of these things have just got me emotional.</p>
|
||||||
|
<h2>My secrets</h2>
|
||||||
|
<p>I am an emotional person, sometimes to my detriment. I’m prone to fits of anger and depression. I<br />
|
||||||
|
spent many years masking things through alcohol abuse and many other idiotic tendencies. I still<br />
|
||||||
|
drink on occasion, but not as I once did.</p>
|
||||||
|
<p>I often put my faith in folks, even if I haven’t met them in person, this can often lead to being<br />
|
||||||
|
let down. I guess I struggle sometimes with the reality of online relationships. I think that people<br />
|
||||||
|
are genuine, because I’m that way (how I act online is the same as I act in person for the most<br />
|
||||||
|
part). I will happily show / share the good and the bad, in hopes that someone may learn. This is<br />
|
||||||
|
not at all something to be ashamed of, or anything that I’d like to change, however it does on<br />
|
||||||
|
occasion lead me into turmoil when I find out some true identity / personality of someone.</p>
|
||||||
|
<p>I hold grudges, like forever grudges. It is very hard for me to get over somethings, even if I want<br />
|
||||||
|
to. I can sometimes put things out of my mind, but when I’m spinning, they will resurface. I want to<br />
|
||||||
|
forgive people, but it is just not the way it works for me often times. It takes a lot to get me<br />
|
||||||
|
beyond my breaking point, but once someone has gotten me there, there is likely no turning back for<br />
|
||||||
|
that person. Luckily, I can count on one hand the number of folks that I’ve had to cut out of my<br />
|
||||||
|
life for these reasons. I’d love to say that I’m a bigger / better person, that I forgive them, but<br />
|
||||||
|
truthfully I do not.</p>
|
||||||
|
<p>My emotions sometimes make me say things publicly that I should keep to myself. I don’t have a lot<br />
|
||||||
|
of regret around these things, because I generally mean what I say, and also feel we are entitled to<br />
|
||||||
|
opinions as well as entitled to change those opinions as often as we see fit. Although I don’t<br />
|
||||||
|
regret them per-se, it does make me wonder what type of impression it leaves (something for future<br />
|
||||||
|
pondering, perhaps).</p>
|
||||||
|
<p>I’m one of those that says “I don’t care what they think about me”, when I really do care what<br />
|
||||||
|
people think about me. This often leads to fear and anxiety, especially in social settings. I’m not<br />
|
||||||
|
the greatest at conversation, I’m better at writing or some interaction that gives me a bit of time<br />
|
||||||
|
to think before responding. Therefore, I’m quick to make a joke or something rather than having<br />
|
||||||
|
thoughtful / genuine responses.</p>
|
||||||
|
<h2>Community</h2>
|
||||||
|
<p>All of these things have just got me thinking about community. Community is an aspect that seems<br />
|
||||||
|
distant nowadays, even though we have more opportunity than ever. We call ourselves part of<br />
|
||||||
|
communities, especially online, but I’m not convinced that it is really community (or at least not<br />
|
||||||
|
most of the time, not saying it can’t be / in absolute terms).</p>
|
||||||
|
<p>I have met a lot of folks online that I consider true friends. Friends that I would do anything for<br />
|
||||||
|
and feel they would do anything for me, just like my real life friends who have stuck with me for<br />
|
||||||
|
many years. These are people that challenge me and how I think on a regular basis. They do their<br />
|
||||||
|
best to lift me up when I’m down.</p>
|
||||||
|
<p>It’s easy to hide when so much of our interactions are not really in person, to feel like the<br />
|
||||||
|
relationships we do have are not genuine, but that’s awfully cynical. I prefer to give people the<br />
|
||||||
|
benefit / trust they deserve until, at least until they don’t then see my part about holding grudges<br />
|
||||||
|
;)</p>
|
||||||
|
<p>Do you ever feel the same? Instead of being cynical and down, today, I’m trying to be positive. I’m<br />
|
||||||
|
trying to share a little bit of what I feel community should be. Although, I’ve never met HVAChicks<br />
|
||||||
|
Jennifer in real life, I read today about her mom and decided to take an hour or so to put together<br />
|
||||||
|
a website for the <a href="https://hvachicks.com">HVAChicks Community</a>, hoping it would bring a moment of<br />
|
||||||
|
happiness to her day. While I’ve deployed several websites in the past, this one for some reason was<br />
|
||||||
|
a total PITA, but I got through it. I could feel how grateful she was when I shared it with her (and<br />
|
||||||
|
it’s basic AF), but that truly made me feel useful / great after being down in the dumps for a bit.</p>
|
||||||
|
<h2>Conclusion</h2>
|
||||||
|
<p>I’ve probably rambled enough and am losing direction here, so I will end with a few things.</p>
|
||||||
|
<ol>
|
||||||
|
<li>Build the community around you that you want / deserve.</li>
|
||||||
|
<li>Don’t be so quick to pass judgment.</li>
|
||||||
|
<li>Spend time with your loved ones, while you can.</li>
|
||||||
|
<li>Tell someone you love them.</li>
|
||||||
|
</ol>
|
||||||
|
<p>Finally, I’d like to shout out some people that I’m grateful for. This is non-exhaustive list, if I<br />
|
||||||
|
left you off, I’m sorry and please do not take it personally.</p>
|
||||||
|
<ol>
|
||||||
|
<li>Bryan Orr
|
||||||
|
<ul>
|
||||||
|
<li>Bryan has cultivated an awesome group / community that I’m proud to be a part of. His time and<br />
|
||||||
|
commitment to the HVAC industry is something that I hope he himself is proud of. Without Bryan,<br />
|
||||||
|
mostly all the following names would not even be in my vocabulary.</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Ty Branaman (forget exactly how to spell his last name).
|
||||||
|
<ul>
|
||||||
|
<li>Ty has such a great personality during his videos / training and I’m sure it’s a struggle to be<br />
|
||||||
|
positive all the time, however it brings me hope and joy everytime!</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Dustin (mother f’n) Cole
|
||||||
|
<ul>
|
||||||
|
<li>Dustin is like a brother that I never had, he’s a true master of his craft and I know that I<br />
|
||||||
|
can rely on him anytime I need it!</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Genry Garcia
|
||||||
|
<ul>
|
||||||
|
<li>The cuban crusader who has taught me so much about home performance, and especially ZPD (baby,<br />
|
||||||
|
baby)!</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Chris Hughes
|
||||||
|
<ul>
|
||||||
|
<li>It’s hard to put into words here, but I know that Chris is there to talk when I need it and<br />
|
||||||
|
he’s a great motivator because of his action items :)</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Eric Kaiser
|
||||||
|
<ul>
|
||||||
|
<li>I think genuine when I think of Eric, I hear his voice in my head when I write reports because<br />
|
||||||
|
of guidance he has given in the past. He truly wants to help teach people.</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Michael Cianfracco (??)
|
||||||
|
<ul>
|
||||||
|
<li>Man does he make me laugh and we share a passion for the 4-Roses.</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>HVAChicks Jennifer (I’ll butcher her last name from memory)
|
||||||
|
<ul>
|
||||||
|
<li>Jennifer is inspiring with her goals and everything she does to help anyone in the industry. I<br />
|
||||||
|
can’t wait to meet her in person one day soon!</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>HVAC Overtime Crew
|
||||||
|
<ul>
|
||||||
|
<li>I’m lumping these guys together because I truly enjoy when I’m able to make their live stream<br />
|
||||||
|
on Friday’s. And I interact with A-Team a lot and really appreciate him / them!</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Alicia Hollon
|
||||||
|
<ul>
|
||||||
|
<li>Alicia is so awesome to me, I mean she just made my favorite pancakes and sausage for dinner,<br />
|
||||||
|
love you babe!</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
<p>Lastly, I have to shout out to my mom. I know she’s going through a rough time with my aunt<br />
|
||||||
|
currently. My mother is the kindest gentlest soul that I’ve ever met. I look up to all 5’ of her!</p>
|
||||||
|
<p>At any rate, thanks for sticking it out to the end through my ramblings. Be kind to someone today<br />
|
||||||
|
and tomorrow!</p></content>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<id>http://localhost:3000/articles/2023/calculate-seer-degradation-by-age/</id>
|
||||||
|
<title>Calculate SEER Degradation by Age</title>
|
||||||
|
<updated>2025-02-19T21:55:30Z</updated>
|
||||||
|
<content type="html"><p>This is a quick tech-tip to learn how to calculate the degradation of SEER based<br />
|
||||||
|
on age.</p>
|
||||||
|
<p>The degradation of SEER is due to fouling of the evaporator coil with dirt and<br />
|
||||||
|
refrigerant charge losses. It should be noted that this is not true for all<br />
|
||||||
|
applications, but is used as an estimation based on research done by the <code>DOE</code><br />
|
||||||
|
of the average degradation based on systems tested.</p>
|
||||||
|
<h2>Formula</h2>
|
||||||
|
<p>This is the formula used to calculate the SEER based on age of the evaporator<br />
|
||||||
|
coil / air handler.</p>
|
||||||
|
<p>$$ SEER_d = SEER_n \times (1 - M)^{age} $$</p>
|
||||||
|
<p>| Where | |<br />
|
||||||
|
| –––– | —————————————— | — |<br />
|
||||||
|
| $SEER_d$ | Degradated SEER rating |<br />
|
||||||
|
| $SEER_n$ | Nominal SEER rating when equipment was new | |<br />
|
||||||
|
| M | Maintenance factor, 0.01-0.03 |<br />
|
||||||
|
| age | The age of the equipment, in years |</p>
|
||||||
|
<p>The maintenance factor of 0.01 is for expertly maintained equipment and 0.03 is<br />
|
||||||
|
for unmaintained. The maintenance factor in essence is based on 1%-3%<br />
|
||||||
|
degradation per year, however there are some<br />
|
||||||
|
<a href="https://publications.energyresearch.ucf.edu/wp-content/uploads/2018/09/FSEC-PF-474-18.pdf">studies</a><br />
|
||||||
|
that show that this can actually be as high as 5% or above depending on climate.<br />
|
||||||
|
We could use up to 0.05 as the maintenance factor, just to see what the “range”<br />
|
||||||
|
of degradation would be.</p>
|
||||||
|
<p>Interestingly, the study linked also shows that the degradation is higher the<br />
|
||||||
|
higher the tonnage of the equipment. It also shows that the degradation is lower<br />
|
||||||
|
per year the higher the nominal SEER rating of the system (which is corelated to<br />
|
||||||
|
using TXV’s and lower airflow rates because of the equipment having multiple<br />
|
||||||
|
stages).</p>
|
||||||
|
<h2>Example</h2>
|
||||||
|
<p>Let’s consider that we have a 13 SEER piece of equipment that was matched when<br />
|
||||||
|
installed and the system is 15 years old.</p>
|
||||||
|
<p>Plugging those numbers into our formula.</p>
|
||||||
|
<hr />
|
||||||
|
<h4>Lowest Range (1% degradation / year)</h4>
|
||||||
|
<p>$$ SEER_d = 13 \times (1 - 0.01)^{15} = 11.2 $$</p>
|
||||||
|
<hr />
|
||||||
|
<h4>Highest Rage (5% degradation / year)</h4>
|
||||||
|
<p>$$ SEER_d = 13 \times (1 - 0.05)^{15} = 6 $$</p>
|
||||||
|
<hr />
|
||||||
|
<p>An expertly maintained system may not have degraded that much, with an 11.2 SEER<br />
|
||||||
|
vs. a poorly maintained / dirty system that also suffers from refrigerant charge<br />
|
||||||
|
losses can be as low as 6 SEER.</p>
|
||||||
|
<p>Thanks for learning how to estimate SEER degradation based on equipment age!</p></content>
|
||||||
|
</entry>
|
||||||
|
</feed>
|
||||||
BIN
deploy/articles/images/2023-09-19-calculate-seer-degradation-by-age.png
LFS
Normal file
BIN
deploy/articles/images/2023-09-19-calculate-seer-degradation-by-age.png
LFS
Normal file
Binary file not shown.
BIN
deploy/articles/images/2023-10-18-the-struggle.png
LFS
Normal file
BIN
deploy/articles/images/2023-10-18-the-struggle.png
LFS
Normal file
Binary file not shown.
BIN
deploy/articles/images/2023-10-21-markdown.png
LFS
Normal file
BIN
deploy/articles/images/2023-10-21-markdown.png
LFS
Normal file
Binary file not shown.
BIN
deploy/articles/images/2023-10-21-pandoc.gif
LFS
Normal file
BIN
deploy/articles/images/2023-10-21-pandoc.gif
LFS
Normal file
Binary file not shown.
BIN
deploy/articles/images/2023-10-21-you-should-learn-markdown.png
LFS
Normal file
BIN
deploy/articles/images/2023-10-21-you-should-learn-markdown.png
LFS
Normal file
Binary file not shown.
BIN
deploy/articles/images/2023-10-27-ah.png
LFS
Normal file
BIN
deploy/articles/images/2023-10-27-ah.png
LFS
Normal file
Binary file not shown.
BIN
deploy/articles/images/2023-10-27-buffers2.png
LFS
Normal file
BIN
deploy/articles/images/2023-10-27-buffers2.png
LFS
Normal file
Binary file not shown.
BIN
deploy/articles/images/2023-10-27-heat-recovery-chiller.png
LFS
Normal file
BIN
deploy/articles/images/2023-10-27-heat-recovery-chiller.png
LFS
Normal file
Binary file not shown.
BIN
deploy/articles/images/2023-10-30-hope.png
LFS
Normal file
BIN
deploy/articles/images/2023-10-30-hope.png
LFS
Normal file
Binary file not shown.
BIN
deploy/articles/images/2023-12-12-cancel-this.gif
LFS
Normal file
BIN
deploy/articles/images/2023-12-12-cancel-this.gif
LFS
Normal file
Binary file not shown.
BIN
deploy/articles/images/2023-12-14-most-important-job.gif
LFS
Normal file
BIN
deploy/articles/images/2023-12-14-most-important-job.gif
LFS
Normal file
Binary file not shown.
BIN
deploy/articles/images/2024-02-27-elevating-hvac.png
LFS
Normal file
BIN
deploy/articles/images/2024-02-27-elevating-hvac.png
LFS
Normal file
Binary file not shown.
BIN
deploy/articles/images/2024-03-15-connect.png
LFS
Normal file
BIN
deploy/articles/images/2024-03-15-connect.png
LFS
Normal file
Binary file not shown.
BIN
deploy/articles/images/2024-03-15-login.png
LFS
Normal file
BIN
deploy/articles/images/2024-03-15-login.png
LFS
Normal file
Binary file not shown.
BIN
deploy/articles/images/2024-03-15-ssh.png
LFS
Normal file
BIN
deploy/articles/images/2024-03-15-ssh.png
LFS
Normal file
Binary file not shown.
BIN
deploy/articles/images/2024-03-15-status.png
LFS
Normal file
BIN
deploy/articles/images/2024-03-15-status.png
LFS
Normal file
Binary file not shown.
BIN
deploy/articles/images/2024-03-15-time-machine.png
LFS
Normal file
BIN
deploy/articles/images/2024-03-15-time-machine.png
LFS
Normal file
Binary file not shown.
BIN
deploy/articles/images/2024-03-15-unvr-as-nas.png
LFS
Normal file
BIN
deploy/articles/images/2024-03-15-unvr-as-nas.png
LFS
Normal file
Binary file not shown.
BIN
deploy/articles/images/2024-04-04-pgp-encryption-introduction.gif
LFS
Normal file
BIN
deploy/articles/images/2024-04-04-pgp-encryption-introduction.gif
LFS
Normal file
Binary file not shown.
BIN
deploy/articles/images/2024-04-09-free-as-in-freedom.png
LFS
Normal file
BIN
deploy/articles/images/2024-04-09-free-as-in-freedom.png
LFS
Normal file
Binary file not shown.
BIN
deploy/articles/images/2025-01-05-vapor-htmx-todo-app.png
LFS
Normal file
BIN
deploy/articles/images/2025-01-05-vapor-htmx-todo-app.png
LFS
Normal file
Binary file not shown.
BIN
deploy/articles/images/2025-01-05-vapor.gif
LFS
Normal file
BIN
deploy/articles/images/2025-01-05-vapor.gif
LFS
Normal file
Binary file not shown.
284
deploy/articles/index.html
Normal file
284
deploy/articles/index.html
Normal file
@@ -0,0 +1,284 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en-US">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta content="#0e1112" media="(prefers-color-scheme: dark)" name="theme-color"/>
|
||||||
|
<meta content="#566B78" media="(prefers-color-scheme: light)" name="theme-color"/>
|
||||||
|
<meta content="Michael Housh" name="author"/>
|
||||||
|
<meta content="Mhoush" name="apple-mobile-web-app-title"/>
|
||||||
|
<meta content="initial-scale=1.0, width=device-width" name="viewport"/>
|
||||||
|
<meta content="telephone=no" name="format-detection"/>
|
||||||
|
<meta content="True" name="HandheldFriendly"/>
|
||||||
|
<meta content="320" name="MobileOptimized"/>
|
||||||
|
<meta content="Mhoush" name="og:site_name"/>
|
||||||
|
<meta content="hvac, developer, swift, home-performance, design" name="keywords"/>
|
||||||
|
<title>
|
||||||
|
mhoush: Articles
|
||||||
|
</title>
|
||||||
|
<link href="/static/favicon.ico" rel="shortcut icon"/>
|
||||||
|
<link href="/static/output.css" rel="stylesheet"/>
|
||||||
|
<link href="/static/style.css" rel="stylesheet"/>
|
||||||
|
<link href="/articles/feed.xml" rel="alternate" title="mhoush" type="application/rss+xml"/>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body class="bg-page text-white pb-5 font-avenir articles">
|
||||||
|
<header class="bg-nav text-gray py-4 text-base/6 lg:fixed w-full lg:h-[62px]">
|
||||||
|
<nav class="container flex gap-x-5 lg:gap-x-y items-center">
|
||||||
|
<ul class="flex flex-wrap gap-x-2 lg:gap-x-5">
|
||||||
|
<li>
|
||||||
|
<a class href="/">Home</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="active" href="/articles/">Articles</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class href="/about/">About</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<div class="container pt-12 lg:pt-28">
|
||||||
|
<div>
|
||||||
|
<h1 class="text-4xl font-extrabold mb-12">
|
||||||
|
2025
|
||||||
|
</h1>
|
||||||
|
<div class="grid gap-10 mb-16">
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2025/vapor-htmx-todo-app/">Vapor + HTMX</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">January 05, 2025</span><a href="/articles/tag/general/">general</a>, <a href="/articles/tag/programming/">programming</a> and <a href="/articles/tag/software/">software</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2025/vapor-htmx-todo-app/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2025-01-05-vapor-htmx-todo-app.png"/>
|
||||||
|
Build an example application using Vapor and HTMX.
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h1 class="text-4xl font-extrabold mb-12">
|
||||||
|
2024
|
||||||
|
</h1>
|
||||||
|
<div class="grid gap-10 mb-16">
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2024/free-as-in-freedom/">Free As In Freedom</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">April 09, 2024</span><a href="/articles/tag/general/">general</a>, <a href="/articles/tag/open-source/">open-source</a> and <a href="/articles/tag/software/">software</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2024/free-as-in-freedom/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2024-04-09-free-as-in-freedom.png"/>
|
||||||
|
Salute to open-source software engineers
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2024/pgp-encryption-introduction/">PGP Encryption Introduction</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">April 04, 2024</span><a href="/articles/tag/gnupgp/">GnuPGP</a>, <a href="/articles/tag/pgp/">PGP</a>, <a href="/articles/tag/programming/">programming</a> and <a href="/articles/tag/security/">security</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2024/pgp-encryption-introduction/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2024-04-04-pgp-encryption-introduction.gif"/>
|
||||||
|
In this article I introduce PGP and show a use case for me, which perhaps you can use as well.
|
||||||
|
What is PGP
|
||||||
|
PGP stands for Pretty Good Privacy, it was first developed in 1991 by Phil Zimmermann. PGP uses
|
||||||
|
cryptographic privacy and authentication and is...
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2024/unvr-as-nas/">UNVR as NAS</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">March 15, 2024</span><a href="/articles/tag/how-to/">how-to</a>, <a href="/articles/tag/nas/">nas</a>, <a href="/articles/tag/networking/">networking</a> and <a href="/articles/tag/programming/">programming</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2024/unvr-as-nas/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2024-03-15-unvr-as-nas.png"/>
|
||||||
|
In this post, I’m going to show how to setup a Samba server on a Ubiquity UNVR so that it can be
|
||||||
|
used as NAS (network attached storage). Be aware that this should be done with caution and may void
|
||||||
|
any warranty on your UNVR as we are using it for...
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2024/elevating-hvac/">Elevating HVAC: A Skilled Trade Beyond Labor</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">February 27, 2024</span><a href="/articles/tag/hvac/">HVAC</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2024/elevating-hvac/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2024-02-27-elevating-hvac.png"/>
|
||||||
|
This is a guest post from my good friend, Ty Branaman.
|
||||||
|
Introduction:
|
||||||
|
Heating, Ventilation, and Air Conditioning (HVAC) is often mistakenly categorized as a simple labor
|
||||||
|
job, overshadowing the intricate skill set and technical expertise required in...
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h1 class="text-4xl font-extrabold mb-12">
|
||||||
|
2023
|
||||||
|
</h1>
|
||||||
|
<div class="grid gap-10 mb-16">
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2023/most-important-job/">Most Important Job</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">December 14, 2023</span><a href="/articles/tag/hvac/">HVAC</a> and <a href="/articles/tag/tech-tip/">tech-tip</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2023/most-important-job/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2023-12-14-most-important-job.gif"/>
|
||||||
|
This short tech tip is about something one of my good friends in the trade told me a long time ago,
|
||||||
|
that has stuck with me through the years. It is a simple phrase / mindset.
|
||||||
|
|
||||||
|
“The current job you’re on, is the most important job of your day”.
|
||||||
|
|
||||||
|
This...
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2023/cancel-this/">Cancel This</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">December 12, 2023</span><a href="/articles/tag/hvac/">HVAC</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2023/cancel-this/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2023-12-12-cancel-this.gif"/>
|
||||||
|
This post is going to be hard to put into words, it’s going to seem egotistical at points, but know
|
||||||
|
that my actions / feelings online are the same as they are if you met me in person. The problem with
|
||||||
|
online interactions is tone and other subtleties...
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2023/hope/">Hope</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">October 30, 2023</span><a href="/articles/tag/general/">general</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2023/hope/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2023-10-30-hope.png"/>
|
||||||
|
This is a piggy-back article off of
|
||||||
|
The Struggle article that I had recently.
|
||||||
|
I was a bit of a “Debbie Downer” in that article, which is okay, I get that way sometimes. In this
|
||||||
|
article I’d like to take a minute to layout some of the things that give...
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2023/heat-recovery-chiller/">Heat Recovery Chiller</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">October 27, 2023</span><a href="/articles/tag/hvac/">HVAC</a>, <a href="/articles/tag/chiller/">chiller</a> and <a href="/articles/tag/hydronics/">hydronics</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2023/heat-recovery-chiller/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2023-10-27-heat-recovery-chiller.png"/>
|
||||||
|
This is an article that I wrote back in 2020, but I don’t believe that I published it anywhere, so
|
||||||
|
I’m doing it now. I did discuss this on
|
||||||
|
this episode of the HVAC School Podcast.
|
||||||
|
Heat Recovery Chillers
|
||||||
|
I have always had a love and passion for...
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2023/you-should-learn-markdown/">You Should Learn Markdown</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">October 21, 2023</span><a href="/articles/tag/hvac/">HVAC</a>, <a href="/articles/tag/general/">general</a> and <a href="/articles/tag/programming/">programming</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2023/you-should-learn-markdown/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2023-10-21-you-should-learn-markdown.png"/>
|
||||||
|
This is a quick article about why you should learn markdown.
|
||||||
|
What is markdown
|
||||||
|
Markdown is a “mark-up” language. It allows you to write content in plain text that can be easily
|
||||||
|
converted to other formats, such as html, pdf, docx, and many more. All...
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2023/the-struggle/">The Struggle</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">October 18, 2023</span><a href="/articles/tag/article/">article</a> and <a href="/articles/tag/general/">general</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2023/the-struggle/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2023-10-18-the-struggle.png"/>
|
||||||
|
This is a get stuff of my chest article. Probably going to be a mixture of ranting and whining. If
|
||||||
|
that is not your cup of tea then feel free to skip this article.
|
||||||
|
The struggle
|
||||||
|
It has been one of those “when it rains, it pours” type of weeks. As...
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h2 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2023/calculate-seer-degradation-by-age/">Calculate SEER Degradation by Age</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-gray gray-links text-sm mb-4">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">September 19, 2023</span><a href="/articles/tag/hvac/">HVAC</a>, <a href="/articles/tag/formulas/">formulas</a> and <a href="/articles/tag/tech-tip/">tech-tip</a>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="/articles/2023/calculate-seer-degradation-by-age/"><div>
|
||||||
|
<img alt="banner" src="http://localhost:3000/articles/images/2023-09-19-calculate-seer-degradation-by-age.png"/>
|
||||||
|
This is a quick tech-tip to learn how to calculate the degradation of SEER based
|
||||||
|
on age.
|
||||||
|
The degradation of SEER is due to fouling of the evaporator coil with dirt and
|
||||||
|
refrigerant charge losses. It should be noted that this is not true for...
|
||||||
|
</div></a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="site-footer container text-gray gray-links border-t border-light text-center pt-6 mt-8 text-sm">
|
||||||
|
<p>
|
||||||
|
Copyright © Michael Housh 2023-2025.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Built in Swift using
|
||||||
|
<a href="https://github.com/loopwerk/Saga" rel="nofollow" target="_blank">Saga</a>
|
||||||
|
(<a href="https://github.com/m-housh/mhoush.com" rel="nofollow" target="_blank">source</a>).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="http://localhost:3000/articles/feed.xml" rel="nofollow" target="_blank">RSS</a>
|
||||||
|
|
|
||||||
|
<a href="https://github.com/m-housh" rel="nofollow" target="_blank">Github</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.youtube.com/channel/UCb58SeURd5bObfTiL0KoliA" rel="nofollow" target="_blank">Youtube</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.facebook.com/michael.housh" rel="nofollow" target="_blank">Facebook</a>
|
||||||
|
|
|
||||||
|
<a href="mailto:michael@mhoush.com" rel="nofollow">Email</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
157
deploy/articles/tag/article/feed.xml
Normal file
157
deploy/articles/tag/article/feed.xml
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
|
||||||
|
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||||
|
<id>http://localhost:3000/articles/tag/article/feed.xml</id>
|
||||||
|
<title>mhoush</title>
|
||||||
|
<author>
|
||||||
|
<name>Michael Housh</name>
|
||||||
|
</author>
|
||||||
|
<link rel="self" href="http://localhost:3000"></link>
|
||||||
|
<updated>2025-02-19T21:55:31Z</updated>
|
||||||
|
<entry>
|
||||||
|
<id>http://localhost:3000/articles/2023/the-struggle/</id>
|
||||||
|
<title>The Struggle</title>
|
||||||
|
<updated>2025-02-19T20:53:34Z</updated>
|
||||||
|
<content type="html"><p>This is a get stuff of my chest article. Probably going to be a mixture of ranting and whining. If<br />
|
||||||
|
that is not your cup of tea then feel free to skip this article.</p>
|
||||||
|
<h2>The struggle</h2>
|
||||||
|
<p>It has been one of those “when it rains, it pours” type of weeks. As write this, I feel like a baby<br />
|
||||||
|
/ complainer, which is not my intention, but here it goes.</p>
|
||||||
|
<p>My aunt had a stroke and is likely not going to make it through the week. My aunt has always lived<br />
|
||||||
|
in Florida during my life / memory, but has always come to visit. She is my mom’s oldest sister (9<br />
|
||||||
|
years apart), so she helped raise my mother growing up. They’ve always had a close relationship and<br />
|
||||||
|
are like two peas in a pod. They would always visit us, especially while my grand-parents were still<br />
|
||||||
|
alive. She is currently not really awake or expected to make it. She does not eat / drink and<br />
|
||||||
|
they’ve basically just been making her comfortable.</p>
|
||||||
|
<p>One of my employees broke his neck over the weekend. I don’t have a ton of details on this subject,<br />
|
||||||
|
but he had surgery to fuse some discs back together and should eventually be ok, however it will be<br />
|
||||||
|
a long recovery time.</p>
|
||||||
|
<p>A few weeks ago, I commited one of the deadly sins of running a blower door test without checking /<br />
|
||||||
|
asking about the fireplaces, which caused lord knows how much damage from the soot that was spread<br />
|
||||||
|
throughout the living room(s).</p>
|
||||||
|
<p>An online friend lost her mother.</p>
|
||||||
|
<p>All of these things have just got me emotional.</p>
|
||||||
|
<h2>My secrets</h2>
|
||||||
|
<p>I am an emotional person, sometimes to my detriment. I’m prone to fits of anger and depression. I<br />
|
||||||
|
spent many years masking things through alcohol abuse and many other idiotic tendencies. I still<br />
|
||||||
|
drink on occasion, but not as I once did.</p>
|
||||||
|
<p>I often put my faith in folks, even if I haven’t met them in person, this can often lead to being<br />
|
||||||
|
let down. I guess I struggle sometimes with the reality of online relationships. I think that people<br />
|
||||||
|
are genuine, because I’m that way (how I act online is the same as I act in person for the most<br />
|
||||||
|
part). I will happily show / share the good and the bad, in hopes that someone may learn. This is<br />
|
||||||
|
not at all something to be ashamed of, or anything that I’d like to change, however it does on<br />
|
||||||
|
occasion lead me into turmoil when I find out some true identity / personality of someone.</p>
|
||||||
|
<p>I hold grudges, like forever grudges. It is very hard for me to get over somethings, even if I want<br />
|
||||||
|
to. I can sometimes put things out of my mind, but when I’m spinning, they will resurface. I want to<br />
|
||||||
|
forgive people, but it is just not the way it works for me often times. It takes a lot to get me<br />
|
||||||
|
beyond my breaking point, but once someone has gotten me there, there is likely no turning back for<br />
|
||||||
|
that person. Luckily, I can count on one hand the number of folks that I’ve had to cut out of my<br />
|
||||||
|
life for these reasons. I’d love to say that I’m a bigger / better person, that I forgive them, but<br />
|
||||||
|
truthfully I do not.</p>
|
||||||
|
<p>My emotions sometimes make me say things publicly that I should keep to myself. I don’t have a lot<br />
|
||||||
|
of regret around these things, because I generally mean what I say, and also feel we are entitled to<br />
|
||||||
|
opinions as well as entitled to change those opinions as often as we see fit. Although I don’t<br />
|
||||||
|
regret them per-se, it does make me wonder what type of impression it leaves (something for future<br />
|
||||||
|
pondering, perhaps).</p>
|
||||||
|
<p>I’m one of those that says “I don’t care what they think about me”, when I really do care what<br />
|
||||||
|
people think about me. This often leads to fear and anxiety, especially in social settings. I’m not<br />
|
||||||
|
the greatest at conversation, I’m better at writing or some interaction that gives me a bit of time<br />
|
||||||
|
to think before responding. Therefore, I’m quick to make a joke or something rather than having<br />
|
||||||
|
thoughtful / genuine responses.</p>
|
||||||
|
<h2>Community</h2>
|
||||||
|
<p>All of these things have just got me thinking about community. Community is an aspect that seems<br />
|
||||||
|
distant nowadays, even though we have more opportunity than ever. We call ourselves part of<br />
|
||||||
|
communities, especially online, but I’m not convinced that it is really community (or at least not<br />
|
||||||
|
most of the time, not saying it can’t be / in absolute terms).</p>
|
||||||
|
<p>I have met a lot of folks online that I consider true friends. Friends that I would do anything for<br />
|
||||||
|
and feel they would do anything for me, just like my real life friends who have stuck with me for<br />
|
||||||
|
many years. These are people that challenge me and how I think on a regular basis. They do their<br />
|
||||||
|
best to lift me up when I’m down.</p>
|
||||||
|
<p>It’s easy to hide when so much of our interactions are not really in person, to feel like the<br />
|
||||||
|
relationships we do have are not genuine, but that’s awfully cynical. I prefer to give people the<br />
|
||||||
|
benefit / trust they deserve until, at least until they don’t then see my part about holding grudges<br />
|
||||||
|
;)</p>
|
||||||
|
<p>Do you ever feel the same? Instead of being cynical and down, today, I’m trying to be positive. I’m<br />
|
||||||
|
trying to share a little bit of what I feel community should be. Although, I’ve never met HVAChicks<br />
|
||||||
|
Jennifer in real life, I read today about her mom and decided to take an hour or so to put together<br />
|
||||||
|
a website for the <a href="https://hvachicks.com">HVAChicks Community</a>, hoping it would bring a moment of<br />
|
||||||
|
happiness to her day. While I’ve deployed several websites in the past, this one for some reason was<br />
|
||||||
|
a total PITA, but I got through it. I could feel how grateful she was when I shared it with her (and<br />
|
||||||
|
it’s basic AF), but that truly made me feel useful / great after being down in the dumps for a bit.</p>
|
||||||
|
<h2>Conclusion</h2>
|
||||||
|
<p>I’ve probably rambled enough and am losing direction here, so I will end with a few things.</p>
|
||||||
|
<ol>
|
||||||
|
<li>Build the community around you that you want / deserve.</li>
|
||||||
|
<li>Don’t be so quick to pass judgment.</li>
|
||||||
|
<li>Spend time with your loved ones, while you can.</li>
|
||||||
|
<li>Tell someone you love them.</li>
|
||||||
|
</ol>
|
||||||
|
<p>Finally, I’d like to shout out some people that I’m grateful for. This is non-exhaustive list, if I<br />
|
||||||
|
left you off, I’m sorry and please do not take it personally.</p>
|
||||||
|
<ol>
|
||||||
|
<li>Bryan Orr
|
||||||
|
<ul>
|
||||||
|
<li>Bryan has cultivated an awesome group / community that I’m proud to be a part of. His time and<br />
|
||||||
|
commitment to the HVAC industry is something that I hope he himself is proud of. Without Bryan,<br />
|
||||||
|
mostly all the following names would not even be in my vocabulary.</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Ty Branaman (forget exactly how to spell his last name).
|
||||||
|
<ul>
|
||||||
|
<li>Ty has such a great personality during his videos / training and I’m sure it’s a struggle to be<br />
|
||||||
|
positive all the time, however it brings me hope and joy everytime!</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Dustin (mother f’n) Cole
|
||||||
|
<ul>
|
||||||
|
<li>Dustin is like a brother that I never had, he’s a true master of his craft and I know that I<br />
|
||||||
|
can rely on him anytime I need it!</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Genry Garcia
|
||||||
|
<ul>
|
||||||
|
<li>The cuban crusader who has taught me so much about home performance, and especially ZPD (baby,<br />
|
||||||
|
baby)!</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Chris Hughes
|
||||||
|
<ul>
|
||||||
|
<li>It’s hard to put into words here, but I know that Chris is there to talk when I need it and<br />
|
||||||
|
he’s a great motivator because of his action items :)</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Eric Kaiser
|
||||||
|
<ul>
|
||||||
|
<li>I think genuine when I think of Eric, I hear his voice in my head when I write reports because<br />
|
||||||
|
of guidance he has given in the past. He truly wants to help teach people.</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Michael Cianfracco (??)
|
||||||
|
<ul>
|
||||||
|
<li>Man does he make me laugh and we share a passion for the 4-Roses.</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>HVAChicks Jennifer (I’ll butcher her last name from memory)
|
||||||
|
<ul>
|
||||||
|
<li>Jennifer is inspiring with her goals and everything she does to help anyone in the industry. I<br />
|
||||||
|
can’t wait to meet her in person one day soon!</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>HVAC Overtime Crew
|
||||||
|
<ul>
|
||||||
|
<li>I’m lumping these guys together because I truly enjoy when I’m able to make their live stream<br />
|
||||||
|
on Friday’s. And I interact with A-Team a lot and really appreciate him / them!</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Alicia Hollon
|
||||||
|
<ul>
|
||||||
|
<li>Alicia is so awesome to me, I mean she just made my favorite pancakes and sausage for dinner,<br />
|
||||||
|
love you babe!</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
<p>Lastly, I have to shout out to my mom. I know she’s going through a rough time with my aunt<br />
|
||||||
|
currently. My mother is the kindest gentlest soul that I’ve ever met. I look up to all 5’ of her!</p>
|
||||||
|
<p>At any rate, thanks for sticking it out to the end through my ramblings. Be kind to someone today<br />
|
||||||
|
and tomorrow!</p></content>
|
||||||
|
</entry>
|
||||||
|
</feed>
|
||||||
78
deploy/articles/tag/article/index.html
Normal file
78
deploy/articles/tag/article/index.html
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en-US">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta content="#0e1112" media="(prefers-color-scheme: dark)" name="theme-color"/>
|
||||||
|
<meta content="#566B78" media="(prefers-color-scheme: light)" name="theme-color"/>
|
||||||
|
<meta content="Michael Housh" name="author"/>
|
||||||
|
<meta content="Mhoush" name="apple-mobile-web-app-title"/>
|
||||||
|
<meta content="initial-scale=1.0, width=device-width" name="viewport"/>
|
||||||
|
<meta content="telephone=no" name="format-detection"/>
|
||||||
|
<meta content="True" name="HandheldFriendly"/>
|
||||||
|
<meta content="320" name="MobileOptimized"/>
|
||||||
|
<meta content="Mhoush" name="og:site_name"/>
|
||||||
|
<meta content="hvac, developer, swift, home-performance, design" name="keywords"/>
|
||||||
|
<title>
|
||||||
|
mhoush: Articles in article
|
||||||
|
</title>
|
||||||
|
<link href="/static/favicon.ico" rel="shortcut icon"/>
|
||||||
|
<link href="/static/output.css" rel="stylesheet"/>
|
||||||
|
<link href="/static/style.css" rel="stylesheet"/>
|
||||||
|
<link href="/articles/feed.xml" rel="alternate" title="mhoush" type="application/rss+xml"/>
|
||||||
|
<link href="/articles/tag/article/feed.xml" rel="alternate" title="mhoush: articles with tag article" type="application/rss+xml"/>
|
||||||
|
</head>
|
||||||
|
<body class="bg-page text-white pb-5 font-avenir articles">
|
||||||
|
<header class="bg-nav text-gray py-4 text-base/6 lg:fixed w-full lg:h-[62px]">
|
||||||
|
<nav class="container flex gap-x-5 lg:gap-x-y items-center">
|
||||||
|
<ul class="flex flex-wrap gap-x-2 lg:gap-x-5">
|
||||||
|
<li>
|
||||||
|
<a class href="/">Home</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="active" href="/articles/">Articles</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class href="/about/">About</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<div class="container pt-12 lg:pt-28">
|
||||||
|
<section class="mb-10">
|
||||||
|
<h1 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2023/the-struggle/">The Struggle</a>
|
||||||
|
</h1>
|
||||||
|
<div class="text-gray gray-links text-sm">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">October 18, 2023</span>1520 words, posted in <a href="/articles/tag/article/">article</a> and <a href="/articles/tag/general/">general</a>
|
||||||
|
</div>
|
||||||
|
<p class="mt-4">
|
||||||
|
<a href="/articles/2023/the-struggle/">This is a get stuff of my chest article. Probably going to be a mixture of ranting and whining. If
|
||||||
|
that is not your cup of tea then feel free to skip this article.
|
||||||
|
The struggle
|
||||||
|
It has been one of those “when it rains, it pours” type of weeks. As...</a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<div class="site-footer container text-gray gray-links border-t border-light text-center pt-6 mt-8 text-sm">
|
||||||
|
<p>
|
||||||
|
Copyright © Michael Housh 2023-2025.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Built in Swift using
|
||||||
|
<a href="https://github.com/loopwerk/Saga" rel="nofollow" target="_blank">Saga</a>
|
||||||
|
(<a href="https://github.com/m-housh/mhoush.com" rel="nofollow" target="_blank">source</a>).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="http://localhost:3000/articles/tag/article/feed.xml" rel="nofollow" target="_blank">RSS</a>
|
||||||
|
|
|
||||||
|
<a href="https://github.com/m-housh" rel="nofollow" target="_blank">Github</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.youtube.com/channel/UCb58SeURd5bObfTiL0KoliA" rel="nofollow" target="_blank">Youtube</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.facebook.com/michael.housh" rel="nofollow" target="_blank">Facebook</a>
|
||||||
|
|
|
||||||
|
<a href="mailto:michael@mhoush.com" rel="nofollow">Email</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
86
deploy/articles/tag/chiller/feed.xml
Normal file
86
deploy/articles/tag/chiller/feed.xml
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
|
||||||
|
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||||
|
<id>http://localhost:3000/articles/tag/chiller/feed.xml</id>
|
||||||
|
<title>mhoush</title>
|
||||||
|
<author>
|
||||||
|
<name>Michael Housh</name>
|
||||||
|
</author>
|
||||||
|
<link rel="self" href="http://localhost:3000"></link>
|
||||||
|
<updated>2025-02-19T21:55:31Z</updated>
|
||||||
|
<entry>
|
||||||
|
<id>http://localhost:3000/articles/2023/heat-recovery-chiller/</id>
|
||||||
|
<title>Heat Recovery Chiller</title>
|
||||||
|
<updated>2025-02-19T21:08:37Z</updated>
|
||||||
|
<content type="html"><p>This is an article that I wrote back in 2020, but I don’t believe that I published it anywhere, so<br />
|
||||||
|
I’m doing it now. I did discuss this on<br />
|
||||||
|
<a href="https://hvacrschool.com/podcasts/is-the-future-of-air-conditioning-self-contained-propane-chillers/">this episode of the HVAC School Podcast.</a></p>
|
||||||
|
<h2>Heat Recovery Chillers</h2>
|
||||||
|
<p>I have always had a love and passion for hydronic systems, perhaps it’s because they are not that<br />
|
||||||
|
common in most areas. The designs tend to be elegant and the flexibility is unparalleled by most<br />
|
||||||
|
equipment choices currently available in the U.S. I’m going to try to not get too far into the weeds<br />
|
||||||
|
in this article, but offer an overview of what I feel would be my dream system.</p>
|
||||||
|
<h2>The Source</h2>
|
||||||
|
<p>A heat recovery chiller will do simultaneous heating and cooling, as opposed to a traditional<br />
|
||||||
|
heat-pump or reverse cycle chiller that can only operate in one mode at a time. This system would<br />
|
||||||
|
have a second refrigerant to water heat exchanger and utilize the air-source when we don’t need to<br />
|
||||||
|
bank / store heat, or are running in heat only mode. There are several benefits to this style<br />
|
||||||
|
system, the main being that while operating simultaneous heating / cooling mode the COP of the<br />
|
||||||
|
system doubles. For example, the <a href="https://multiaqua.com/mhrc2/">Multi-Aqua MHRC2</a> shows a COP of<br />
|
||||||
|
about 8, which is approximately equivalent to 30 EER or 34 SEER. This gives us geothermal level<br />
|
||||||
|
performance without the need of a field.</p>
|
||||||
|
<h2>Indoor Portion</h2>
|
||||||
|
<p>The indoor portion of the system, we would utilize buffer tanks as thermal storage for the chiller.<br />
|
||||||
|
The buffer tanks give us several benefits, including longer run times for the chiller, load<br />
|
||||||
|
matching, and the ability to size for larger load (heating or cooling) without some of the problems<br />
|
||||||
|
that occur when over-sizing a traditional system. The buffer tanks also allow sizing more<br />
|
||||||
|
aggressively by having storage during peak load conditions.</p>
|
||||||
|
<p><img src="/articles/images/2023-10-27-buffers2.png" alt="buffer" /></p>
|
||||||
|
<p>This shows a cooling buffer tank as well as a heating buffer tank. The horizontal pumps are what<br />
|
||||||
|
circulate water through the chiller, while the vertical pumps are what distribute the water to the<br />
|
||||||
|
load / emitters. This configuration allows for water to be used for the loads first and extra<br />
|
||||||
|
capacity to go into the buffer tanks. The buffer tanks also offer hydraulic separation for the pumps<br />
|
||||||
|
(meaning that they won’t interfere with each other if / when there are different flow rates).<br />
|
||||||
|
Another advantage of the buffer tanks is that you can connect multiple heating or cooling sources in<br />
|
||||||
|
parallel to the system. This is shown by the extra tees in the hot buffer tank where we could<br />
|
||||||
|
connect something such as solar water collectors, pellet or wood boiler, or a conventional boiler.<br />
|
||||||
|
You’ll also notice on the right side of the hot buffer tank, that I am showing a brazed plate heat<br />
|
||||||
|
exchanger that would be used to supply domestic hot water.</p>
|
||||||
|
<h2>Distribution System</h2>
|
||||||
|
<p>This could be a number of things, from radiant panels, in-floor, high-output baseboard radiators,<br />
|
||||||
|
however I’m going to model it as a 4-pipe hydronic air handler.</p>
|
||||||
|
<p><img src="/articles/images/2023-10-27-ah.png" alt="ah" /></p>
|
||||||
|
<p>The hydronic air handler is able to provide cooling, heating, and re-heat dehumidification, all in<br />
|
||||||
|
one package. With a hydronic system, it would be very easy to load match by controlling the fan<br />
|
||||||
|
speed and utilizing a Delta-T pump or outdoor reset controls. These air handlers are available from<br />
|
||||||
|
several manufacturers and come in different styles from traditional (as shown), small duct high<br />
|
||||||
|
velocity systems, and even ductless styles.</p>
|
||||||
|
<h2>Disadvantages</h2>
|
||||||
|
<ol>
|
||||||
|
<li>Not highly available in the U.S.</li>
|
||||||
|
<li>When the chiller is down nothing works (not much different than traditional)</li>
|
||||||
|
<li>Lack of understanding / technicians afraid to work on this style system.</li>
|
||||||
|
<li>Potentially higher upfront costs.</li>
|
||||||
|
<li>Lack of design or planning could cause unhappy clients (same with traditional)</li>
|
||||||
|
<li>Distribution systems need to be designed around low water temperatures (not a drop in replacement<br />
|
||||||
|
for traditional boiler systems)</li>
|
||||||
|
</ol>
|
||||||
|
<h2>Advantages</h2>
|
||||||
|
<ol>
|
||||||
|
<li>Central plant for heating, cooling, and DHW (also a disadvantage)</li>
|
||||||
|
<li>Flexible distribution options / methods.</li>
|
||||||
|
<li>Self contained refrigerant circuit</li>
|
||||||
|
<li>Ability to produce / store thermal energy during off peak electrical hours</li>
|
||||||
|
<li>Ability to move BTU’s more efficiently through water than air</li>
|
||||||
|
<li>Long life for distribution system (50-100+ years)</li>
|
||||||
|
<li>Easier transition to natural / flammable refrigerants</li>
|
||||||
|
</ol>
|
||||||
|
<h2>Conclusion</h2>
|
||||||
|
<p>In conclusion, there are many advantages to this style system, as well as disadvantages. One of the<br />
|
||||||
|
main points is to think of the system in 3 distinct components, the source(s), thermal storage, and<br />
|
||||||
|
distribution. As mentioned, this only one concept, but in reality, there are many ways to accomplish<br />
|
||||||
|
this, which is one of it’s advantages. For example, perhaps in certain scenarios it makes sense to<br />
|
||||||
|
dump excess heat into a pool, create ice storage during off peak hours, cascade into another water<br />
|
||||||
|
-&gt; water heat pump for higher temperature distribution, incorporate solar collectors, and so on.</p>
|
||||||
|
<p>Thank you for reading all the way to the end!</p></content>
|
||||||
|
</entry>
|
||||||
|
</feed>
|
||||||
79
deploy/articles/tag/chiller/index.html
Normal file
79
deploy/articles/tag/chiller/index.html
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en-US">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta content="#0e1112" media="(prefers-color-scheme: dark)" name="theme-color"/>
|
||||||
|
<meta content="#566B78" media="(prefers-color-scheme: light)" name="theme-color"/>
|
||||||
|
<meta content="Michael Housh" name="author"/>
|
||||||
|
<meta content="Mhoush" name="apple-mobile-web-app-title"/>
|
||||||
|
<meta content="initial-scale=1.0, width=device-width" name="viewport"/>
|
||||||
|
<meta content="telephone=no" name="format-detection"/>
|
||||||
|
<meta content="True" name="HandheldFriendly"/>
|
||||||
|
<meta content="320" name="MobileOptimized"/>
|
||||||
|
<meta content="Mhoush" name="og:site_name"/>
|
||||||
|
<meta content="hvac, developer, swift, home-performance, design" name="keywords"/>
|
||||||
|
<title>
|
||||||
|
mhoush: Articles in chiller
|
||||||
|
</title>
|
||||||
|
<link href="/static/favicon.ico" rel="shortcut icon"/>
|
||||||
|
<link href="/static/output.css" rel="stylesheet"/>
|
||||||
|
<link href="/static/style.css" rel="stylesheet"/>
|
||||||
|
<link href="/articles/feed.xml" rel="alternate" title="mhoush" type="application/rss+xml"/>
|
||||||
|
<link href="/articles/tag/chiller/feed.xml" rel="alternate" title="mhoush: articles with tag chiller" type="application/rss+xml"/>
|
||||||
|
</head>
|
||||||
|
<body class="bg-page text-white pb-5 font-avenir articles">
|
||||||
|
<header class="bg-nav text-gray py-4 text-base/6 lg:fixed w-full lg:h-[62px]">
|
||||||
|
<nav class="container flex gap-x-5 lg:gap-x-y items-center">
|
||||||
|
<ul class="flex flex-wrap gap-x-2 lg:gap-x-5">
|
||||||
|
<li>
|
||||||
|
<a class href="/">Home</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="active" href="/articles/">Articles</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class href="/about/">About</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<div class="container pt-12 lg:pt-28">
|
||||||
|
<section class="mb-10">
|
||||||
|
<h1 class="text-2xl font-bold mb-2">
|
||||||
|
<a class="[&:hover]:border-b border-orange" href="/articles/2023/heat-recovery-chiller/">Heat Recovery Chiller</a>
|
||||||
|
</h1>
|
||||||
|
<div class="text-gray gray-links text-sm">
|
||||||
|
<span class="border-r border-gray pr-2 mr-2">October 27, 2023</span>811 words, posted in <a href="/articles/tag/hvac/">HVAC</a>, <a href="/articles/tag/chiller/">chiller</a> and <a href="/articles/tag/hydronics/">hydronics</a>
|
||||||
|
</div>
|
||||||
|
<p class="mt-4">
|
||||||
|
<a href="/articles/2023/heat-recovery-chiller/">This is an article that I wrote back in 2020, but I don’t believe that I published it anywhere, so
|
||||||
|
I’m doing it now. I did discuss this on
|
||||||
|
this episode of the HVAC School Podcast.
|
||||||
|
Heat Recovery Chillers
|
||||||
|
I have always had a love and passion for...</a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<div class="site-footer container text-gray gray-links border-t border-light text-center pt-6 mt-8 text-sm">
|
||||||
|
<p>
|
||||||
|
Copyright © Michael Housh 2023-2025.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Built in Swift using
|
||||||
|
<a href="https://github.com/loopwerk/Saga" rel="nofollow" target="_blank">Saga</a>
|
||||||
|
(<a href="https://github.com/m-housh/mhoush.com" rel="nofollow" target="_blank">source</a>).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="http://localhost:3000/articles/tag/chiller/feed.xml" rel="nofollow" target="_blank">RSS</a>
|
||||||
|
|
|
||||||
|
<a href="https://github.com/m-housh" rel="nofollow" target="_blank">Github</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.youtube.com/channel/UCb58SeURd5bObfTiL0KoliA" rel="nofollow" target="_blank">Youtube</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.facebook.com/michael.housh" rel="nofollow" target="_blank">Facebook</a>
|
||||||
|
|
|
||||||
|
<a href="mailto:michael@mhoush.com" rel="nofollow">Email</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
58
deploy/articles/tag/formulas/feed.xml
Normal file
58
deploy/articles/tag/formulas/feed.xml
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
|
||||||
|
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||||
|
<id>http://localhost:3000/articles/tag/formulas/feed.xml</id>
|
||||||
|
<title>mhoush</title>
|
||||||
|
<author>
|
||||||
|
<name>Michael Housh</name>
|
||||||
|
</author>
|
||||||
|
<link rel="self" href="http://localhost:3000"></link>
|
||||||
|
<updated>2025-02-19T21:55:31Z</updated>
|
||||||
|
<entry>
|
||||||
|
<id>http://localhost:3000/articles/2023/calculate-seer-degradation-by-age/</id>
|
||||||
|
<title>Calculate SEER Degradation by Age</title>
|
||||||
|
<updated>2025-02-19T21:55:30Z</updated>
|
||||||
|
<content type="html"><p>This is a quick tech-tip to learn how to calculate the degradation of SEER based<br />
|
||||||
|
on age.</p>
|
||||||
|
<p>The degradation of SEER is due to fouling of the evaporator coil with dirt and<br />
|
||||||
|
refrigerant charge losses. It should be noted that this is not true for all<br />
|
||||||
|
applications, but is used as an estimation based on research done by the <code>DOE</code><br />
|
||||||
|
of the average degradation based on systems tested.</p>
|
||||||
|
<h2>Formula</h2>
|
||||||
|
<p>This is the formula used to calculate the SEER based on age of the evaporator<br />
|
||||||
|
coil / air handler.</p>
|
||||||
|
<p>$$ SEER_d = SEER_n \times (1 - M)^{age} $$</p>
|
||||||
|
<p>| Where | |<br />
|
||||||
|
| –––– | —————————————— | — |<br />
|
||||||
|
| $SEER_d$ | Degradated SEER rating |<br />
|
||||||
|
| $SEER_n$ | Nominal SEER rating when equipment was new | |<br />
|
||||||
|
| M | Maintenance factor, 0.01-0.03 |<br />
|
||||||
|
| age | The age of the equipment, in years |</p>
|
||||||
|
<p>The maintenance factor of 0.01 is for expertly maintained equipment and 0.03 is<br />
|
||||||
|
for unmaintained. The maintenance factor in essence is based on 1%-3%<br />
|
||||||
|
degradation per year, however there are some<br />
|
||||||
|
<a href="https://publications.energyresearch.ucf.edu/wp-content/uploads/2018/09/FSEC-PF-474-18.pdf">studies</a><br />
|
||||||
|
that show that this can actually be as high as 5% or above depending on climate.<br />
|
||||||
|
We could use up to 0.05 as the maintenance factor, just to see what the “range”<br />
|
||||||
|
of degradation would be.</p>
|
||||||
|
<p>Interestingly, the study linked also shows that the degradation is higher the<br />
|
||||||
|
higher the tonnage of the equipment. It also shows that the degradation is lower<br />
|
||||||
|
per year the higher the nominal SEER rating of the system (which is corelated to<br />
|
||||||
|
using TXV’s and lower airflow rates because of the equipment having multiple<br />
|
||||||
|
stages).</p>
|
||||||
|
<h2>Example</h2>
|
||||||
|
<p>Let’s consider that we have a 13 SEER piece of equipment that was matched when<br />
|
||||||
|
installed and the system is 15 years old.</p>
|
||||||
|
<p>Plugging those numbers into our formula.</p>
|
||||||
|
<hr />
|
||||||
|
<h4>Lowest Range (1% degradation / year)</h4>
|
||||||
|
<p>$$ SEER_d = 13 \times (1 - 0.01)^{15} = 11.2 $$</p>
|
||||||
|
<hr />
|
||||||
|
<h4>Highest Rage (5% degradation / year)</h4>
|
||||||
|
<p>$$ SEER_d = 13 \times (1 - 0.05)^{15} = 6 $$</p>
|
||||||
|
<hr />
|
||||||
|
<p>An expertly maintained system may not have degraded that much, with an 11.2 SEER<br />
|
||||||
|
vs. a poorly maintained / dirty system that also suffers from refrigerant charge<br />
|
||||||
|
losses can be as low as 6 SEER.</p>
|
||||||
|
<p>Thanks for learning how to estimate SEER degradation based on equipment age!</p></content>
|
||||||
|
</entry>
|
||||||
|
</feed>
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user