diff --git a/.gitignore b/.gitignore index 878022feb08..9926d52aafe 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,9 @@ source/_data/blueprint_exchange_data.json source/_data/version_data.json source/_data/alerts_data.json source/_data/language_scores.json +source/_data/codeowners.json source/_stash +source/stylesheets/homeassistant/pages/community/index.css source/stylesheets/screen.css source/.jekyll-cache/ vendor diff --git a/Rakefile b/Rakefile index 0948a8b0655..722d7e1eed8 100644 --- a/Rakefile +++ b/Rakefile @@ -32,6 +32,8 @@ task :generate do abort("Generating version data failed") unless success success = system "rake language_scores_data" abort("Generating language scores data failed") unless success + success = system "rake codeowners_data" + abort("Extracting codeowners") unless success success = system "jekyll build" abort("Generating site failed") unless success if ENV["CONTEXT"] != 'production' @@ -71,6 +73,7 @@ task :preview, :listen do |t, args| system "rake analytics_data" system "rake version_data" system "rake language_scores_data" + system "rake codeowners_data" system "rake alerts_data" jekyllPid = Process.spawn({"OCTOPRESS_ENV"=>"preview"}, "jekyll build -t --watch --incremental") compassPid = Process.spawn("compass watch") @@ -128,3 +131,25 @@ task :language_scores_data do file.write(JSON.generate(remote_data)) end end + +desc "Extract CODEOWNERS and output to _data/codeowners.json" +task :codeowners_data do + codeowners = [] + File.readlines("CODEOWNERS").each do |line| + next if line.start_with?("#") || line.strip.empty? + parts = line.split + next if parts.length < 2 + owners = parts[1..-1] + owners.each do |owner| + owner = owner.delete_prefix('@') + next if owner.include?('/') + codeowners << owner unless codeowners.include?(owner) + end + end + + codeowners.sort! + + File.open("#{source_dir}/_data/codeowners.json", "w") do |file| + file.write(JSON.generate(codeowners)) + end +end \ No newline at end of file diff --git a/sass/homeassistant/pages/community/_base.scss b/sass/homeassistant/pages/community/_base.scss new file mode 100644 index 00000000000..d76c155f5a7 --- /dev/null +++ b/sass/homeassistant/pages/community/_base.scss @@ -0,0 +1,132 @@ +.container { + display: flex; + margin: 0 auto; + max-width: calc(var(--container-max-width) + (var(--container-gutters) * 2)); + padding: 12px calc(var(--container-gutters) / 2); + width: 100%; + height: 100%; + + @include bp(desktop) { + padding: 12px var(--container-gutters); + } + + &-full { + margin: 0 auto; + padding: 0 calc(var(--container-gutters) / 2); + max-width: calc(var(--container-full-max-width) + (var(--container-gutters) * 2)); + width: 100%; + + @include bp(desktop) { + padding: 0 var(--container-gutters); + } + } +} + +footer{ + isolation: isolate; + position: relative; + &:before{ + content: ''; + position: absolute; + height: 500px; + left: 0; + right: 0; + bottom: 100%; + background: linear-gradient(180deg, #F5F6FA 0%, #FFFFFF 100%); + } +} + +html{ + scroll-padding-top: 92px; +} + +#landingpage { + background-color: #F5F6FA; + color: #002332; + + height: auto; + + .page-content { + overflow-x: clip; + padding-top: 68px; + } + + .content { + max-width: unset; + margin: 0; + } + + img { + box-shadow: unset; + vertical-align: unset; + border: unset; + } + + .spacer { + display: none; + } +} + +section { + padding: var(--section-spacing-y) 0; + position: relative; + z-index: 1; +} + +main#page-community { + h1, + .h1 { + @include h1; + } + + h2, + .h2 { + @include h2; + } + + h3, + .h3 { + @include h3; + text-transform: unset; + letter-spacing: unset; + } + + h4, + .h4 { + @include h4; + } + + h5, + .h5 { + @include h5; + } + + h6, + .h6 { + @include h6; + } + + .small { + @include small; + } + + .big { + @include big; + } + + p { + color: var(--typography-paragraph-color); + font-size: var(--typography-paragraph-font-size); + font-weight: var(--typography-paragraph-font-weight); + line-height: var(--typography-paragraph-line-height); + margin: 0; + + &:last-child { + margin-bottom: 0; + } + } + + figure { + margin: 0; + } +} \ No newline at end of file diff --git a/sass/homeassistant/pages/community/_buttons.scss b/sass/homeassistant/pages/community/_buttons.scss new file mode 100644 index 00000000000..9dfa1bdb225 --- /dev/null +++ b/sass/homeassistant/pages/community/_buttons.scss @@ -0,0 +1,107 @@ + .button { + // Reset - remove after global button refactor + border: unset; + color: initial; + height: unset; + line-height: initial; + margin: unset; + overflow: hidden; + + align-items: center; + background-color: #99DFFC; + border-radius: 40px; + display: inline-flex; + font-size: 10px; + font-weight: 600; + padding: 10px 24px; + transition: color 0.2s ease, background-color 0.2s ease; + + @include bp(desktop) { + font-size: 14px; + } + + &:hover { + box-shadow: unset; + background-color: var(--color-primary); + color: #ffffff; + } + + &:before { + content: unset; + } + + &:has(.icon) { + gap: 4px; + padding: 4px 14px 4px 4px; + + @include bp(desktop) { + gap: 10px; + padding: 8px 24px 8px 8px; + } + } + + &.secondary { + background-color: var(--color-secondary); + + &:hover { + background-color: var(--color-primary); + color: #ffffff; + } + } + + &.hollow-dark { + background-color: unset; + box-shadow: inset 0 0 0 1px #fff; + color: #ffffff; + + + &:hover { + background-color: #ffffff; + color: #002332; + + + } + } + } + + .buttons { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 12px; + + // If DSAP is enabled + &[data-dsap] { + + // Only apply if scrolling down into view + &:not([data-dsap-is="in"]):not([data-dsap-is="above"]) { + // Only if scrolling down into the element + + .button { + transition-duration: 0s; + transition-delay: 0s; + opacity: 0; + transform: translateY(50px); + scale: 0.85; + } + } + + .button { + transform: translateY(0); + + @for $i from 1 through 10 { + &:nth-child(#{$i}) { + transition-property: transform, opacity, scale; + transition-duration: .5s; + transition-delay: #{0.1 + ($i * 0.05)}s; + transition-timing-function: cubic-bezier(0.2, 1, 0.5, 1); + + } + } + } + } + + @include bp(desktop) { + gap: 24px; + } + } \ No newline at end of file diff --git a/sass/homeassistant/pages/community/_event-card.scss b/sass/homeassistant/pages/community/_event-card.scss new file mode 100644 index 00000000000..09eb6987cf1 --- /dev/null +++ b/sass/homeassistant/pages/community/_event-card.scss @@ -0,0 +1,21 @@ +.event-card{ + background-color: rgba(255,255,255,0.4); + padding: 12px; + border-radius: 12px; + border: 1px solid #ffffff; + + .button{ + margin-top: 20px; + } + + .event-title{ + @include h4; + } + + .event-meta{ + @include p; + color: #4F606E; + margin-top: 6px; + font-size: 12px; + } +} \ No newline at end of file diff --git a/sass/homeassistant/pages/community/_icon.scss b/sass/homeassistant/pages/community/_icon.scss new file mode 100644 index 00000000000..582a2b1343b --- /dev/null +++ b/sass/homeassistant/pages/community/_icon.scss @@ -0,0 +1,25 @@ +.icon{ + aspect-ratio: 1/1; + background-color: #ffffff; + border-radius: 50%; + color: #002332; + height: 100%; + padding: 4px; + display: grid; + place-items: center; + height: 24px; + width: 24px; + + &:has(use[href="#facebook"]){ + padding: 0; + svg{ + height: 100%; + width: 100%; + } + } + + svg{ + width: 100%; + height: 100%; + } +} \ No newline at end of file diff --git a/sass/homeassistant/pages/community/_mixins.scss b/sass/homeassistant/pages/community/_mixins.scss new file mode 100644 index 00000000000..cf71fb96520 --- /dev/null +++ b/sass/homeassistant/pages/community/_mixins.scss @@ -0,0 +1,84 @@ +@mixin bp($breakpoint) { + @if $breakpoint ==large-mobile { + @media (min-width: 500px) { + @content; + } + } + + @else if $breakpoint ==tablet { + @media (min-width: 768px) { + @content; + } + } + + @else if $breakpoint ==desktop { + @media (min-width: 1024px) { + @content; + } + } + + @else if $breakpoint ==large-desktop { + @media (min-width: 1280px) { + @content; + } + } + + // else if the breakpoint is a pixel value, use it as is + @else { + @media (min-width: $breakpoint) { + @content; + } + } +} + +@mixin h1 { + font-size: var(--typography-h1-font-size); + font-weight: var(--typography-h1-font-weight); + line-height: var(--typography-h1-line-height); + letter-spacing: -1px; +} +@mixin h2 { + font-size: var(--typography-h2-font-size); + font-weight: var(--typography-h2-font-weight); + line-height: var(--typography-h2-line-height); + letter-spacing: -1px; +} +@mixin h3 { + font-size: var(--typography-h3-font-size); + font-weight: var(--typography-h3-font-weight); + line-height: var(--typography-h3-line-height); +} +@mixin h4 { + font-size: var(--typography-h4-font-size); + font-weight: var(--typography-h4-font-weight); + line-height: var(--typography-h4-line-height); +} +@mixin h5 { + font-size: var(--typography-h5-font-size); + font-weight: var(--typography-h5-font-weight); + line-height: var(--typography-h5-line-height); +} +@mixin h6 { + font-size: var(--typography-h6-font-size); + font-weight: var(--typography-h6-font-weight); + line-height: var(--typography-h6-line-height); +} + +@mixin p { + font-size: var(--typography-paragraph-font-size); + font-weight: var(--typography-paragraph-font-weight); + line-height: var(--typography-paragraph-line-height); +} + +@mixin small{ + font-size: var(--typography-small-paragraph-font-size, var(--typography-paragraph-font-size)); + font-weight: var(--typography-small-paragraph-font-weight, var(--typography-paragraph-font-weight)); + line-height: var(--typography-small-paragraph-line-height, var(--typography-paragraph-line-height)); +} + +@mixin big { + font-size: var(--typography-big-font-size); + font-weight: var(--typography-big-font-weight); + line-height: var(--typography-big-line-height); + text-transform: uppercase; +} \ No newline at end of file diff --git a/sass/homeassistant/pages/community/_photos.scss b/sass/homeassistant/pages/community/_photos.scss new file mode 100644 index 00000000000..4051722b6b3 --- /dev/null +++ b/sass/homeassistant/pages/community/_photos.scss @@ -0,0 +1,92 @@ +.photos { + display: grid; + isolation: isolate; + place-items: center; + position: relative; + + &[data-dsap]:not([data-dsap-is="in"]):not([data-dsap-is="above"]) { // Only if scrolling down into the element + .photo { + opacity: 0; + left: 0; + top: 0; + right: 0; + transform: rotate(0) scale(0.8); + transition-duration: 0s; + transition-delay: 0s; + + &.large { + opacity: 1; + + } + } + } + + .photo { + background-color: #ffffff; + grid-area: 1/1; + display: flex; + flex-direction: column; + gap: 8px; + transition-property: transform, opacity, top, left, right; + transition-duration: .8s; + transition-delay: .25s; + transition-timing-function: cubic-bezier(0.2, 1, 0.5, 1); + + @for $i from 1 through 3 { + &:nth-child(#{$i}) { + transition-delay: #{0.25 + ($i * 0.05)}s; + } + } + + img { + aspect-ratio: 1/1; + width: 100%; + background-color: #f5f5f5; + } + + figcaption { + font-size: 16px; + text-align: center; + } + + &.small { + border-radius: 8px; + padding: 6px; + position: absolute; + right: -15%; + top: -10%; + width: 50%; + z-index: 1; + transform: rotate(9deg); + + img { + border-radius: 4px; + } + } + + &.medium { + border-radius: 12px; + left: -10%; + padding: 8px; + position: absolute; + top: -15%; + width: 70%; + z-index: 2; + transform: rotate(-15deg); + + img { + border-radius: 6px; + } + } + + &.large { + border-radius: 12px; + padding: 12px; + z-index: 3; + + img { + border-radius: 6px; + } + } + } +} \ No newline at end of file diff --git a/sass/homeassistant/pages/community/_stats.scss b/sass/homeassistant/pages/community/_stats.scss new file mode 100644 index 00000000000..6b6c510cbf5 --- /dev/null +++ b/sass/homeassistant/pages/community/_stats.scss @@ -0,0 +1,60 @@ +@property --num { + syntax: ''; + initial-value: 0; + inherits: false; +} + +.stats { + + display: flex; + flex-wrap: wrap; + gap: 24px 40px; + + &[data-dsap-seen] { + .stat { + .stat-value span { + --num: attr(data-value type(#{''})); + } + } + } + + .stat { + display: flex; + flex-direction: column; + min-width: 100px; + + @for $i from 0 through 10 { + &:nth-child(#{$i + 1}) { + .stat-value span { + transition-delay: #{$i * 0.15}s; + } + } + } + + .stat-value { + @include h3; + + color: var(--color-secondary); + display: flex; + gap: 4px; + + span { + --num: 0; + + transition: --num 1.5s ease-out; + counter-reset: num var(--num); + + &::after { + content: counter(num); + } + } + } + + .stat-label { + @include small; + + max-width: 140px; + text-wrap: balance; + } + } +} \ No newline at end of file diff --git a/sass/homeassistant/pages/community/_variables.scss b/sass/homeassistant/pages/community/_variables.scss new file mode 100644 index 00000000000..0d4acb003ff --- /dev/null +++ b/sass/homeassistant/pages/community/_variables.scss @@ -0,0 +1,57 @@ +:root { + --color-primary: #00AEF8; + --color-secondary: #16F3BE; + + // Containers and widths + --container-max-width: 1100px; + --container-full-max-width: 1400px; + --container-gutters: 24px; + + --section-spacing-y: 52px; + + // Typography + --typography-base-font: "Figtree", serif; + --typography-heading-line-height: 1.25; + + --typography-h1-font-size: 36px; + --typography-h1-font-weight: 600; + --typography-h1-line-height: 1; + + --typography-h2-font-size: 30px; + --typography-h2-font-weight: 600; + --typography-h2-line-height: 1.1; + + --typography-h3-font-size: 24px; + --typography-h3-font-weight: 700; + --typography-h3-line-height: var(--typography-heading-line-height); + + --typography-h4-font-size: 14px; + --typography-h4-font-weight: 700; + --typography-h4-line-height: 1.25; + + --typography-paragraph-color: #4F606E; + --typography-paragraph-font-size: 16px; + --typography-paragraph-font-weight: 400; + --typography-paragraph-line-height: 1.25; + + --typography-small-paragraph-font-size: 12px; + --typography-small-paragraph-line-height: 1.3; + + --typography-big-font-size: 46px; + --typography-big-font-weight: 700; + --typography-big-line-height: 1; +} + +@include bp(desktop) { + :root { + --section-spacing-y: 80px; + + --typography-h1-font-size: 66px; + --typography-h2-font-size: 48px; + --typography-h3-font-size: 32px; + --typography-h4-font-size: 20px; + --typography-paragraph-font-size: 24px; + --typography-small-paragraph-font-size: 16px; + --typography-big-font-size: 128px; + } +} \ No newline at end of file diff --git a/sass/homeassistant/pages/community/components/_faq.scss b/sass/homeassistant/pages/community/components/_faq.scss new file mode 100644 index 00000000000..1e793b438ad --- /dev/null +++ b/sass/homeassistant/pages/community/components/_faq.scss @@ -0,0 +1,260 @@ +section#faq { + + .container{ + flex-direction: column; + + h2{ + margin: 0; + margin-bottom: 30px; + @include bp(desktop){ + margin-bottom: 60px; + } + } + } + + .accordion { + + .accordion-items { + display: flex; + flex-direction: column; + margin-top: 1px; + } + + .accordion-item { + --open: 0; + border-bottom: 1px solid #72787E; + display: flex; + flex-direction: column; + + // Checkbox-driven open state + input[type="checkbox"] { + display: none; + } + + input[type="checkbox"]:checked ~ .accordion-item-heading { + // Optionally style the heading when open + } + + input[type="checkbox"]:checked ~ .accordion-item-content-animation-wrapper { + grid-template-rows: 1fr; + transition: grid-template-rows 0.4s ease 0s; + + @media (prefers-reduced-motion: reduce) { + transition: none; + } + + .accordion-item-content-transform-wrapper { + opacity: 1; + transform: translateY(0); + transition: transform 0.4s ease, visibility 0s 0.4s ease, margin-top 0.4s ease, opacity 0.3s ease 0.425s; + visibility: visible; + + @media (prefers-reduced-motion: reduce) { + transition: none; + } + } + } + + input[type="checkbox"]:checked ~ .accordion-item-heading .button-more { + background-color: var(--color-primary) + } + + input[type="checkbox"]:checked ~ .accordion-item-heading .button-more:before, + input[type="checkbox"]:checked ~ .accordion-item-heading .button-more:after { + transform: translate(-50%, -50%) scale(calc(64/28)); + } + + input[type="checkbox"]:checked ~ .accordion-item-heading .button-more:hover:before, + input[type="checkbox"]:checked ~ .accordion-item-heading .button-more:hover:after { + transform: translate(-50%, -50%) scale(calc(56/28)); + } + + input[type="checkbox"]:checked ~ .accordion-item-heading .button-more .plus { + transform: translate(-50%, -50%) rotate(90deg); + } + + input[type="checkbox"]:checked ~ .accordion-item-heading .button-more .plus:before { + opacity: 0; + } + input[type="checkbox"]:checked ~ .accordion-item-heading .button-more .plus:after { + background-color: #ffffff; + } + + &-heading { + cursor: pointer; + margin-bottom: -1px; + transition: background-color 0.3s, color 0.3s; + user-select: none; + isolation: isolate; + + label{ + + display: flex; + justify-content: space-between; + padding: 20px 0; + z-index: 1; + + @include bp(desktop){ + padding: 40px 0; + } + } + + &-title { + font-weight: 400; + font-size: 20px; + color: #002332; + @include bp(desktop){ + font-size: 24px; + } + } + + &-icon { + display: grid; + flex-shrink: 0; + height: 32px; + place-items: center; + position: relative; + width: 32px; + } + + .button-more { + background-color: #ffffff; + border-radius: 50%; + cursor: pointer; + height: 24px; + position: relative; + transition: background-color 0.25s ease-out, box-shadow 0.25s ease-out; + width: 24px; + + .plus { + height: 8px; + left: 50%; + position: absolute; + top: 50%; + transform: translate(-50%, -50%) rotate(0deg); + transition: transform .25s ease-out; + width: 8px; + + @media (prefers-reduced-motion: reduce) { + transition: none; + } + } + + .plus:before, + .plus:after { + background-color: var(--color-primary); + content: ''; + left: 50%; + position: absolute; + top: 50%; + transform: translate(-50%, -50%); + transition: opacity .25s ease-out, background-color .25s ease-out; + + @media (prefers-reduced-motion: reduce) { + transition: none; + } + } + + .plus:before { + height: 2px; + width: 8px; + } + + .plus:after { + height: 8px; + width: 2px; + } + + &:before { + -webkit-backdrop-filter: blur(2px); + backdrop-filter: blur(2px); + background-color: rgba(255, 255, 255, .25); + border-radius: 50%; + content: ''; + height: 28px; + left: 50%; + position: absolute; + top: 50%; + transform: translate(-50%, -50%); + transition: transform .25s ease-out; + width: 28px; + z-index: -1; + + @media (prefers-reduced-motion: reduce) { + transition: none; + } + } + + &:after { + border-radius: 50%; + content: ''; + height: 28px; + left: 50%; + position: absolute; + top: 50%; + transform: translate(-50%, -50%); + width: 28px; + z-index: 1; + } + + &:hover:before, + &:hover:after { + transform: translate(-50%, -50%) scale(calc(34/28)); + } + + // .active state now handled by input:checked selectors above + } + } + + &-content { + gap: 20px; + grid-template-rows: 0fr; + justify-content: center; + padding: 0 0 20px 0; + transition: grid-template-rows 0.3s, transform, visibility 0.3s; + + @media (prefers-reduced-motion: reduce) { + transition: none; + } + + &, + p { + color: #4F606E; + font-size: 16px; + line-height: 1.5; + margin: 0; + } + + p:not(:last-child) { + margin-bottom: 1rem; + } + + &-animation { + min-height: 0; + } + + &-animation-wrapper { + display: grid; + grid-template-rows: 0fr; + overflow: hidden; + transition: grid-template-rows 0.4s ease; + + @media (prefers-reduced-motion: reduce) { + transition: none; + } + } + + &-transform-wrapper { + margin-top: 0; + opacity: 0.875; + transform: translateY(-100%); + transition: transform 0.4s ease, margin-top 0.4s ease, opacity 0.3s ease; + + @media (prefers-reduced-motion: reduce) { + transition: none; + } + } + } + } + } +} \ No newline at end of file diff --git a/sass/homeassistant/pages/community/components/_global.scss b/sass/homeassistant/pages/community/components/_global.scss new file mode 100644 index 00000000000..46b4ef6fe68 --- /dev/null +++ b/sass/homeassistant/pages/community/components/_global.scss @@ -0,0 +1,54 @@ +section#global { + padding-bottom: 0; + + .container { + align-items: center; + flex-direction: column; + gap: 0 40px; + + @include bp(desktop) { + flex-direction: row; + } + } + + .content { + display: flex; + flex-basis: 0; + flex-direction: column; + flex-grow: 1; + gap: 24px; + + @include bp(desktop) { + gap: 60px; + } + + &-inner { + display: flex; + flex-direction: column; + gap: 6px; + + @include bp(desktop) { + gap: 12px; + } + } + + h2 { + margin: 0; + } + + } + + .photos-wrapper { + max-width: 424px; + padding: 100px 0 0; + + @include bp(desktop) { + margin-left: 75px; + } + + .photos { + flex-basis: 0; + flex-grow: 1; + } + } +} \ No newline at end of file diff --git a/sass/homeassistant/pages/community/components/_hero.scss b/sass/homeassistant/pages/community/components/_hero.scss new file mode 100644 index 00000000000..8d914870c3c --- /dev/null +++ b/sass/homeassistant/pages/community/components/_hero.scss @@ -0,0 +1,45 @@ +section#hero { + --section-spacing-y: 0; + + background-image: url('/images/community/hero-m.svg'); + background-position: center; + background-size: cover; + border-radius: 12px; + display: flex; + flex-direction: column; + justify-content: flex-end; + min-height: 600px; + + @include bp(tablet) { + background-image: url('/images/community/hero.svg'); + background-position: center; + border-radius: 24px; + } + + .container { + display: flex; + flex-direction: column; + justify-content: flex-end; + padding: 24px 12px; + + @include bp(tablet) { + padding: 164px 12px 66px 12px; + } + + .content { + align-items: flex-start; + display: flex; + flex-direction: column; + max-width: 670px; + + .event-card { + margin-top: 24px; + + @include bp(tablet) { + margin-top: 60px; + } + } + } + + } +} \ No newline at end of file diff --git a/sass/homeassistant/pages/community/components/_join.scss b/sass/homeassistant/pages/community/components/_join.scss new file mode 100644 index 00000000000..35fe3221dc9 --- /dev/null +++ b/sass/homeassistant/pages/community/components/_join.scss @@ -0,0 +1,106 @@ +section#join { + isolation: isolate; + + .container { + align-items: center; + flex-direction: column; + position: relative; + } + + h2 { + align-items: center; + display: flex; + flex-direction: column; + margin: 0 auto; + text-transform: unset; + + span:not(:first-child) { + margin-top: 8px; + + @include bp(desktop) { + margin-top: 24px; + } + } + } + + p { + //background-color: rgba(245, 246, 250, 0.6); + //backdrop-filter: blur(2px); + max-width: 650px; + text-align: center; + text-wrap: balance; + padding-top: 16px; + z-index: 1; + + @include bp(desktop) { + padding-top: 40px; + } + } + + .buttons { + margin-top: 52px; + z-index: 1; + + @include bp(desktop) { + margin-top: 60px; + } + } + + .avatars { + display: grid; + // 12 cols + grid-template-columns: repeat(6, 1fr); + position: absolute; + inset: 0; + + &[data-dsap]:not([data-dsap-is="in"]):not([data-dsap-is="above"]) { // Reset after scroll up + .avatar{ + opacity: 0; + } + } + + @include bp(tablet) { + grid-template-columns: repeat(12, 1fr); + } + + + .avatar { + justify-self: center; + transition: opacity 0.25s ease-out; + + &.hide{ + img{ + opacity: 0; + } + } + + img { + height: 48px; + width: 48px; + border-radius: 50%; + transition: opacity 0.5s ease-out; + } + + + // hide every even avatar on desktop + + &:nth-child(odd) { + display: none; + @include bp(tablet) { + display: block; + } + } + + + $list: 21,31,76,0,35,70,100,95,50,6,30,26; + @for $i from 1 through 12 { + &:nth-child(#{$i}) { + $offset: nth($list, $i); + transform: translateY(calc(#{$offset} * 1%)); + opacity: 1; + transition-delay: #{0.2 + ($i * 0.05)}s; + } + } + } + } +} \ No newline at end of file diff --git a/sass/homeassistant/pages/community/components/_meetups.scss b/sass/homeassistant/pages/community/components/_meetups.scss new file mode 100644 index 00000000000..d8fe54f5ceb --- /dev/null +++ b/sass/homeassistant/pages/community/components/_meetups.scss @@ -0,0 +1,126 @@ +section#meetups { + + background-color: #CCEFFE; + border-radius: 12px; + overflow: hidden; + margin-top: 24px; + + @include bp(tablet) { + border-radius: 24px; + } + + .container { + gap: 60px; + flex-direction: column; + + @include bp(tablet) { + flex-direction: row; + } + + .content { + display: flex; + flex-direction: column; + align-items: flex-start; + + h2 { + margin: 0; + margin-bottom: 20px; + + @include bp(tablet) { + margin-bottom: 40px; + } + } + + svg:has(use[href="#community"]) { + height: 40px; + width: 40px; + margin-bottom: 12px; + + @include bp(desktop) { + margin-bottom: 40px; + height: 80px; + width: 80px; + } + } + + .event-card { + margin-top: 20px; + + @include bp(tablet) { + margin-top: 40px; + } + } + } + + .guide { + background-color: rgba(246, 248, 251, 0.2); + border: 1px solid #ffffff; + border-radius: 12px; + padding: 40px 24px; + + h3 { + margin: 0; + text-wrap: balance; + margin-bottom: 12px; + } + + p { + color: #002332; + } + + .buttons { + justify-content: flex-start; + } + + .steps { + display: flex; + flex-direction: column; + gap: 8px; + margin: 40px 0; + + .step { + @include small; + padding-left: 32px; + line-height: 1.5; + color: #4F606E; + position: relative; + + &:before { + content: ''; + width: 15px; + height: 15px; + border-radius: 50%; + + box-shadow: inset 0 0 0 5px var(--color-primary); + left: 0; + top: 4px; + position: absolute; + } + + &:not(:last-child) { + padding-bottom: 28px; + + &:after { + content: ''; + width: 1px; + background-color: #4F606E; + left: 7px; + bottom: -4px; + top: 26px; + position: absolute; + } + } + } + } + } + } + + .content, + .guide { + @include bp(desktop) { + flex-grow: 1; + flex-basis: 50%; + width: 100%; + } + } +} \ No newline at end of file diff --git a/sass/homeassistant/pages/community/components/_nav.scss b/sass/homeassistant/pages/community/components/_nav.scss new file mode 100644 index 00000000000..339f5c33cd5 --- /dev/null +++ b/sass/homeassistant/pages/community/components/_nav.scss @@ -0,0 +1,36 @@ +section#nav { + --section-spacing-y: 20px; + @include bp(tablet) { + --section-spacing-y: 40px; + } + + .nav-pills{ + display: flex; + justify-content: center; + flex-wrap: wrap; + + gap: 12px; + + .nav-pill{ + background-color: #ffffff; + border-radius: 32px; + cursor: pointer; + transition: background-color 0.25s ease, color 0.25s ease; + font-size: 12px; + font-weight: 500; + padding: 6px 12px; + white-space: nowrap; + text-decoration: none; + color: #002332; + + &:hover{ + background-color: var(--color-primary); + color: #ffffff; + } + + @include bp(tablet) { + font-size: 14px; + } + } + } +} \ No newline at end of file diff --git a/sass/homeassistant/pages/community/components/_newsletter.scss b/sass/homeassistant/pages/community/components/_newsletter.scss new file mode 100644 index 00000000000..c4f2cea8e15 --- /dev/null +++ b/sass/homeassistant/pages/community/components/_newsletter.scss @@ -0,0 +1,157 @@ +section#newsletter { + --section-spacing-y: 0; + background-color: #002332; + border-radius: 12px; + overflow: hidden; + + .container { + gap: 0px 60px; + align-items: flex-end; + justify-content: center; + align-items: center; + flex-direction: column; + + @include bp(tablet) { + align-items: center; + flex-direction: row; + } + + @include bp(desktop) { + align-items: flex-end; + } + } + + + + h2 { + margin-top: 0; + text-wrap: balance; + } + + &, + p { + color: #ffffff; + } + + @include bp(tablet) { + border-radius: 24px; + } + + .content { + padding: 52px 0; + + @include bp(tablet) { + padding: 100px 0; + } + } + + .buttons { + justify-content: flex-start; + margin-top: 20px; + + @include bp(tablet) { + margin-top: 40px; + } + } + + .editions { + display: flex; + flex-direction: column; + flex-shrink: 0; + max-width: 570px; + align-items: center; + margin-bottom: -40px; + width: 100%; + order: 1; + + @include bp(tablet) { + order: -1; + flex-basis: 50%; + align-self: center; + } + @include bp(desktop) { + } + + @include bp(large-desktop) { + flex-basis: 570px; + align-self: flex-end; + margin-bottom: -64px; + + } + + &[data-dsap]:not([data-dsap-is="in"]):not([data-dsap-is="above"]) { + + // Only if scrolling down into the element + .edition { + transition-duration: 0s; + transition-delay: 0s; + + &:nth-child(1) { + transform: translateY(120px); + } + + &:nth-child(2) { + transform: translateY(40px); + } + } + } + + .edition { + aspect-ratio: 571/300; + width: 100%; + max-width: 100%; + position: relative; + border-radius: 6px; + overflow: hidden; + transition: transform 0.8s cubic-bezier(0.3, 1, 0.5, 1); + transition-delay: .25s; + + @include bp(tablet) { + border-radius: 12px; + } + + .label { + display: none; + } + + img { + width: 100%; + height: 100%; + object-fit: cover; + position: absolute; + border-radius: 0; + inset: 0; + } + + &:nth-child(1) { + max-width: 80%; + height: 45px; + transition-delay: .3s; + z-index: 1; + + @include bp(tablet) { + height: 70px; + } + } + + &:nth-child(2) { + max-width: 90%; + justify-self: center; + height: 50px; + transform: translateY(-20px); + z-index: 2; + + @include bp(tablet) { + height: 80px; + } + } + + &:nth-child(3) { + max-width: 100%; + justify-self: center; + z-index: 3; + transform: translateY(-40px); + } + } + } +} \ No newline at end of file diff --git a/sass/homeassistant/pages/community/index.scss b/sass/homeassistant/pages/community/index.scss new file mode 100644 index 00000000000..ddfff1905df --- /dev/null +++ b/sass/homeassistant/pages/community/index.scss @@ -0,0 +1,20 @@ +// Setup +@import "homeassistant/pages/community/mixins.scss"; +@import "homeassistant/pages/community/variables.scss"; + +// Base +@import "homeassistant/pages/community/base.scss"; +@import "homeassistant/pages/community/icon.scss"; +@import "homeassistant/pages/community/buttons.scss"; +@import "homeassistant/pages/community/event-card.scss"; +@import "homeassistant/pages/community/photos.scss"; +@import "homeassistant/pages/community/stats.scss"; + +// Components +@import "homeassistant/pages/community/components/nav.scss"; +@import "homeassistant/pages/community/components/hero.scss"; +@import "homeassistant/pages/community/components/global.scss"; +@import "homeassistant/pages/community/components/join.scss"; +@import "homeassistant/pages/community/components/newsletter.scss"; +@import "homeassistant/pages/community/components/meetups.scss"; +@import "homeassistant/pages/community/components/faq.scss"; diff --git a/source/_data/community-faq.yml b/source/_data/community-faq.yml new file mode 100644 index 00000000000..ed442270f0b --- /dev/null +++ b/source/_data/community-faq.yml @@ -0,0 +1,11 @@ +items: + - question: Where do I find support? + answer: Support for Home Assistant software (and other Open Home Foundation projects) is done by community members who volunteer their time to help out fellow hobbyists. The most active communities for providing support are our community forums and the Discord server. Just make sure to follow the rules about where and how to post your support query. It is also possible to ask for support in the Facebook group and on Reddit. + - question: How can I contribute to the project? + answer:

No matter your experience, there are plenty of ways to get involved and contribute to Home Assistant! If you’ve got the dev skills (whether you're a beginner or expert), start here, which shows you how to craft a PR, and then check out our extensive Core documentation to help familiarize yourself with our architecture. There you will find instructions on how to join the Developers category in our Discord server, which allows you to chat directly with other developers.

If you're knowledgeable about how to use Home Assistant, don't be afraid to hop onto one (or more) of our community platforms to share this knowledge. This is a great way to contribute if you’re not a developer. Additionally, suppose you're a designer and are passionate about Home Assistant. In that case, we'd love for you to check out our Developers category in Discord (Follow the steps to join the development server, and choose I want to contribute design skills!).

If you’re not able to give your time, you can also financially support the foundation, which pays passionate people to work on Home Assistant full-time. Subscribing to Home Assistant Cloud or purchasing our officially licensed Home Assistant hardware supports the development of this project and many others. In the near future, we hope to relaunch our merch store where community members can purchase swag to support the foundation.

+ - question: Where can I find regional communities? + answer:

This is not an exhaustive list of regional communities, but the ones that we are aware of. Is yours missing? Let us know!

+ - question: Can community hosts be reimbursed for fees related to their meetups? + answer: Yes! Community is the foundation of Home Assistant, and we want to help make sure that meeting with other smart home enthusiasts is a stress-free experience. The Open Home Foundation will reimburse hosts for certain fees related to hosting a meetup. Check out our Expense Guidelines for Hosts for more information. + - question: I have a suggestion for this page! + answer: Excellent! Let Missy know by emailing community@openhomefoundation.org, and we'll put it under consideration. \ No newline at end of file diff --git a/source/_includes/custom/news.html b/source/_includes/custom/news.html index 47bf98b3cbc..3f92dd924e9 100644 --- a/source/_includes/custom/news.html +++ b/source/_includes/custom/news.html @@ -80,11 +80,11 @@ - - + " aria-label="Join the Home Assistant community"> diff --git a/source/_includes/site/footer.html b/source/_includes/site/footer.html index ed9c23e63ad..3867b1c48d3 100644 --- a/source/_includes/site/footer.html +++ b/source/_includes/site/footer.html @@ -31,6 +31,7 @@
  • Community Forum {% icon "tabler:external-link" %}
  • Creator Network {% icon "tabler:external-link" %}
  • Works With Home Assistant {% icon "tabler:external-link" %}
  • +
  • Our community
  • Reporting issues
  • System status

    diff --git a/source/_posts/2025-09-17-home-assistant-turns-12.markdown b/source/_posts/2025-09-17-home-assistant-turns-12.markdown new file mode 100644 index 00000000000..9643984cbeb --- /dev/null +++ b/source/_posts/2025-09-17-home-assistant-turns-12.markdown @@ -0,0 +1,110 @@ +--- +layout: post +title: "Happy 12th Birthday, Home Assistant!" +description: "This year we’re sharing some stories from the community and some stats about our growth." +date: 2025-09-17 00:00:01 +date_formatted: "September 17, 2025" +author: Missy Quarry +comments: true +categories: Announcements +og_image: /images/blog/2025-09-12th-anniversary/art.webp +--- + +Home Assistant 12th Anniversary + +Every September, we celebrate the anniversary of Home Assistant’s first PR in 2013 – for our 12th birthday, we’re going all in on community again. Last month, we asked for submissions on how Home Assistant helps you, and today we will highlight our favorites! We will also take a look at all the cool milestones over the past year in the project, thanks to contributions from you all, and the new things coming up for the community. + +## It’s a communal effort + +When I (Missy Quarry) joined as the Community & Social Media Manager in February 2024, I was still new to how an open source project the size of Home Assistant manages its community. Over the past 18 months, I’ve seen Home Assistant community members from all walks of life — whether DIY tinkerers or people simply looking to make small improvements at home — contribute in their own ways. By sharing your stories and inspiring others, you’ve helped the project grow.  For our 12th birthday, I want to celebrate these contributions, no matter the size or complexity. 😌 + +Before I jump into celebrating all your amazing contributions and how they shape the projects managed by the Open Home Foundation, I have a couple of birthday presents for you. 🎁 + +First, I’m thrilled to share our new Community website! Right now, it’s a simple hub to find community information with ease, but we expect to evolve this over the coming months (or so). You’ll find links to our official community platforms, information on events, and details on meetups, including how to get reimbursed for certain fees as a host. In the future, I’d like to include links to regional communities we’re aware of and showcase more of the kinds of stories I’ll be sharing today. + +*Feel like something’s missing from this new page? [Let me know](mailto:community@openhomefoundation.org)!* + +Next, we’ve been working hard to do more of our development in the open. Last September, I redesigned the Discord server and in doing so I gated the *Developer* category behind a role. This has made it more difficult to develop in the open with the channels hidden behind a role, so we’re switching things up. + +As of this week, the Developer category is now **read-only** for every member. Want to take a peek into the future of Home Assistant? Head to the [#projects channel](https://discord.com/channels/330944238910963714/1346914401508392980) and see what contributors are talking about! Want to join in and contribute with either your feedback or skills? I’ve created [an info thread](https://discord.com/channels/330944238910963714/1346952081881436331) for the channel that explains how to assign yourself either the Developer or Designer role and unlock the ability to chat in the threads. + +Let’s jump into those submitted stories now… 🤩 + +## Happily ever after + +In my opinion, the best thing about Home Assistant is its flexibility - you can integrate such a wide range of devices into it and use their data to build a unique-to-your-home experience. And that’s exactly why I wanted to hear how you, the community, use it in your own home to benefit you. Here are my favorite stories you submitted - I hope one inspires your next project. ✨ + +- [A coffee automation to improve Home Approval Factor](https://jordan.roher.me/projects/home-automation/). ☕️ Jordan made a morning automation to avoid having the coffee grinder grind his morning mood. + +- u/katschung helped their girlfriend fully accept Home Assistant by [creating a dashboard with a retrogame-style floor plan](https://www.reddit.com/r/homeassistant/comments/1hrkku1/pokemon_style_floorplan/). 🕹️ + +- Sythsaz uses Home Assistant to make sure their pupper is fed. 🐾 “*I've managed to make it so my dog's food auto emails the vet then the response to the email gets put on my calendar so I know how long a bag of food lasts as well as adding the receipts to Google Drive.*” + +- Inspired by [PowerDisplayESPHome](https://github.com/johannyren/PowerDisplayESPHome/tree/main), JannickBlmndl [made an LED matrix](https://gitlab.com/JannickBlmndl/ESPHome-Dynamic-Prices-LEDMatrix) that helps their household be more sustainable by being energy flexible. It displays the live energy prices from their energy provider. 📊 + +- [Tano Spirits](https://www.youtube.com/@TanoSpirits) in Melbourne, Australia, uses Home Assistant to automate their Japanese Shochu distillery, inspired by the brewing automations at [Little Island Brewing Co](https://libc.co/brewing-process/) in Singapore. 🍻 + +- Several years ago, HillPhantom found that Home Assistant wasn’t quite ready for him. Over the past year, though, he’s now got Ollama set up with his Home Assistant Voice Preview Edition and has been building guides on how to make your own [mmWave radar sensors in Home Assistant](https://www.youtube.com/watch?v=Gb-4l93st8A). 👋🏻 + +- Over just a few weeks, Pieter van Kampen recently integrated 190 devices that respond to voice control and more than 1200 active entities from his KNX home to create over 30 automations to help with everything from mowing the lawn to controlling shades based on the sun’s location and intensity. 🪟 + +- MB used Zigbee buttons to help collect data for their son’s doctor after he developed some trouble sleeping. This gave excellent insight for the doctor to start looking into causes, and they even used the system remotely while doing further evaluation. 📈 + +- Graham Hosking took automations to another level (before we did) with his [AI Automation Suggester](https://github.com/ITSpecialist111/ai_automation_suggester) and [Automation Inspector](https://github.com/ITSpecialist111/Automation-Inspector). It takes the load off your brain by helping come up with new, clever automations! 🤖 + +- Wessam Lauf fell down the rabbit hole that is Home Assistant once he got his setup running. Inspired by the Graphite theme and after some LLM vibe-coding, he wrote a template for his very own theme, [Frosted Glass](https://github.com/wessamlauf/homeassistant-frosted-glass-themes) - now available in [HACS](https://www.hacs.xyz/). 🎨 + +- Too many of us anthropomorphize our homes, telling it to chill out when five things break the same day. Biofects took that to heart and created this [Home Assistant avatar](https://streamable.com/hnoc63) for his home (here’s a bonus, nightmare fuel [first version](https://streamable.com/xah2va)). 🫣 + +## Developers! 👏🏻 Developers! 👏🏻 Developers! 👏🏻 + +Our community is more than developers, it’s true. But we wouldn’t be the [largest open source project](https://github.blog/news-insights/octoverse/octoverse-2024/) on GitHub if we didn’t have a vibrant and active developer community. This ship sails largely due to their contributions, and we genuinely appreciate all of their efforts. + +That’s why we’re eager to interview community members when we open new roles at the foundation. We’ve employed community members like [Joostlek](https://github.com/joostlek) (who designed the new [Integration Quality Scale](https://developers.home-assistant.io/docs/core/integration-quality-scale/) and helps onboard new integrations into Core), [Timo](https://github.com/TimoPtr) (who is our first ever Android developer and has focused on [polishing the Android app](/blog/2025/07/23/companion-app-for-android/)), and [Maxim](https://github.com/maximmaxim345) (a talented developer from the Music Assistant community who works on both Music Assistant and ESPHome and is one of our newest additions to the team). Their contributions have helped shape how things work around here, but it was their contributions as community members that helped pave the way for their joining the foundation. These are just a select few of the *several* new hires at the foundation who were active community members. + +(Have you checked our [jobs page](https://jobs.ashbyhq.com/openhomefoundation/) recently to see what roles are open? 👀) + +With our community of contributors and working with Nabu Casa on the hardware design, we have successfully launched a few new pieces of hardware. The [Home Assistant Voice Preview Edition](/voice-pe/) brought in language experts from every corner of the world to help ensure our language coverage is the most robust in the industry. Thanks to contributors, we support languages like Greek, Icelandic, and more recently Irish Gaeilge! 😎 We had community contributors help make sure the Home Assistant [Connect ZWA-2](/connect/zwa-2/) was prepared for launch last month. Sincerely, we couldn’t be more grateful for your support and efforts in these spaces. + +Here are some fun stats from our GitHub contributors ([commits on our Core repo](https://github.com/home-assistant/core/graphs/contributors?from=9%2F9%2F2023)): + +- Last 12 months (Sept - Aug) - 14,385 +- Previous 12 months - 14,503 + +A SPECIAL CONGRATULATIONS to [bdraco](https://github.com/bdraco), who just last week surpassed [balloob](https://github.com/balloob) (the founder of Home Assistant) as the contributor with the most commits! + +
    + Top 8 contributors of all time for home-assistant/core + The top 8 contributors of all time in home-assistant/core👏🏻 +
    + +This is just a small peek into all the hard work that goes into maintaining Home Assistant - we have more repositories than just Core, and every single contribution is valued. + +Honorable dev mention from the submitted community stories - I couldn’t leave Joostlek’s (joke) submission out. 🤣 + +- Our very own Head of Developer Relations (his words), Joost Lekkerkerker, says Home Assistant helps keep him off the street. He’s just launched [his new blog](https://joostlek.dev/what-is-a-smart-home/) that talks about his vision of a smart home, and how he was inspired to not buy Tuya Wi-Fi lights after seeing my experience with some path lights. + +## Our humble gratitude + +Community is the core of what we do and the heart of Home Assistant. We thrive because you care and contribute your valuable time to support our collective success. Whether you found our platform because you wanted more privacy from big tech, were intrigued by the number of choices implemented into a single app, or needed something to track your sustainability efforts — you support our values every day. Thanks for choosing us, and thank you for all you do to help support the foundation and the projects we maintain. + +A very special thanks to all our [Home Assistant Cloud](/cloud/) subscribers and anyone who has purchased our official Home Assistant hardware. These support the full-time development of Home Assistant (along with ESPHome, Music Assistant, and so much more), and are the easiest way to ensure these projects keep getting cool new features! + +We have more things coming down the line for you. In the near future, we plan on announcing a new merch store 👕. In the first half of next year, I’ll announce when Home Assistant Community Day 2026 will be. We’re already working with Nabu Casa on the next exciting hardware announcement (no spoilers…for now). And that’s not even touching the industry events we plan on attending, the State of the Open Home, and so much more. I’m excited to take you all on the journey we’re already working on over the next 12 months, and I’m always looking forward to another year of amazing contributions. 😌 + + diff --git a/source/_redirects b/source/_redirects index 399c538d209..33c00c1a362 100644 --- a/source/_redirects +++ b/source/_redirects @@ -17,7 +17,6 @@ layout: null /merch https://home-assistant-store.creator-spring.com /feature-requests https://github.com/orgs/home-assistant/discussions /issues https://github.com/home-assistant/core/issues -/community https://community.home-assistant.io/ /voice /voice_control/builtin_sentences/ /latest-security-alert /security/ diff --git a/source/community/assets/_icons.html b/source/community/assets/_icons.html new file mode 100644 index 00000000000..47d8301dfbd --- /dev/null +++ b/source/community/assets/_icons.html @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/source/community/components/_faq.html b/source/community/components/_faq.html new file mode 100644 index 00000000000..52adf7d7abe --- /dev/null +++ b/source/community/components/_faq.html @@ -0,0 +1,35 @@ +
    +
    +

    Got some questions?

    +
    +
    + {% for item in site.data["community-faq"].items %} +
    + +
    + +
    +
    +
    +
    +
    + {{ item.answer }} +
    +
    +
    +
    +
    + {% endfor %} +
    +
    +
    +
    \ No newline at end of file diff --git a/source/community/components/_global.html b/source/community/components/_global.html new file mode 100644 index 00000000000..4d6a392f614 --- /dev/null +++ b/source/community/components/_global.html @@ -0,0 +1,52 @@ +
    +
    +
    +
    +

    A Global Community, Growing Every Day

    +

    Wherever you are in the world, the community will be ready to share knowledge and ideas.

    +
    +
    +
    +
    + + +
    +
    + Events & Meetups Worldwide +
    +
    +
    +
    + + +
    +
    + Contributors Every Month +
    +
    +
    +
    + + +
    +
    + Active Community Members +
    +
    +
    +
    +
    +
    +
    + A crowd of people gathering in a bar - Utrecht, Netherlands +
    Community Day 2025 - Utrecht
    +
    +
    + A group of 6 people standing in front of a bar - Berlin, Germany +
    Community Meetup - IFA Berlin 2025
    +
    +
    + A few people gathering around a table demonstrating ESP32 hardware - Columbus, Ohio +
    Community Day 2025 - Columbus
    +
    +
    +
    +
    +
    \ No newline at end of file diff --git a/source/community/components/_hero.html b/source/community/components/_hero.html new file mode 100644 index 00000000000..57bd7293645 --- /dev/null +++ b/source/community/components/_hero.html @@ -0,0 +1,23 @@ +
    +
    +
    +

    The Home Assistant Community

    +

    Connect with makers, tinkerers, and smart home enthusiasts. Share ideas, ask questions, and discover ways + to + make your home smarter, more private, and truly yours.

    + +
    +
    No upcoming events
    +
    Time to take matters into your own hands, and create your own meetup.
    + +
    + + + +
    + Create your own event +
    +
    +
    +
    +
    \ No newline at end of file diff --git a/source/community/components/_join.html b/source/community/components/_join.html new file mode 100644 index 00000000000..ba727b88946 --- /dev/null +++ b/source/community/components/_join.html @@ -0,0 +1,106 @@ +
    +
    +

    + Join the + Community +

    +

    + Our vibrant community is very active and super friendly. + We love to talk and share our passion for home + automation. +

    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + + \ No newline at end of file diff --git a/source/community/components/_meetups.html b/source/community/components/_meetups.html new file mode 100644 index 00000000000..1bba7b70e57 --- /dev/null +++ b/source/community/components/_meetups.html @@ -0,0 +1,56 @@ +
    +
    +
    + + + +

    Community Meetups

    +

    The community will be leading meetups across the globe, so find your nearest event and register now! + They’re all free and will be full of smart people with smart homes.

    +
    +
    No upcoming events
    +
    Time to take matters into your own hands, and create your own meetup.
    + +
    + + + +
    + Create your own event +
    +
    +
    + +
    +

    Is your city not included in the list?

    +

    Time to take matters into your own hands, and create your own meetup.

    +
    +
    Using Luma, create an account, and navigate to our Home Assistant Community Day event + page, select Submit Event > Create New Event (the button is above the calendar on the right). 
    +
    Set the invite graphic we created as the event image. When creating your own event, + make sure you add the event name, time zone, date, time, event location, capacity and hosts.
    +
    Click Create Event once you’ve followed the checklist, then come let everyone know in + the Home Assistant Community Day meetup thread on Discord or the Social section of the Community + forum!
    +
    + +
    +
    +
    \ No newline at end of file diff --git a/source/community/components/_nav.html b/source/community/components/_nav.html new file mode 100644 index 00000000000..aef0c9976f6 --- /dev/null +++ b/source/community/components/_nav.html @@ -0,0 +1,9 @@ + diff --git a/source/community/components/_newsletter.html b/source/community/components/_newsletter.html new file mode 100644 index 00000000000..716b3aa443f --- /dev/null +++ b/source/community/components/_newsletter.html @@ -0,0 +1,27 @@ +
    +
    +
    +
    + +
    +
    + +
    +
    + +
    +
    +
    +

    Subscribe to the newsletter

    +

    Open Home is our vision for smart homes that offer privacy, choice and sustainability. The Open Home Foundation newsletter is the latest from the projects making this a reality, including Home Assistant and ESPHome.

    + +
    +
    +
    \ No newline at end of file diff --git a/source/community/index.html b/source/community/index.html new file mode 100644 index 00000000000..7f462471cdd --- /dev/null +++ b/source/community/index.html @@ -0,0 +1,26 @@ +--- +layout: landingpage +title: "Home Assistant Community" +description: "Connect and share ideas with makers, tinkerers, and smart home enthusiasts." +og_image: /images/community/og.jpeg +frontpage: false +--- + + + + +
    +
    + {% include_relative assets/_icons.html %} + {% include_relative components/_nav.html %} + {% include_relative components/_hero.html %} + {% include_relative components/_global.html %} + {% include_relative components/_join.html %} + {% include_relative components/_newsletter.html %} + {% include_relative components/_meetups.html %} + {% include_relative components/_faq.html %} +
    +
    \ No newline at end of file diff --git a/source/images/blog/2025-09-12th-anniversary/art.webp b/source/images/blog/2025-09-12th-anniversary/art.webp new file mode 100644 index 00000000000..60d2d4c73c2 Binary files /dev/null and b/source/images/blog/2025-09-12th-anniversary/art.webp differ diff --git a/source/images/blog/2025-09-12th-anniversary/contributors.webp b/source/images/blog/2025-09-12th-anniversary/contributors.webp new file mode 100644 index 00000000000..15aa04172c6 Binary files /dev/null and b/source/images/blog/2025-09-12th-anniversary/contributors.webp differ diff --git a/source/images/community/berlin.webp b/source/images/community/berlin.webp new file mode 100644 index 00000000000..6f0ace266db Binary files /dev/null and b/source/images/community/berlin.webp differ diff --git a/source/images/community/columbus.webp b/source/images/community/columbus.webp new file mode 100644 index 00000000000..5e3b5098027 Binary files /dev/null and b/source/images/community/columbus.webp differ diff --git a/source/images/community/hero-m.svg b/source/images/community/hero-m.svg new file mode 100644 index 00000000000..44d534063fd --- /dev/null +++ b/source/images/community/hero-m.svg @@ -0,0 +1,438 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/images/community/hero.svg b/source/images/community/hero.svg new file mode 100644 index 00000000000..81bff3a28f7 --- /dev/null +++ b/source/images/community/hero.svg @@ -0,0 +1,473 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/images/community/og.jpeg b/source/images/community/og.jpeg new file mode 100644 index 00000000000..f8d4d697e67 Binary files /dev/null and b/source/images/community/og.jpeg differ diff --git a/source/images/community/utrecht.webp b/source/images/community/utrecht.webp new file mode 100644 index 00000000000..3e39ad99da1 Binary files /dev/null and b/source/images/community/utrecht.webp differ diff --git a/source/images/frontpage/community-card.webp b/source/images/frontpage/community-card.webp new file mode 100644 index 00000000000..fab19710fd2 Binary files /dev/null and b/source/images/frontpage/community-card.webp differ diff --git a/source/images/frontpage/community-meetup.webp b/source/images/frontpage/community-meetup.webp deleted file mode 100644 index dd4d039c31c..00000000000 Binary files a/source/images/frontpage/community-meetup.webp and /dev/null differ diff --git a/source/javascripts/dsap.es.js b/source/javascripts/dsap.es.js new file mode 100644 index 00000000000..a2cec58ada5 --- /dev/null +++ b/source/javascripts/dsap.es.js @@ -0,0 +1,35 @@ +var m = Object.defineProperty; +var p = (a, t, e) => t in a ? m(a, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : a[t] = e; +var r = (a, t, e) => (p(a, typeof t != "symbol" ? t + "" : t, e), e); +class g { + constructor() { + r(this, "elems"); + r(this, "maxScrollDelta", 1e3); + this.init(); + } + init() { + this.elems = document.querySelectorAll("[data-dsap]"), this.elems.forEach((t) => { + t.dataset.dsap = crypto.getRandomValues(new Uint32Array(1))[0].toString(16); + }), this.style = document.createElement("style"), this.style.id = "dsap-style", this.style.innerHTML = `:root{--dsap-max-scroll-delta: ${this.maxScrollDelta}}`, document.head.appendChild(this.style), this.doScroll(), window.addEventListener("scroll", this.debounce(this.doScroll.bind(this)), { passive: !0 }); + } + doScroll() { + const t = window.scrollY, e = t + window.innerHeight; + let i = [`:root{--dsap-max-scroll-delta: ${this.maxScrollDelta}}`]; + this.elems.forEach((s) => { + const o = s.getBoundingClientRect().top + t, h = o + s.getBoundingClientRect().height, c = s.hasAttribute("data-dsap-scroll"); + let l = !1, n = !1, d = 0; + e < o ? n = !1 : t > h ? n = !0 : l = !0, c && (l ? d = ((e - o) / (s.getBoundingClientRect().height + window.innerHeight) * this.maxScrollDelta).toFixed(0) : n && (d = this.maxScrollDelta)), s.dataset.dsapIs = l ? "in" : n ? "above" : "below", l && (s.dataset.dsapSeen = !0), c && i.push(`[data-dsap="${s.dataset.dsap}"]{--dsap-scroll-delta: ${d}}`); + }), this.style.innerHTML !== i.join("") && (this.style.innerHTML = i.join("")); + } + debounce(t) { + let e; + return (...i) => { + e && cancelAnimationFrame(e), e = requestAnimationFrame(() => { + t(...i); + }); + }; + } +} +export { + g as DSAP +};