Community page (#40820)

This commit is contained in:
Darren Griffin 2025-09-17 16:58:18 +02:00 committed by GitHub
parent b1a6c3385b
commit 8c922032ef
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
43 changed files with 2878 additions and 5 deletions

2
.gitignore vendored
View File

@ -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

View File

@ -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

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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%;
}
}

View File

@ -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;
}

View File

@ -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;
}
}
}
}

View File

@ -0,0 +1,60 @@
@property --num {
syntax: '<integer>';
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(#{'<number>'}));
}
}
}
.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;
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}
}
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}
}
}

View File

@ -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;
}
}
}
}
}

View File

@ -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%;
}
}
}

View File

@ -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;
}
}
}
}

View File

@ -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);
}
}
}
}

View File

@ -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";

View File

@ -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 <a href="https://community.home-assistant.io/">community forums</a> and the <a href="https://discord.com/invite/home-assistant">Discord server</a>. 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 <a href="https://www.facebook.com/groups/HomeAssistant/">Facebook group</a> and on <a href="https://www.reddit.com/r/homeassistant/">Reddit</a>.
- question: How can I contribute to the project?
answer: <p>No matter your experience, there are plenty of ways to get involved and contribute to Home Assistant! If youve got the dev skills (whether you're a beginner or expert), <a href="https://developers.home-assistant.io/docs/review-process#before-creating-your-pr">start here</a>, which shows you how to craft a PR, and then check out our extensive <a href="https://developers.home-assistant.io/docs/development_index/">Core documentation</a> 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.</p><p>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 youre 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 <a href="https://developers.home-assistant.io/docs/development_index/">Developers category in Discord</a> (Follow the steps to join the development server, and choose I want to contribute design skills!).</p><p>If youre 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 <a href="https://www.home-assistant.io/cloud/">Home Assistant Cloud</a> or purchasing our officially licensed Home Assistant hardware supports the development of this project and <a href="https://www.openhomefoundation.org/projects/">many others</a>. In the near future, we hope to relaunch our merch store where community members can purchase swag to support the foundation.</p>
- question: Where can I find regional communities?
answer: <p>This is not an exhaustive list of regional communities, but the ones that we are aware of. Is yours missing? Let us know!</p><ul><li><a href="https://forum.hacf.fr/">Home Assistant Communauté Francophone</a></li><li><a href="https://discord.com/invite/6PWva4TYXz">Community Smart Home</a> (German-speaking Discord Server) and <a href="https://community-smarthome.com/">their forums</a></li><li><a href="https://www.facebook.com/groups/HomeAssistantNL/">Home Assistant [DUTCH]</a> (Private FB group)</li><li><a href="https://www.facebook.com/groups/594073248777064">Home Assistant Enthusiasts - South Africa</a> (Private FB group)</li><li><a href="https://www.facebook.com/groups/homeassistantau">Home Assistant AU & NZ</a> (Australia & New Zealand - Public FB group)</li><li><a href="https://www.facebook.com/groups/homeassistant.island/">Home Assistant Ísland</a> (Iceland - Private FB group)</li></ul>
- 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 <a href="mailto:community@openhomefoundation.org">community@openhomefoundation.org</a>, and we'll put it under consideration.

View File

@ -80,11 +80,11 @@
</ol>
</div>
<!-- Community Day 2025 - To move on/after event -->
<a href="https://lu.ma/homeassistant" class="material-card picture-promo" target="_blank" style="
background-image: url(/images/frontpage/community-meetup.webp);
<!-- Community -->
<a href="/community" class="material-card picture-promo" style="
background-image: url(/images/frontpage/community-card.webp);
aspect-ratio: 500/263;
" aria-label="State of the Open Home - Saturday April 12th 2025">
" aria-label="Join the Home Assistant community">
</a>
<!-- OHF notice -->

View File

@ -31,6 +31,7 @@
<li><a class="external-link" href="https://community.home-assistant.io">Community Forum {% icon "tabler:external-link" %}</a></li>
<li><a class="external-link" href="https://creators.home-assistant.io/">Creator Network {% icon "tabler:external-link" %}</a></li>
<li><a class="external-link" href="https://works-with.home-assistant.io/">Works With Home Assistant {% icon "tabler:external-link" %}</a></li>
<li><a href="/community">Our community</li>
<li><a href="/help/reporting_issues/">Reporting issues</a></li>
</ul>
<h3>System status</h3>

View File

@ -0,0 +1,110 @@
---
layout: post
title: "Happy 12th Birthday, Home Assistant!"
description: "This year were 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
---
<img src='/images/blog/2025-09-12th-anniversary/art.webp' style='border: 0;box-shadow: none;' alt="Home Assistant 12th Anniversary">
Every September, we celebrate the anniversary of Home Assistants first PR in 2013 for our 12th birthday, were 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.<!-- more -->
## Its 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, Ive 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, youve 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, Im thrilled to share our new Community website! Right now, its a simple hub to find community information with ease, but we expect to evolve this over the coming months (or so). Youll 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, Id like to include links to regional communities were aware of and showcase more of the kinds of stories Ill be sharing today.
*Feel like somethings missing from this new page? [Let me know](mailto:community@openhomefoundation.org)!*
Next, weve 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 were 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? Ive 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.
Lets 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 thats 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 wasnt quite ready for him. Over the past year, though, hes 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 suns location and intensity. 🪟
- MB used Zigbee buttons to help collect data for their sons 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 (heres a bonus, nightmare fuel [first version](https://streamable.com/xah2va)). 🫣
## Developers! 👏🏻 Developers! 👏🏻 Developers! 👏🏻
Our community is more than developers, its true. But we wouldnt be the [largest open source project](https://github.blog/news-insights/octoverse/octoverse-2024/) on GitHub if we didnt have a vibrant and active developer community. This ship sails largely due to their contributions, and we genuinely appreciate all of their efforts.
Thats why were eager to interview community members when we open new roles at the foundation. Weve 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 couldnt 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!
<div class="contain nb">
<img src="/images/blog/2025-09-12th-anniversary/contributors.webp" alt="Top 8 contributors of all time for home-assistant/core" style="width:100%;max-width:700px;">
The top 8 contributors of all time in home-assistant/core👏🏻
</div>
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 couldnt leave Joostleks (joke) submission out. 🤣
- Our very own Head of Developer Relations (his words), Joost Lekkerkerker, says Home Assistant helps keep him off the street. Hes 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, Ill announce when Home Assistant Community Day 2026 will be. Were already working with Nabu Casa on the next exciting hardware announcement (no spoilers…for now). And thats not even touching the industry events we plan on attending, the State of the Open Home, and so much more. Im excited to take you all on the journey were already working on over the next 12 months, and Im always looking forward to another year of amazing contributions. 😌
<script>
if (!document.cookie.split('; ').find(row => row.startsWith('12th-blog-confetti='))) {
const d = new Date();
d.setTime(d.getTime() + (24*60*60*1000)); // Once a day only
let expires = "expires="+ d.toUTCString();
document.cookie = "12th-blog-confetti=1;" + expires + ";path=/";
const script = document.createElement('script');
script.src = 'https://cdn.jsdelivr.net/npm/canvas-confetti@1.9.3/dist/confetti.browser.min.js';
script.onload = () => {
// launch confetti. Full screen, bottom anchor
confetti({ particleCount: 500, gravity: 1, spread: 120, scalar: 1.5, startVelocity: 150, ticks: 200, angle: 90, origin: { y: 1.4, x: 0.5 }});
};
document.head.appendChild(script);
}
</script>

View File

@ -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/

View File

@ -0,0 +1,63 @@
<svg style="display: none;">
<defs>
<symbol id="luma" viewBox="0 0 12 12">
<path d="M12 6C8.6871 6 6 3.3129 6 0C6 3.3129 3.3129 6 0 6C3.3129 6 6 8.6871 6 12C6 8.6871 8.6871 6 12 6Z"
fill="currentColor" />
</symbol>
<symbol id="creator" viewBox="0 0 12 13">
<path
d="M6 11.315C5.67 11.315 5.3875 11.195 5.1525 10.955C4.9175 10.715 4.8 10.43 4.8 10.1C4.8 9.77 4.9175 9.4875 5.1525 9.2525C5.3875 9.0175 5.67 8.9 6 8.9L6.36 8.555C6.44 8.475 6.5325 8.4125 6.6375 8.3675C6.7425 8.3225 6.85 8.3 6.96 8.3C7.19 8.3 7.3875 8.385 7.5525 8.555C7.7175 8.725 7.8 8.925 7.8 9.155V9.41C7.8 9.61 7.865 9.775 7.995 9.905C8.125 10.035 8.29 10.1 8.49 10.1C8.64 10.1 8.775 10.055 8.895 9.965C9.015 9.875 9.1 9.76 9.15 9.62L9.33 9.125C9.42 8.885 9.565 8.6875 9.765 8.5325C9.965 8.3775 10.195 8.3 10.455 8.3C10.565 8.02 10.6525 7.73 10.7175 7.43C10.7825 7.13 10.815 6.82 10.815 6.5C10.815 5.61 10.5925 4.7975 10.1475 4.0625C9.7025 3.3275 9.12 2.75 8.4 2.33V2.9C8.4 3.23 8.2825 3.5125 8.0475 3.7475C7.8125 3.9825 7.53 4.1 7.2 4.1H6.6V5.3C6.6 5.47 6.5425 5.6125 6.4275 5.7275C6.3125 5.8425 6.17 5.9 6 5.9H5.4V6.92C5.4 7.14 5.325 7.325 5.175 7.475C5.025 7.625 4.84 7.7 4.62 7.7C4.48 7.7 4.3525 7.67 4.2375 7.61C4.1225 7.55 4.03 7.465 3.96 7.355L3 5.9H2.4V6.5C2.4 6.81 2.295 7.075 2.085 7.295C1.875 7.515 1.625 7.645 1.335 7.685C1.595 8.725 2.1575 9.59 3.0225 10.28C3.8875 10.97 4.88 11.315 6 11.315ZM7.2 7.7C7.03 7.7 6.8875 7.6425 6.7725 7.5275C6.6575 7.4125 6.6 7.27 6.6 7.1C6.6 6.93 6.6575 6.7875 6.7725 6.6725C6.8875 6.5575 7.03 6.5 7.2 6.5H7.8C7.97 6.5 8.1125 6.5575 8.2275 6.6725C8.3425 6.7875 8.4 6.93 8.4 7.1C8.4 7.27 8.3425 7.4125 8.2275 7.5275C8.1125 7.6425 7.97 7.7 7.8 7.7H7.2ZM8.595 5.9C8.395 5.9 8.2375 5.8225 8.1225 5.6675C8.0075 5.5125 7.98 5.34 8.04 5.15L8.265 4.49C8.305 4.37 8.375 4.275 8.475 4.205C8.575 4.135 8.685 4.1 8.805 4.1C9.005 4.1 9.1625 4.1775 9.2775 4.3325C9.3925 4.4875 9.42 4.66 9.36 4.85L9.135 5.51C9.095 5.63 9.025 5.725 8.925 5.795C8.825 5.865 8.715 5.9 8.595 5.9ZM6 12.5C5.17 12.5 4.39 12.3425 3.66 12.0275C2.93 11.7125 2.295 11.285 1.755 10.745C1.215 10.205 0.7875 9.57 0.4725 8.84C0.1575 8.11 0 7.33 0 6.5C0 5.67 0.1575 4.89 0.4725 4.16C0.7875 3.43 1.215 2.795 1.755 2.255C2.295 1.715 2.93 1.2875 3.66 0.9725C4.39 0.6575 5.17 0.5 6 0.5C6.83 0.5 7.61 0.6575 8.34 0.9725C9.07 1.2875 9.705 1.715 10.245 2.255C10.785 2.795 11.2125 3.43 11.5275 4.16C11.8425 4.89 12 5.67 12 6.5C12 7.33 11.8425 8.11 11.5275 8.84C11.2125 9.57 10.785 10.205 10.245 10.745C9.705 11.285 9.07 11.7125 8.34 12.0275C7.61 12.3425 6.83 12.5 6 12.5Z"
fill="currentColor" />
</symbol>
<symbol id="docs" viewBox="0 0 10 13">
<path
d="M1.25 12.5C0.90625 12.5 0.611979 12.3825 0.367188 12.1475C0.122396 11.9125 0 11.63 0 11.3V1.7C0 1.37 0.122396 1.0875 0.367188 0.8525C0.611979 0.6175 0.90625 0.5 1.25 0.5H8.75C9.09375 0.5 9.38802 0.6175 9.63281 0.8525C9.8776 1.0875 10 1.37 10 1.7V11.3C10 11.63 9.8776 11.9125 9.63281 12.1475C9.38802 12.3825 9.09375 12.5 8.75 12.5H1.25ZM1.25 11.3H8.75V1.7H7.5V5.9L5.9375 5L4.375 5.9V1.7H1.25V11.3Z"
fill="currentColor" />
</symbol>
<symbol id="download" viewBox="0 0 12 13">
<path
d="M6 9.5L2.25 5.75L3.3 4.6625L5.25 6.6125V0.5H6.75V6.6125L8.7 4.6625L9.75 5.75L6 9.5ZM1.5 12.5C1.0875 12.5 0.734375 12.3531 0.440625 12.0594C0.146875 11.7656 0 11.4125 0 11V8.75H1.5V11H10.5V8.75H12V11C12 11.4125 11.8531 11.7656 11.5594 12.0594C11.2656 12.3531 10.9125 12.5 10.5 12.5H1.5Z"
fill="currentColor" />
</symbol>
<symbol id="forum" viewBox="0 0 13 13">
<path
d="M3.9 7.8H9.1V7.4425C9.1 6.96583 8.86167 6.58125 8.385 6.28875C7.90833 5.99625 7.28 5.85 6.5 5.85C5.72 5.85 5.09167 5.99625 4.615 6.28875C4.13833 6.58125 3.9 6.96583 3.9 7.4425V7.8ZM6.5 5.2C6.8575 5.2 7.16354 5.07271 7.41813 4.81812C7.67271 4.56354 7.8 4.2575 7.8 3.9C7.8 3.5425 7.67271 3.23646 7.41813 2.98187C7.16354 2.72729 6.8575 2.6 6.5 2.6C6.1425 2.6 5.83646 2.72729 5.58188 2.98187C5.32729 3.23646 5.2 3.5425 5.2 3.9C5.2 4.2575 5.32729 4.56354 5.58188 4.81812C5.83646 5.07271 6.1425 5.2 6.5 5.2ZM0 13V1.3C0 0.9425 0.127292 0.636458 0.381875 0.381875C0.636458 0.127292 0.9425 0 1.3 0H11.7C12.0575 0 12.3635 0.127292 12.6181 0.381875C12.8727 0.636458 13 0.9425 13 1.3V9.1C13 9.4575 12.8727 9.76354 12.6181 10.0181C12.3635 10.2727 12.0575 10.4 11.7 10.4H2.6L0 13ZM2.0475 9.1H11.7V1.3H1.3V9.83125L2.0475 9.1Z"
fill="currentColor" />
</symbol>
<symbol id="youtube" viewBox="0 0 13 11">
<path
d="M12.7282 2.37091C12.5784 1.81123 12.1385 1.3714 11.5788 1.22158C10.5655 0.949768 6.49998 0.949768 6.49998 0.949768C6.49998 0.949768 2.43455 0.949768 1.42114 1.22158C0.86146 1.3714 0.421633 1.81123 0.271814 2.37091C8.13641e-08 3.38432 0 5.49998 0 5.49998C0 5.49998 8.13641e-08 7.61565 0.271814 8.62907C0.421633 9.18875 0.86146 9.62857 1.42114 9.77836C2.43455 10.0502 6.49998 10.0502 6.49998 10.0502C6.49998 10.0502 10.5655 10.0502 11.5788 9.77836C12.1385 9.62857 12.5784 9.18875 12.7282 8.62907C13 7.61565 13 5.49998 13 5.49998C13 5.49998 12.9989 3.38432 12.7282 2.37091Z"
fill="currentColor" />
<path d="M5.19873 7.44973L8.57608 5.49997L5.19873 3.55017V7.44973Z" fill="white" />
</symbol>
<symbol id="reddit" viewBox="0 0 14 13">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M9.0825 8.39774C8.55925 8.39774 8.11956 7.96523 8.11956 7.43193C8.11956 6.89864 8.55925 6.45184 9.0825 6.45184C9.60575 6.45184 10.0301 6.89864 10.0301 7.43193C10.0301 7.96523 9.60575 8.39774 9.0825 8.39774ZM9.30474 10.2723C8.81737 10.7686 8.06575 11.0098 7.007 11.0098C7.00481 11.0098 7.00218 11.0094 6.99955 11.0094C6.99737 11.0094 6.99476 11.0098 6.99213 11.0098C5.93338 11.0098 5.18219 10.7686 4.69526 10.2723C4.54563 10.1198 4.54563 9.87322 4.69526 9.72117C4.84444 9.56912 5.08638 9.56912 5.23601 9.72117C5.57201 10.0636 6.14644 10.2304 6.99213 10.2304C6.99476 10.2304 6.99737 10.2308 6.99955 10.2308C7.00218 10.2308 7.00481 10.2304 7.007 10.2304C7.85268 10.2304 8.42755 10.0636 8.76399 9.72117C8.91362 9.56868 9.15556 9.56912 9.30474 9.72117C9.45393 9.87367 9.45393 10.1203 9.30474 10.2723ZM3.96988 7.43193C3.96988 6.89909 4.40869 6.45184 4.93151 6.45184C5.45476 6.45184 5.87912 6.89909 5.87912 7.43193C5.87912 7.96523 5.45476 8.39774 4.93151 8.39774C4.40869 8.39774 3.96988 7.96523 3.96988 7.43193ZM11.6655 1.27943C12.0199 1.27943 12.3082 1.57328 12.3082 1.93401C12.3082 2.29519 12.0199 2.58903 11.6655 2.58903C11.3111 2.58903 11.0228 2.29519 11.0228 1.93401C11.0228 1.57328 11.3111 1.27943 11.6655 1.27943ZM14 6.37113C14 5.42538 13.2453 4.65622 12.3174 4.65622C11.9158 4.65622 11.5469 4.80068 11.2573 5.04102C10.2314 4.38376 8.92938 3.98781 7.53375 3.90399L8.26175 1.55811L10.2624 2.03834C10.3149 2.78076 10.9239 3.36846 11.6655 3.36846C12.4412 3.36846 13.0725 2.72503 13.0725 1.93401C13.0725 1.14343 12.4412 0.5 11.6655 0.5C11.123 0.5 10.6514 0.814797 10.4164 1.27452L8.09156 0.716705C7.89687 0.669886 7.7 0.784043 7.63962 0.978455L6.73575 3.89016C5.23206 3.92762 3.81851 4.32491 2.71732 5.02051C2.43163 4.79265 2.07243 4.65622 1.68262 4.65622C0.754682 4.65622 0 5.42538 0 6.37113C0 6.9557 0.288749 7.47251 0.728437 7.78196C0.710062 7.91796 0.700434 8.05485 0.700434 8.19352C0.700434 9.3756 1.37462 10.4752 2.59874 11.2894C3.77212 12.0701 5.32526 12.5 6.97157 12.5C8.61788 12.5 10.171 12.0701 11.3444 11.2894C12.5685 10.4752 13.2427 9.3756 13.2427 8.19352C13.2427 8.06734 13.2344 7.94203 13.2191 7.81763C13.6881 7.51308 14 6.97844 14 6.37113Z"
fill="currentColor" />
</symbol>
<symbol id="facebook" viewBox="0 0 13 13">
<path
d="M13 6.49999C13 2.91015 10.0898 0 6.5 0C2.91015 0 0 2.91015 0 6.49999C0 9.54835 2.09859 12.1061 4.92976 12.8086V8.48628H3.5894V6.49999H4.92976V5.64409C4.92976 3.43171 5.93096 2.40627 8.103 2.40627C8.51479 2.40627 9.22535 2.487 9.51603 2.56775V4.36836C9.3626 4.35221 9.09615 4.34412 8.76509 4.34412C7.69928 4.34412 7.28746 4.74785 7.28746 5.79752V6.49999H9.4106L9.04587 8.48628H7.28746V12.9524C10.5059 12.5636 13 9.82325 13 6.49999Z"
fill="white" />
<path
d="M9.04587 8.48628L9.4106 6.49999H7.28746V5.79752C7.28746 4.74785 7.69928 4.34412 8.76509 4.34412C9.09615 4.34412 9.3626 4.35221 9.51603 4.36836V2.56775C9.22535 2.487 8.51479 2.40627 8.103 2.40627C5.93096 2.40627 4.92976 3.43171 4.92976 5.64409V6.49999H3.5894V8.48628H4.92976V12.8086C5.43267 12.9333 5.95851 13 6.49999 13C6.76659 13 7.02928 12.9835 7.28746 12.9524V8.48628H9.04587Z"
fill="currentColor" />
</symbol>
<symbol id="discord" viewBox="0 0 13 11" fill="none">
<path
d="M11.0122 1.3375C10.1707 0.94625 9.27094 0.661907 8.33024 0.5C8.21471 0.707559 8.07973 0.986731 7.98668 1.20881C6.98669 1.05937 5.99589 1.05937 5.01429 1.20881C4.92125 0.986731 4.78322 0.707559 4.66665 0.5C3.72494 0.661907 2.82412 0.947295 1.9826 1.33957C0.285265 3.88835 -0.174856 6.37382 0.0552048 8.82399C1.18097 9.6594 2.27197 10.1669 3.34456 10.499C3.60939 10.1368 3.84558 9.75177 4.04905 9.346C3.66153 9.19968 3.29037 9.01911 2.93966 8.80947C3.03271 8.74098 3.12371 8.66937 3.21164 8.59568C5.35069 9.58988 7.67482 9.58988 9.78831 8.59568C9.87727 8.66937 9.96827 8.74098 10.0603 8.80947C9.70855 9.02013 9.33637 9.2007 8.94885 9.34705C9.15232 9.75177 9.3875 10.1378 9.65334 10.5C10.727 10.1679 11.819 9.66045 12.9447 8.82399C13.2147 5.98361 12.4836 3.52097 11.0122 1.3375ZM4.34047 7.31716C3.69835 7.31716 3.17176 6.72147 3.17176 5.99606C3.17176 5.27066 3.6871 4.67394 4.34047 4.67394C4.99385 4.67394 5.52043 5.26961 5.50918 5.99606C5.5102 6.72147 4.99385 7.31716 4.34047 7.31716ZM8.65948 7.31716C8.01736 7.31716 7.49077 6.72147 7.49077 5.99606C7.49077 5.27066 8.0061 4.67394 8.65948 4.67394C9.31285 4.67394 9.83944 5.26961 9.8282 5.99606C9.8282 6.72147 9.31285 7.31716 8.65948 7.31716Z"
fill="currentColor" />
</symbol>
<symbol id="community" viewBox="0 0 80 80" fill="none">
<path d="M39.9998 50.9266C46.0344 50.9266 50.9264 46.0346 50.9264 40C50.9264 33.9654 46.0344 29.0734 39.9998 29.0734C33.9652 29.0734 29.0732 33.9654 29.0732 40C29.0732 46.0346 33.9652 50.9266 39.9998 50.9266Z" fill="#002332"/>
<path d="M61.8691 79.2138C49.8034 79.2138 40.016 69.4264 40.016 57.3606C52.0817 57.3606 61.8691 67.148 61.8691 79.2138Z" fill="#002332"/>
<path d="M40.0002 57.3445C40.0002 69.4103 30.2128 79.1977 18.147 79.1977C18.147 67.1319 27.9344 57.3445 40.0002 57.3445Z" fill="#002332"/>
<path d="M0.802246 61.8532C0.802246 49.7874 10.5896 40 22.6554 40C22.6554 52.0658 12.868 61.8532 0.802246 61.8532Z" stroke="#16F3BE" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M22.6553 40C10.5895 40 0.802085 30.2126 0.802085 18.1468C12.8679 18.1468 22.6553 27.9342 22.6553 40Z" stroke="#16F3BE" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M57.3447 40.016C69.4105 40.016 79.1979 49.8034 79.1979 61.8692C67.1321 61.8692 57.3447 52.0818 57.3447 40.016Z" stroke="#16F3BE" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M79.2139 18.1468C79.2139 30.2126 69.4265 40 57.3607 40C57.3607 27.9342 67.1481 18.1468 79.2139 18.1468Z" stroke="#16F3BE" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M40.016 22.6555C40.016 10.5897 49.8034 0.802268 61.8691 0.802268C61.8691 12.8681 52.0657 22.6555 40.016 22.6555Z" stroke="#16F3BE" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M18.147 0.802246C30.2128 0.802246 40.0002 10.5897 40.0002 22.6554C27.9344 22.6554 18.147 12.868 18.147 0.802246Z" stroke="#16F3BE" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</symbol>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -0,0 +1,35 @@
<section id="faq">
<div class="container">
<h2>Got some questions?</h2>
<div class="accordion">
<div class="accordion-items">
{% for item in site.data["community-faq"].items %}
<div class="accordion-item">
<input type="checkbox" class="accordion-item-checkbox" id="{{ item.question | slugify }}" />
<div class="accordion-item-heading">
<label for="{{ item.question | slugify }}" class="accordion-item-heading-label">
<div class="accordion-item-heading-title">
{{ item.question }}
</div>
<div class="accordion-item-heading-icon">
<div class="button-more">
<div class="plus"></div>
</div>
</div>
</label>
</div>
<div class="accordion-item-content-animation-wrapper">
<div class="accordion-item-content-animation">
<div class="accordion-item-content-transform-wrapper">
<div class="accordion-item-content">
{{ item.answer }}
</div>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
</section>

View File

@ -0,0 +1,52 @@
<section id="global">
<div class="container">
<div class="content">
<div class="content-inner">
<h2>A Global Community, Growing Every Day</h2>
<p>Wherever you are in the world, the community will be ready to share knowledge and ideas.</p>
</div>
<div class="stats" data-dsap>
<div class="stat">
<div class="stat-value">
+<span data-value="90"></span>
</div>
<div class="stat-label">
Events & Meetups Worldwide
</div>
</div>
<div class="stat">
<div class="stat-value">
+<span data-value="200"></span>
</div>
<div class="stat-label">
Contributors Every Month
</div>
</div>
<div class="stat">
<div class="stat-value">
+<span data-value="430000"></span>
</div>
<div class="stat-label">
Active Community Members
</div>
</div>
</div>
</div>
<div class="photos-wrapper">
<div class="photos" data-dsap>
<figure class="photo large">
<img src="/images/community/utrecht.webp" alt="A crowd of people gathering in a bar - Utrecht, Netherlands" />
<figcaption>Community Day 2025 - Utrecht</figcaption>
</figure>
<figure class="photo medium">
<img src="/images/community/berlin.webp" alt="A group of 6 people standing in front of a bar - Berlin, Germany" />
<figcaption>Community Meetup - IFA Berlin 2025</figcaption>
</figure>
<figure class="photo small">
<img src="/images/community/columbus.webp" alt="A few people gathering around a table demonstrating ESP32 hardware - Columbus, Ohio" />
<figcaption>Community Day 2025 - Columbus</figcaption>
</figure>
</div>
</div>
</div>
</section>

View File

@ -0,0 +1,23 @@
<section id="hero">
<div class="container" id="community">
<div class="content">
<h1>The Home Assistant Community</h1>
<p>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.</p>
<div class="event-card">
<div class="event-title">No upcoming events</div>
<div class="event-meta">Time to take matters into your own hands, and create your own meetup.</div>
<a href="https://luma.com/homeassistant" class="button secondary" target="_blank" rel="noopener">
<div class="icon">
<svg>
<use href="#luma" />
</svg>
</div>
Create your own event
</a>
</div>
</div>
</div>
</section>

View File

@ -0,0 +1,106 @@
<section id="join">
<div class="container">
<h2>
<span class="h1">Join the</span>
<span class="big">Community</span>
</h2>
<p>
Our vibrant community is very active and super friendly.
We love to talk and share our passion for home
automation.
</p>
<div class="buttons">
<a href="https://creators.home-assistant.io/" class="button" target="_blank" rel="noreferrer">
<div class="icon">
<svg>
<use href="#creator" />
</svg>
</div>
Creator Network
</a>
<a href="https://community.home-assistant.io/" class="button" target="_blank" rel="noreferrer">
<div class="icon">
<svg>
<use href="#forum" />
</svg>
</div>
Forum
</a>
<a href="https://www.home-assistant.io/join-chat" class="button" target="_blank" rel="noreferrer">
<div class="icon">
<svg>
<use href="#discord" />
</svg>
</div>
Discord
</a>
<a href="https://www.reddit.com/r/homeassistant/" class="button">
<div class="icon">
<svg>
<use href="#reddit" />
</svg>
</div>
Reddit
</a>
<a href="https://www.facebook.com/homeassistantio" class="button">
<div class="icon">
<svg>
<use href="#facebook" />
</svg>
</div>
Facebook
</a>
</div>
<div class="avatars" data-dsap data-dsap-scroll>
<div class="avatar"></div>
<div class="avatar"></div>
<div class="avatar"></div>
<div class="avatar"></div>
<div class="avatar"></div>
<div class="avatar"></div>
<div class="avatar"></div>
<div class="avatar"></div>
<div class="avatar"></div>
<div class="avatar"></div>
<div class="avatar"></div>
<div class="avatar"></div>
</div>
</div>
</section>
<script>
let owners = {{ site.data.codeowners | jsonify }};
owners = owners.sort(() => Math.random() - 0.5);
let lastIndex = -1;
let avatarDivs = document.querySelectorAll('#join .avatars .avatar');
avatarDivs.forEach((div, index) => {
let img = document.createElement('img');
div.appendChild(img);
if (index < owners.length) {
let owner = owners[index];
div.querySelector('img').src = `https://github.com/${owner}.png`;
div.title = owner;
}
});
setInterval(() => {
let index = Math.floor(Math.random() * avatarDivs.length);
if (index === lastIndex) {
index = (index + 1) % avatarDivs.length;
}
lastIndex = index;
let ownerIndex = Math.floor(Math.random() * owners.length);
let owner = owners[ownerIndex];
avatarDivs[index].classList.add('hide');
setTimeout(() => {
avatarDivs[index].querySelector('img').src = `https://github.com/${owner}.png`;
avatarDivs[index].title = owner;
}, 500);
setTimeout(() => {
avatarDivs[index].classList.remove('hide');
}, 1000);
}, 2000);
</script>

View File

@ -0,0 +1,56 @@
<section id="meetups">
<div class="container">
<div class="content">
<svg>
<use href="#community" />
</svg>
<h2 class="h1">Community Meetups</h2>
<p>The community will be leading meetups across the globe, so find your nearest event and register now!
Theyre all free and will be full of smart people with smart homes.</p>
<div class="event-card">
<div class="event-title">No upcoming events</div>
<div class="event-meta">Time to take matters into your own hands, and create your own meetup.</div>
<a href="https://luma.com/homeassistant" class="button secondary" target="_blank" rel="noopener">
<div class="icon">
<svg>
<use href="#luma" />
</svg>
</div>
Create your own event
</a>
</div>
</div>
<div class="guide">
<h3>Is your city not included in the list?</h3>
<p>Time to take matters into your own hands, and create your own meetup.</p>
<div class="steps">
<div class="step">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). </div>
<div class="step">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.</div>
<div class="step">Click Create Event once youve 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!</div>
</div>
<div class="buttons">
<a href="https://docs.google.com/document/d/1kcziY3ZJfut2mPez7zY6xcjv8VKcynFxvKYI51NJ8-Y" class="button" target="_blank" rel="noopener">
<div class="icon">
<svg>
<use href="#docs" />
</svg>
</div>
Expense Guidelines for Hosts
</a>
<a href="https://drive.google.com/drive/folders/1cQCV4vcfKx0FCNwzNqd3F2lE1xR5W5co" class="button" target="_blank" rel="noopener">
<div class="icon">
<svg>
<use href="#download" />
</svg>
</div>
Graphic Assets
</a>
</div>
</div>
</div>
</section>

View File

@ -0,0 +1,9 @@
<section id="nav">
<div class="nav-pills">
<a href="#community" class="nav-pill">Home Assistant Community</a>
<a href="#join" class="nav-pill">Join</a>
<a href="#newsletter" class="nav-pill">Newsletter</a>
<a href="#meetups" class="nav-pill">Meetups</a>
<a href="#faq" class="nav-pill">FAQ</a>
</div>
</section>

View File

@ -0,0 +1,27 @@
<section id="newsletter">
<div class="container">
<div class="editions" data-dsap>
<div class="edition">
<img src="https://newsletter.openhomefoundation.org/content/images/size/w960/2025/06/1200X630.jpg" />
</div>
<div class="edition">
<img src="https://newsletter.openhomefoundation.org/content/images/size/w960/2025/07/OHF_Newsletter2507_1200X630.png" />
</div>
<div class="edition">
<img src="https://newsletter.openhomefoundation.org/content/images/size/w960/2025/08/OHF_Newsletter2508_1200x630.png" />
</div>
</div>
<div class="content">
<h2>Subscribe to the newsletter</h2>
<p class="small">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.</p>
<div class="buttons">
<a href="https://newsletter.openhomefoundation.org/#/portal/signup" class="button secondary" target="_blank" rel="noopener">
Subscribe Now
</a>
<a href="https://newsletter.openhomefoundation.org/" class="button hollow-dark">
Read Our Latest Posts
</a>
</div>
</div>
</div>
</section>

View File

@ -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
---
<link rel="stylesheet" href="/stylesheets/homeassistant/pages/community/index.css" />
<script type="module">
import {DSAP} from "/javascripts/dsap.es.js";
window.dsap = new DSAP();
</script>
<main id="page-community">
<div class="container-full">
{% 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 %}
</div>
</main>

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 316 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 209 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 352 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 514 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

View File

@ -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
};