New Membership Page and other changes #4

Merged
kumi merged 29 commits from membership-page into main 2024-05-30 10:15:10 +00:00
33 changed files with 860 additions and 421 deletions

View file

@ -24,3 +24,8 @@ The website will be available at `http://localhost:9810`.
This project is licensed under the MIT License - see the [LICENSE](LICENSE)
file for details.
## Attribution
This website is built using the [Bootstrap](https://getbootstrap.com) framework
and [Phosphor Icons](https://phosphoricons.com).

View file

@ -85,6 +85,48 @@ h5 {
margin-top: 10px;
}
.currency-col {
width: 200px;
white-space: nowrap;
text-align: right;
}
.table-transparency td:not(:first-child) {
text-align: right;
}
.section {
padding: 20px 0;
border-bottom: 1px solid #e0e0e0;
}
.alert-warning {
background-color: #fff3cd;
border-color: #ffeeba;
color: #856404;
padding: 15px;
margin-bottom: 20px;
border-radius: 4px;
}
.alert-warning .alert-link {
color: #856404;
font-weight: bold;
text-decoration: underline;
}
.alert-warning .alert-link:hover {
color: #604c2e;
}
.bs-icon.bs-icon-primary svg {
fill: var(--bs-primary-bg-subtle);
}
.bs-icon.bs-icon-lg svg {
fill: var(--bs-primary)
}
/* Responsive Styles */
@media (max-width: 768px) {
.navbar .container {

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M128,96H232a8,8,0,0,1,0,16H128a8,8,0,0,1,0-16Zm104,32H128a8,8,0,0,0,0,16H232a8,8,0,0,0,0-16Zm0,32H80a8,8,0,0,0,0,16H232a8,8,0,0,0,0-16Zm0,32H80a8,8,0,0,0,0,16H232a8,8,0,0,0,0-16ZM96,144a8,8,0,0,0,0-16H88V64h32v8a8,8,0,0,0,16,0V56a8,8,0,0,0-8-8H32a8,8,0,0,0-8,8V72a8,8,0,0,0,16,0V64H72v64H64a8,8,0,0,0,0,16Z"></path></svg>

After

Width:  |  Height:  |  Size: 430 B

1
assets/dist/icons/calendar.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M208,32H184V24a8,8,0,0,0-16,0v8H88V24a8,8,0,0,0-16,0v8H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32ZM72,48v8a8,8,0,0,0,16,0V48h80v8a8,8,0,0,0,16,0V48h24V80H48V48ZM208,208H48V96H208V208Zm-96-88v64a8,8,0,0,1-16,0V132.94l-4.42,2.22a8,8,0,0,1-7.16-14.32l16-8A8,8,0,0,1,112,120Zm59.16,30.45L152,176h16a8,8,0,0,1,0,16H136a8,8,0,0,1-6.4-12.8l28.78-38.37A8,8,0,1,0,145.07,132a8,8,0,1,1-13.85-8A24,24,0,0,1,176,136,23.76,23.76,0,0,1,171.16,150.45Z"></path></svg>

After

Width:  |  Height:  |  Size: 604 B

1
assets/dist/icons/chats.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M216,80H184V48a16,16,0,0,0-16-16H40A16,16,0,0,0,24,48V176a8,8,0,0,0,13,6.22L72,154V184a16,16,0,0,0,16,16h93.59L219,230.22a8,8,0,0,0,5,1.78,8,8,0,0,0,8-8V96A16,16,0,0,0,216,80ZM66.55,137.78,40,159.25V48H168v88H71.58A8,8,0,0,0,66.55,137.78ZM216,207.25l-26.55-21.47a8,8,0,0,0-5-1.78H88V152h80a16,16,0,0,0,16-16V96h32Z"></path></svg>

After

Width:  |  Height:  |  Size: 438 B

1
assets/dist/icons/coffee.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M80,56V24a8,8,0,0,1,16,0V56a8,8,0,0,1-16,0Zm40,8a8,8,0,0,0,8-8V24a8,8,0,0,0-16,0V56A8,8,0,0,0,120,64Zm32,0a8,8,0,0,0,8-8V24a8,8,0,0,0-16,0V56A8,8,0,0,0,152,64Zm96,56v8a40,40,0,0,1-37.51,39.91,96.59,96.59,0,0,1-27,40.09H208a8,8,0,0,1,0,16H32a8,8,0,0,1,0-16H56.54A96.3,96.3,0,0,1,24,136V88a8,8,0,0,1,8-8H208A40,40,0,0,1,248,120ZM200,96H40v40a80.27,80.27,0,0,0,45.12,72h69.76A80.27,80.27,0,0,0,200,136Zm32,24a24,24,0,0,0-16-22.62V136a95.78,95.78,0,0,1-1.2,15A24,24,0,0,0,232,128Z"></path></svg>

After

Width:  |  Height:  |  Size: 600 B

1
assets/dist/icons/database.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M128,24C74.17,24,32,48.6,32,80v96c0,31.4,42.17,56,96,56s96-24.6,96-56V80C224,48.6,181.83,24,128,24Zm80,104c0,9.62-7.88,19.43-21.61,26.92C170.93,163.35,150.19,168,128,168s-42.93-4.65-58.39-13.08C55.88,147.43,48,137.62,48,128V111.36c17.06,15,46.23,24.64,80,24.64s62.94-9.68,80-24.64ZM69.61,53.08C85.07,44.65,105.81,40,128,40s42.93,4.65,58.39,13.08C200.12,60.57,208,70.38,208,80s-7.88,19.43-21.61,26.92C170.93,115.35,150.19,120,128,120s-42.93-4.65-58.39-13.08C55.88,99.43,48,89.62,48,80S55.88,60.57,69.61,53.08ZM186.39,202.92C170.93,211.35,150.19,216,128,216s-42.93-4.65-58.39-13.08C55.88,195.43,48,185.62,48,176V159.36c17.06,15,46.23,24.64,80,24.64s62.94-9.68,80-24.64V176C208,185.62,200.12,195.43,186.39,202.92Z"></path></svg>

After

Width:  |  Height:  |  Size: 834 B

1
assets/dist/icons/envelope.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M224,48H32a8,8,0,0,0-8,8V192a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A8,8,0,0,0,224,48Zm-96,85.15L52.57,64H203.43ZM98.71,128,40,181.81V74.19Zm11.84,10.85,12,11.05a8,8,0,0,0,10.82,0l12-11.05,58,53.15H52.57ZM157.29,128,216,74.18V181.82Z"></path></svg>

After

Width:  |  Height:  |  Size: 360 B

1
assets/dist/icons/git-branch.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M232,64a32,32,0,1,0-40,31v17a8,8,0,0,1-8,8H96a23.84,23.84,0,0,0-8,1.38V95a32,32,0,1,0-16,0v66a32,32,0,1,0,16,0V144a8,8,0,0,1,8-8h88a24,24,0,0,0,24-24V95A32.06,32.06,0,0,0,232,64ZM64,64A16,16,0,1,1,80,80,16,16,0,0,1,64,64ZM96,192a16,16,0,1,1-16-16A16,16,0,0,1,96,192ZM200,80a16,16,0,1,1,16-16A16,16,0,0,1,200,80Z"></path></svg>

After

Width:  |  Height:  |  Size: 435 B

1
assets/dist/icons/images.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M216,40H72A16,16,0,0,0,56,56V72H40A16,16,0,0,0,24,88V200a16,16,0,0,0,16,16H184a16,16,0,0,0,16-16V184h16a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40ZM72,56H216v62.75l-10.07-10.06a16,16,0,0,0-22.63,0l-20,20-44-44a16,16,0,0,0-22.62,0L72,109.37ZM184,200H40V88H56v80a16,16,0,0,0,16,16H184Zm32-32H72V132l36-36,49.66,49.66a8,8,0,0,0,11.31,0L194.63,120,216,141.38V168ZM160,84a12,12,0,1,1,12,12A12,12,0,0,1,160,84Z"></path></svg>

After

Width:  |  Height:  |  Size: 525 B

1
assets/dist/icons/leaf.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M223.45,40.07a8,8,0,0,0-7.52-7.52C139.8,28.08,78.82,51,52.82,94a87.09,87.09,0,0,0-12.76,49c.57,15.92,5.21,32,13.79,47.85l-19.51,19.5a8,8,0,0,0,11.32,11.32l19.5-19.51C81,210.73,97.09,215.37,113,215.94q1.67.06,3.33.06A86.93,86.93,0,0,0,162,203.18C205,177.18,227.93,116.21,223.45,40.07ZM153.75,189.5c-22.75,13.78-49.68,14-76.71.77l88.63-88.62a8,8,0,0,0-11.32-11.32L65.73,179c-13.19-27-13-54,.77-76.71,22.09-36.47,74.6-56.44,141.31-54.06C210.2,114.89,190.22,167.41,153.75,189.5Z"></path></svg>

After

Width:  |  Height:  |  Size: 598 B

1
assets/dist/icons/lightbulb.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M176,232a8,8,0,0,1-8,8H88a8,8,0,0,1,0-16h80A8,8,0,0,1,176,232Zm40-128a87.55,87.55,0,0,1-33.64,69.21A16.24,16.24,0,0,0,176,186v6a16,16,0,0,1-16,16H96a16,16,0,0,1-16-16v-6a16,16,0,0,0-6.23-12.66A87.59,87.59,0,0,1,40,104.49C39.74,56.83,78.26,17.14,125.88,16A88,88,0,0,1,216,104Zm-16,0a72,72,0,0,0-73.74-72c-39,.92-70.47,33.39-70.26,72.39a71.65,71.65,0,0,0,27.64,56.3A32,32,0,0,1,96,186v6h64v-6a32.15,32.15,0,0,1,12.47-25.35A71.65,71.65,0,0,0,200,104Zm-16.11-9.34a57.6,57.6,0,0,0-46.56-46.55,8,8,0,0,0-2.66,15.78c16.57,2.79,30.63,16.85,33.44,33.45A8,8,0,0,0,176,104a9,9,0,0,0,1.35-.11A8,8,0,0,0,183.89,94.66Z"></path></svg>

After

Width:  |  Height:  |  Size: 728 B

1
assets/dist/icons/link.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M240,88.23a54.43,54.43,0,0,1-16,37L189.25,160a54.27,54.27,0,0,1-38.63,16h-.05A54.63,54.63,0,0,1,96,119.84a8,8,0,0,1,16,.45A38.62,38.62,0,0,0,150.58,160h0a38.39,38.39,0,0,0,27.31-11.31l34.75-34.75a38.63,38.63,0,0,0-54.63-54.63l-11,11A8,8,0,0,1,135.7,59l11-11A54.65,54.65,0,0,1,224,48,54.86,54.86,0,0,1,240,88.23ZM109,185.66l-11,11A38.41,38.41,0,0,1,70.6,208h0a38.63,38.63,0,0,1-27.29-65.94L78,107.31A38.63,38.63,0,0,1,144,135.71a8,8,0,0,0,16,.45A54.86,54.86,0,0,0,144,96a54.65,54.65,0,0,0-77.27,0L32,130.75A54.62,54.62,0,0,0,70.56,224h0a54.28,54.28,0,0,0,38.64-16l11-11A8,8,0,0,0,109,185.66Z"></path></svg>

After

Width:  |  Height:  |  Size: 714 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M229.66,218.34l-50.07-50.06a88.11,88.11,0,1,0-11.31,11.31l50.06,50.07a8,8,0,0,0,11.32-11.32ZM40,112a72,72,0,1,1,72,72A72.08,72.08,0,0,1,40,112Z"></path></svg>

After

Width:  |  Height:  |  Size: 267 B

1
assets/dist/icons/markdown-logo.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M232,48H24A16,16,0,0,0,8,64V192a16,16,0,0,0,16,16H232a16,16,0,0,0,16-16V64A16,16,0,0,0,232,48Zm0,144H24V64H232V192ZM128,104v48a8,8,0,0,1-16,0V123.31L93.66,141.66a8,8,0,0,1-11.32,0L64,123.31V152a8,8,0,0,1-16,0V104a8,8,0,0,1,13.66-5.66L88,124.69l26.34-26.35A8,8,0,0,1,128,104Zm77.66,18.34a8,8,0,0,1,0,11.32l-24,24a8,8,0,0,1-11.32,0l-24-24a8,8,0,0,1,11.32-11.32L168,132.69V104a8,8,0,0,1,16,0v28.69l10.34-10.35A8,8,0,0,1,205.66,122.34Z"></path></svg>

After

Width:  |  Height:  |  Size: 555 B

1
assets/dist/icons/mastodon-logo.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M184,32H72A40,40,0,0,0,32,72V192a40,40,0,0,0,40,40h88a8,8,0,0,0,0-16H72a24,24,0,0,1-24-24v-8H184a40,40,0,0,0,40-40V72A40,40,0,0,0,184,32Zm24,112a24,24,0,0,1-24,24H48V72A24,24,0,0,1,72,48H184a24,24,0,0,1,24,24Zm-24-40v32a8,8,0,0,1-16,0V104a16,16,0,0,0-32,0v32a8,8,0,0,1-16,0V104a16,16,0,0,0-32,0v32a8,8,0,0,1-16,0V104a32,32,0,0,1,56-21.13A32,32,0,0,1,184,104Z"></path></svg>

After

Width:  |  Height:  |  Size: 482 B

1
assets/dist/icons/matrix-logo.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M72,216a8,8,0,0,1-8,8H40a8,8,0,0,1-8-8V40a8,8,0,0,1,8-8H64a8,8,0,0,1,0,16H48V208H64A8,8,0,0,1,72,216ZM216,32H192a8,8,0,0,0,0,16h16V208H192a8,8,0,0,0,0,16h24a8,8,0,0,0,8-8V40A8,8,0,0,0,216,32Zm-32,88a32,32,0,0,0-56-21.13,31.93,31.93,0,0,0-40.71-6.15A8,8,0,0,0,72,96v64a8,8,0,0,0,16,0V120a16,16,0,0,1,32,0v40a8,8,0,0,0,16,0V120a16,16,0,0,1,32,0v40a8,8,0,0,0,16,0Z"></path></svg>

After

Width:  |  Height:  |  Size: 485 B

1
assets/dist/icons/network.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M232,112H136V88h8a16,16,0,0,0,16-16V40a16,16,0,0,0-16-16H112A16,16,0,0,0,96,40V72a16,16,0,0,0,16,16h8v24H24a8,8,0,0,0,0,16H56v32H48a16,16,0,0,0-16,16v32a16,16,0,0,0,16,16H80a16,16,0,0,0,16-16V176a16,16,0,0,0-16-16H72V128H184v32h-8a16,16,0,0,0-16,16v32a16,16,0,0,0,16,16h32a16,16,0,0,0,16-16V176a16,16,0,0,0-16-16h-8V128h32a8,8,0,0,0,0-16ZM112,40h32V72H112ZM80,208H48V176H80Zm128,0H176V176h32Z"></path></svg>

After

Width:  |  Height:  |  Size: 516 B

1
assets/dist/icons/pencil-ruler.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M208,32H160a16,16,0,0,0-16,16V208a16,16,0,0,0,16,16h48a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32Zm0,176H160V176h24a8,8,0,0,0,0-16H160V136h24a8,8,0,0,0,0-16H160V96h24a8,8,0,0,0,0-16H160V48h48V208ZM77.66,26.34a8,8,0,0,0-11.32,0l-32,32A8,8,0,0,0,32,64V208a16,16,0,0,0,16,16H96a16,16,0,0,0,16-16V64a8,8,0,0,0-2.34-5.66ZM48,176V80H64v96ZM80,80H96v96H80ZM72,43.31,92.69,64H51.31ZM48,208V192H96v16Z"></path></svg>

After

Width:  |  Height:  |  Size: 513 B

1
assets/dist/icons/video.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M164.44,105.34l-48-32A8,8,0,0,0,104,80v64a8,8,0,0,0,12.44,6.66l48-32a8,8,0,0,0,0-13.32ZM120,129.05V95l25.58,17ZM216,40H40A16,16,0,0,0,24,56V168a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40Zm0,128H40V56H216V168Zm16,40a8,8,0,0,1-8,8H32a8,8,0,0,1,0-16H224A8,8,0,0,1,232,208Z"></path></svg>

After

Width:  |  Height:  |  Size: 412 B

1
assets/dist/icons/webcam.svg vendored Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M168,104a40,40,0,1,0-40,40A40,40,0,0,0,168,104Zm-64,0a24,24,0,1,1,24,24A24,24,0,0,1,104,104Zm120,96H136V183.6a80,80,0,1,0-16,0V200H32a8,8,0,0,0,0,16H224a8,8,0,0,0,0-16ZM64,104a64,64,0,1,1,64,64A64.07,64.07,0,0,1,64,104Z"></path></svg>

After

Width:  |  Height:  |  Size: 343 B

33
data/finances.json Normal file
View file

@ -0,0 +1,33 @@
{
"2024": {
"4": {
"Membership Fees": {
"EUR": 365
},
"Donations": {},
"Server Costs": {
"EUR": -216.57
},
"Domain Names": {},
"Operating Expenses": {
"EUR": -36.10
},
"Conversions": {}
},
"5": {
"Membership Fees": {
"EUR": 390
},
"Donations": {
"BTC": 0.000434,
"XMR": 0.447661805527
},
"Server Costs": {
"EUR": -430.04
},
"Domain Names": {},
"Operating Expenses": {},
"Conversions": {}
}
}
}

View file

@ -12,6 +12,7 @@
"url": "https://element.private.coffee"
}
],
"icon": "matrix-logo",
"exclude_from_index": false,
"exclude_from_simple": true
},
@ -27,6 +28,7 @@
"url": "https://cryptpad.private.coffee"
}
],
"icon": "article-ny-times",
"exclude_from_index": false,
"exclude_from_simple": false
},
@ -42,6 +44,7 @@
"url": "https://piped.private.coffee"
}
],
"icon": "video",
"exclude_from_index": false,
"exclude_from_simple": false
},
@ -57,6 +60,7 @@
"url": "https://myip.coffee"
}
],
"icon": "network",
"exclude_from_index": false,
"exclude_from_simple": false
},
@ -72,6 +76,7 @@
"url": "https://invidious.private.coffee"
}
],
"icon": "video",
"exclude_from_index": false,
"exclude_from_simple": false
},
@ -91,6 +96,7 @@
"url": "https://skrt.social"
}
],
"icon": "mastodon-logo",
"exclude_from_index": false,
"exclude_from_simple": false
},
@ -106,6 +112,7 @@
"url": "https://git.private.coffee"
}
],
"icon": "git-branch",
"exclude_from_index": false,
"exclude_from_simple": false
},
@ -121,6 +128,7 @@
"url": "https://bbb.private.coffee"
}
],
"icon": "webcam",
"exclude_from_index": false,
"exclude_from_simple": false
},
@ -136,6 +144,7 @@
"url": "https://hedgedoc.private.coffee"
}
],
"icon": "markdown-logo",
"exclude_from_index": false,
"exclude_from_simple": false
},
@ -151,6 +160,7 @@
"url": "https://gothub.private.coffee"
}
],
"icon": "git-branch",
"exclude_from_index": false,
"exclude_from_simple": false
},
@ -166,6 +176,7 @@
"url": "https://redlib.private.coffee"
}
],
"icon": "chats",
"exclude_from_index": false,
"exclude_from_simple": false
},
@ -181,6 +192,7 @@
"url": "https://alltube.private.coffee"
}
],
"icon": "video",
"exclude_from_index": false,
"exclude_from_simple": false
},
@ -196,6 +208,7 @@
"url": "https://structables.private.coffee"
}
],
"icon": "lightbulb",
"exclude_from_index": false,
"exclude_from_simple": false
},
@ -211,6 +224,7 @@
"url": "https://nocodb.private.coffee"
}
],
"icon": "database",
"exclude_from_index": true,
"exclude_from_simple": true
},
@ -226,6 +240,7 @@
"url": "https://penpot.private.coffee"
}
],
"icon": "pencil-ruler",
"exclude_from_index": false,
"exclude_from_simple": false
},
@ -241,6 +256,7 @@
"url": "https://pcof.fi"
}
],
"icon": "link",
"exclude_from_index": false,
"exclude_from_simple": false
},
@ -256,6 +272,7 @@
"url": "https://rallly.private.coffee"
}
],
"icon": "calendar",
"exclude_from_index": true,
"exclude_from_simple": true
},
@ -271,6 +288,7 @@
"url": "https://librey.private.coffee"
}
],
"icon": "magnifying-glass",
"exclude_from_index": false,
"exclude_from_simple": false
},
@ -286,6 +304,7 @@
"url": "https://overleaf.private.coffee"
}
],
"icon": "leaf",
"exclude_from_index": false,
"exclude_from_simple": false
},
@ -301,44 +320,9 @@
"url": "https://binternet.private.coffee"
}
],
"icon": "images",
"exclude_from_index": false,
"exclude_from_simple": false
},
{
"name": "Nitter",
"url": "https://nitter.private.coffee",
"short_description": "Nitter is a privacy-friendly alternative front-end to Twitter.",
"long_description": "Nitter is a privacy-friendly alternative front-end to Twitter. It allows you to browse Twitter without being tracked.",
"status": "NOK",
"links": [
{
"name": "Go to Nitter",
"url": "https://nitter.private.coffee",
"alternatives": [
{
"name": "Tor (.onion)",
"url": "http://nitter.coffee2m3bjsrrqqycx6ghkxrnejl2q6nl7pjw2j4clchjj6uk5zozad.onion/"
}
]
}
],
"exclude_from_index": true,
"exclude_from_simple": true
},
{
"name": "Proxigram",
"url": "https://proxigram.private.coffee",
"short_description": "Proxigram is a privacy-friendly alternative front-end to Instagram.",
"long_description": "Proxigram is a privacy-friendly alternative front-end to Instagram. It allows you to browse Instagram without being tracked.",
"status": "NOK",
"links": [
{
"name": "Go to Proxigram",
"url": "https://proxigram.private.coffee"
}
],
"exclude_from_index": true,
"exclude_from_simple": true
}
]
}

201
helpers/finances.py Normal file
View file

@ -0,0 +1,201 @@
from decimal import Decimal
def get_latest_month(data):
years = sorted(data.keys())
latest_year = years[-1]
months = sorted(data[latest_year].keys())
latest_month = months[-1]
return int(latest_month), int(latest_year)
def get_transparency_data(data, year=None, month=None):
if year is None:
year = max(data.keys())
if month is None:
month = max(data[year].keys())
assert year in data, f"Year {year} not found in data"
assert month in data[year], f"Month {month}-{year} not found in data"
# Initialize balances
balances = {}
incomes = {}
expenses = {}
start_balance = {}
end_balance = {}
for y in sorted(data.keys()):
if int(y) > int(year):
break
for m in sorted(data[y].keys()):
if int(y) == int(year) and int(m) > int(month):
break
# If the month is the one we are interested in, capture the start balance
if int(y) == int(year) and int(m) == int(month):
start_balance = {k: Decimal(v) for k, v in balances.items()}
for category in data[y][m]:
for currency, amount in data[y][m][category].items():
if currency not in balances:
balances[currency] = Decimal(0)
balances[currency] += Decimal(str(amount))
# Track incomes and expenses
if int(y) == int(year) and int(m) == int(month):
if Decimal(str(amount)) > 0:
if category not in incomes:
incomes[category] = {}
if currency not in incomes[category]:
incomes[category][currency] = Decimal(0)
incomes[category][currency] += Decimal(str(amount))
else:
if category not in expenses:
expenses[category] = {}
if currency not in expenses[category]:
expenses[category][currency] = Decimal(0)
expenses[category][currency] += Decimal(str(amount))
# If the month is the one we are interested in, capture the end balance
if int(y) == int(year) and int(m) == int(month):
end_balance = {k: Decimal(v) for k, v in balances.items()}
# Calculate accumulated sums of incomes and expenses
accumulated_incomes = {
currency: sum(incomes[cat].get(currency, Decimal(0)) for cat in incomes)
for currency in balances
}
accumulated_expenses = {
currency: sum(expenses[cat].get(currency, Decimal(0)) for cat in expenses)
for currency in balances
}
return {
"start_balance": start_balance,
"end_balance": end_balance,
"incomes": incomes,
"expenses": expenses,
"accumulated_incomes": accumulated_incomes,
"accumulated_expenses": accumulated_expenses,
}
def generate_transparency_table(result, currencies=None):
def extract_currencies(data):
return ["EUR"] + (
list(
set(
list(data["start_balance"].keys())
+ list(data["end_balance"].keys())
+ list(data["accumulated_incomes"].keys())
+ list(data["accumulated_expenses"].keys())
)
- {"EUR"}
)
)
def format_currency(value, currency):
if currency == "EUR":
return f"{value:,.2f}"
elif currency in ["BTC", "ETH", "XMR"]:
return f"{value:,.9f} {currency}"
else:
return f"{value} {currency}"
def format_value(value, currency):
if value == 0:
return f"{format_currency(value, currency)}"
elif value > 0:
return f"+ {format_currency(value, currency)}"
else:
return f"- {format_currency(abs(value), currency)}"
html = """
<table class="table table-bordered table-transparency">
<thead class="table-light">
<tr>
<th scope="col">Category</th>
"""
if currencies is None:
currencies = extract_currencies(result)
# Add currency headers
for currency in currencies:
if currency == "EUR":
html += '<th class="currency-col" scope="col">Euros (€)</th>'
elif currency == "BTC":
html += '<th class="currency-col" scope="col">Bitcoin (BTC)</th>'
elif currency == "ETH":
html += '<th class="currency-col" scope="col">Ethereum (ETH)</th>'
elif currency == "XMR":
html += '<th class="currency-col" scope="col">Monero (XMR)</th>'
else:
html += f'<th class="currency-col" scope="col">{currency}</th>'
html += """
</tr>
</thead>
<tbody>
"""
# Add start balance row
html += "<tr><td>Account Balance (start of month)</td>"
for currency in currencies:
value = result["start_balance"].get(currency, Decimal(0))
html += f"<td>{format_value(value, currency)}</td>"
html += "</tr>"
# Add income rows
for category, transactions in result["incomes"].items():
html += f"<tr><td>{category}</td>"
for currency in currencies:
value = transactions.get(currency, "")
if value != "":
html += f"<td>{format_value(value, currency)}</td>"
else:
html += "<td></td>"
html += "</tr>"
# Add expense rows
for category, transactions in result["expenses"].items():
html += f"<tr><td>{category}</td>"
for currency in currencies:
value = transactions.get(currency, "")
if value != "":
html += f"<td>{format_value(value, currency)}</td>"
else:
html += "<td></td>"
html += "</tr>"
# Add total income row
html += '<tr class="table-secondary"><td><b>Total Income</b></td>'
for currency in currencies:
value = result["accumulated_incomes"].get(currency, Decimal(0))
html += f"<td><b>{format_value(value, currency)}</b></td>"
html += "</tr>"
# Add total expenses row
html += '<tr class="table-secondary"><td><b>Total Expenses</b></td>'
for currency in currencies:
value = result["accumulated_expenses"].get(currency, Decimal(0))
html += f"<td><b>{format_value(value, currency)}</b></td>"
html += "</tr>"
# Add end balance row
html += '<tr class="table-secondary"><td><b>Account Balance (end of month)</b></td>'
for currency in currencies:
value = result["end_balance"].get(currency, Decimal(0))
html += f"<td><b>{format_value(value, currency)}</b></td>"
html += "</tr>"
html += """
</tbody>
</table>
"""
return html

77
main.py
View file

@ -3,9 +3,17 @@ from jinja2 import TemplateNotFound
import json
import pathlib
import os
import datetime
from argparse import ArgumentParser
from helpers.finances import (
generate_transparency_table,
get_transparency_data,
get_latest_month,
)
app = Flask(__name__)
@ -18,18 +26,79 @@ def send_assets(path):
@app.route("/<path:path>.html")
def catch_all(path):
try:
services = json.loads(
(pathlib.Path(__file__).parent / "services.json").read_text()
)
return render_template(f"{path}.html", services=services)
kwargs = {}
if app.development_mode:
kwargs.update(
{
"warning": render_template("prod-warning.html"),
}
)
if path in (
"index",
"simple",
):
services = json.loads(
(pathlib.Path(__file__).parent / "data" / "services.json").read_text()
)
kwargs.update(
{
"services": services,
}
)
if path == "membership":
finances = json.loads(
(pathlib.Path(__file__).parent / "data" / "finances.json").read_text()
)
finances_month, finances_year = get_latest_month(finances)
finances_period = datetime.date(finances_year, finances_month, 1)
finances_period_str = finances_period.strftime("%B %Y")
finances_table = generate_transparency_table(
get_transparency_data(finances)
)
kwargs.update(
{
"finances": finances_table,
"finances_period": finances_period_str,
}
)
return render_template(f"{path}.html", **kwargs)
except TemplateNotFound:
return "404 Not Found", 404
app.development_mode = False
if os.environ.get("PRIVATECOFFEE_DEV"):
app.development_mode = True
def icon(icon_name):
file = send_from_directory("assets", f"dist/icons/{icon_name}.svg")
try:
file_content = file.response.file.read().decode("utf-8")
except AttributeError:
file_content = file.response.read().decode("utf-8")
return file_content
app.add_template_filter(icon)
if __name__ == "__main__":
parser = ArgumentParser(description="Run the private.coffee web server.")
parser.add_argument("--port", type=int, default=9810)
parser.add_argument("--debug", action="store_true")
parser.add_argument("--dev", action="store_true")
args = parser.parse_args()
app.development_mode = args.dev or app.development_mode
app.run(port=args.port, debug=args.debug)

View file

@ -51,6 +51,7 @@
</ul><a class="btn btn-primary shadow navbar-btn" role="button" href="/membership.html">JOIN &amp; REBEL</a>
</div>
</nav>
{% if warning %}{{ warning|safe }}{% endif %}
{% block content %}{% endblock %}
<footer class="bg-primary-gradient">
<div class="container py-4 py-lg-5">
@ -74,26 +75,12 @@
<div class="fw-bold d-flex align-items-center mb-2">
<span
class="bs-icon-sm bs-icon-circle bs-icon-primary d-flex justify-content-center align-items-center bs-icon me-2"
><svg
xmlns="http://www.w3.org/2000/svg"
width="1em"
height="1em"
fill="currentColor"
viewBox="0 0 16 16"
class="bi bi-bezier"
>
<path
fill-rule="evenodd"
d="M0 10.5A1.5 1.5 0 0 1 1.5 9h1A1.5 1.5 0 0 1 4 10.5v1A1.5 1.5 0 0 1 2.5 13h-1A1.5 1.5 0 0 1 0 11.5zm1.5-.5a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5zm10.5.5A1.5 1.5 0 0 1 13.5 9h1a1.5 1.5 0 0 1 1.5 1.5v1a1.5 1.5 0 0 1-1.5 1.5h-1a1.5 1.5 0 0 1-1.5-1.5zm1.5-.5a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5zM6 4.5A1.5 1.5 0 0 1 7.5 3h1A1.5 1.5 0 0 1 10 4.5v1A1.5 1.5 0 0 1 8.5 7h-1A1.5 1.5 0 0 1 6 5.5zM7.5 4a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5z"
></path>
<path
d="M6 4.5H1.866a1 1 0 1 0 0 1h2.668A6.517 6.517 0 0 0 1.814 9H2.5c.123 0 .244.015.358.043a5.517 5.517 0 0 1 3.185-3.185A1.503 1.503 0 0 1 6 5.5zm3.957 1.358A1.5 1.5 0 0 0 10 5.5v-1h4.134a1 1 0 1 1 0 1h-2.668a6.517 6.517 0 0 1 2.72 3.5H13.5c-.123 0-.243.015-.358.043a5.517 5.517 0 0 0-3.185-3.185z"
></path></svg></span
>{{ "coffee" | icon | safe }}</span
><span>Private.coffee</span>
</div>
<p class="text-muted">
Private.coffee is a collection of services that respect your
privacy.
Private.coffee is a privacy-focused non-profit association, dedicated
to supporting privacy and digital sovereignty.
</p>
</div>
</div>

View file

@ -29,10 +29,9 @@
<div class="col mb-5">
<div class="card shadow-sm">
<div class="card-body px-4 py-5 px-md-5">
<div class="bs-icon-lg d-flex justify-content-center align-items-center mb-3 bs-icon" style="top: 1rem;right: 1rem;position: absolute;"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" viewBox="0 0 16 16" class="bi bi-chat-text text-primary">
<path d="M2.678 11.894a1 1 0 0 1 .287.801 10.97 10.97 0 0 1-.398 2c1.395-.323 2.247-.697 2.634-.893a1 1 0 0 1 .71-.074A8.06 8.06 0 0 0 8 14c3.996 0 7-2.807 7-6 0-3.192-3.004-6-7-6S1 4.808 1 8c0 1.468.617 2.83 1.678 3.894m-.493 3.905a21.682 21.682 0 0 1-.713.129c-.2.032-.352-.176-.273-.362a9.68 9.68 0 0 0 .244-.637l.003-.01c.248-.72.45-1.548.524-2.319C.743 11.37 0 9.76 0 8c0-3.866 3.582-7 8-7s8 3.134 8 7-3.582 7-8 7a9.06 9.06 0 0 1-2.347-.306c-.52.263-1.639.742-3.468 1.105z"></path>
<path d="M4 5.5a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5M4 8a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7A.5.5 0 0 1 4 8m0 2.5a.5.5 0 0 1 .5-.5h4a.5.5 0 0 1 0 1h-4a.5.5 0 0 1-.5-.5"></path>
</svg></div>
<div class="bs-icon-lg d-flex justify-content-center align-items-center mb-3 bs-icon" style="top: 1rem;right: 1rem;position: absolute;">
{% if service.icon %}{{ service.icon | icon | safe }}{% endif %}
</div>
<h5 class="fw-bold card-title">{{ service.name }}</h5>
<p class="text-muted card-text mb-4">{{ service.long_description }}</p>
{% for link in service.links %}
@ -92,9 +91,7 @@
<div class="col-md-4 col-xl-4 d-flex justify-content-center justify-content-xl-start">
<div class="d-flex flex-wrap flex-md-column justify-content-md-start align-items-md-start h-100">
<div class="d-flex align-items-center p-3">
<div class="bs-icon-md bs-icon-circle bs-icon-primary shadow d-flex flex-shrink-0 justify-content-center align-items-center d-inline-block bs-icon bs-icon-md"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" viewBox="0 0 16 16" class="bi bi-envelope">
<path d="M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1zm13 2.383-4.708 2.825L15 11.105zm-.034 6.876-5.64-3.471L8 9.583l-1.326-.795-5.64 3.47A1 1 0 0 0 2 13h12a1 1 0 0 0 .966-.741M1 11.105l4.708-2.897L1 5.383z"></path>
</svg></div>
<div class="bs-icon-md bs-icon-circle bs-icon-primary shadow d-flex flex-shrink-0 justify-content-center align-items-center d-inline-block bs-icon bs-icon-md">{{ "envelope" | icon | safe }}</div>
<div class="px-2">
<h6 class="fw-bold mb-0">Email</h6>
<p class="text-muted mb-0">support@private.coffee</p>
@ -107,9 +104,7 @@
<div class="col-md-4 col-xl-4 d-flex justify-content-center justify-content-xl-start">
<div class="d-flex flex-wrap flex-md-column justify-content-md-start align-items-md-start h-100">
<div class="d-flex align-items-center p-3">
<div class="bs-icon-md bs-icon-circle bs-icon-primary shadow d-flex flex-shrink-0 justify-content-center align-items-center d-inline-block bs-icon bs-icon-md"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" viewBox="0 0 16 16" class="bi bi-envelope">
<path d="M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1zm13 2.383-4.708 2.825L15 11.105zm-.034 6.876-5.64-3.471L8 9.583l-1.326-.795-5.64 3.47A1 1 0 0 0 2 13h12a1 1 0 0 0 .966-.741M1 11.105l4.708-2.897L1 5.383z"></path>
</svg></div>
<div class="bs-icon-md bs-icon-circle bs-icon-primary shadow d-flex flex-shrink-0 justify-content-center align-items-center d-inline-block bs-icon bs-icon-md">{{ "matrix-logo" | icon | safe }}</div>
<div class="px-2">
<h6 class="fw-bold mb-0">Matrix</h6>
<p class="text-muted mb-0"><a href="https://matrix.pcof.fi/#/#private.coffee:private.coffee">#private.coffee:private.coffee</a></p>

View file

@ -1,7 +1,7 @@
{% extends "base.html" %}
{% block title %}Legal Notice{% endblock %}
{% block content %}
<section class="bg-primary-gradient">
<section>
<div class="container py-5">
<div class="row align-items-center">
<div class="col">
@ -20,7 +20,6 @@
</div>
<div class="container">
<h1>Legal Notice</h1>
<p>This is a legal notice for the website private.coffee</p>
<p>The website private.coffee is run by the following entity:</p>
<address>

View file

@ -1,56 +1,116 @@
{% extends "base.html" %}
{% block title %}Membership / Donations{% endblock %}
{% extends "base.html" %} {% block title %}Membership / Donations{% endblock %}
{% block content %}
<div class="container">
<h1>Membership/Donations</h1>
<p>
private.coffee is a non-profit organization dedicated to supporting privacy
and digital sovereignty. We fund our server infrastructure through donations
and membership fees.
</p>
<p>
Membership fees help cover the costs of server infrastructure, domain names,
and other operating expenses. Likewise, all donations contribute towards
these ongoing costs.
</p>
<p>
Supporting the private.coffee project is possible by joining our association
or by making a direct donation.
</p>
<div class="donation-details">
<p><b>Donations:</b></p>
<p>
Bank private.coffee - Verein zur Förderung von Privatsphäre und digitaler
Souveränität
</p>
<p>IBAN: AT35 2081 5000 4554 0812</p>
<p>BIC: STSPAT2GXXX</p>
<p>
For donation listing preferences, please specify in the note to payee.
<div class="container my-5">
<div class="text-center mb-5">
<h1 class="special-header fancy-text-primary">Membership/Donations</h1>
<p class="lead">
Private.coffee is a non-profit organization dedicated to supporting
privacy and digital sovereignty. We fund our activities and running
infrastructure costs through membership fees. Donations allow us to expand
our services and reach more people.
</p>
</div>
<div class="zvr-number">
<p>Central Register of Associations (ZVR) Number: 1758485319</p>
<p>
Our statutes can be found in our Git
<a href="https://git.private.coffee/PrivateCoffee/statuten"
>in German (legally binding)</a
>
and
<a
href="https://git.private.coffee/PrivateCoffee/Statuten/src/branch/english"
>in English</a
>.
</p>
<p class="contact-info">
Interested in joining the association? Reach out via
<a href="mailto:support@private.coffee">email</a> or
<a href="https://matrix.private.cf/#/#private.coffee:private.coffee"
>Matrix</a
>
for more information.
</p>
<div class="row">
<div class="col-md-4 mb-4">
<div class="card shadow-sm">
<div class="card-body">
<h5 class="card-title">Membership</h5>
<p class="card-text">
Membership fees help cover the costs of our day-to-day activities,
server infrastructure, domain names, and other running operating
expenses. This allows us to provide services to our members and the
public.
</p>
<p class="card-text">
If you're interested in joining our association, get in touch with
us for more information.
</p>
</div>
</div>
</div>
<div class="col-md-4 mb-4">
<div class="card shadow-sm">
<div class="card-body">
<h5 class="card-title">Bank Donations</h5>
<p class="card-text">
Even if you're not a member, you can still support us by making a
direct donation to our bank account. Your donation will be used to
fund our activities and expand our services.
</p>
<p class="card-text"><b>Account holder:</b> Private.coffee</p>
<p class="card-text"><b>IBAN:</b> AT35 2081 5000 4554 0812</p>
<p class="card-text"><b>BIC:</b> STSPAT2GXXX</p>
</div>
</div>
</div>
<div class="col-md-4 mb-4">
<div class="card shadow-sm">
<div class="card-body">
<h5 class="card-title">Crypto Donations</h5>
<p class="card-text">
While our expenses are generally in fiat currency, we accept
donations in cryptocurrencies, too.
</p>
<p class="card-text">
<b>Bitcoin (BTC):</b>
<code>bc1qnu7r5sed4afacfpgx5za8hsyhaj4rs45dpm26k</code>
</p>
<p class="card-text">
<b>Monero (XMR):</b>
<code
>487Ny4iBk2pKGJwjyYrumFD8xFmrS6jCSXNA8e5EvVJ49GyS54CRDVz514MBnXgNT1EioKYiagHs33sLzUAFj8i3Pwg3AMS</code
>
</p>
<p class="card-text">
<b>Ethereum (ETH):</b> <code>Coming soon&trade;</code>
</p>
<p class="card-text">
If your client supports OpenAlias, you can just send your donation
to <code>private.coffee</code>.
</p>
</div>
</div>
</div>
</div>
<div class="card shadow-sm mt-4">
<div class="card-body">
<h5 class="card-title">Transparency Report for {{ finances_period }}</h5>
<p class="card-text">
We believe in transparency and accountability. Below is a summary of our
income and expenses for the last month, so you can see how your
donations are being used.
</p>
<div class="table-responsive">{{ finances|safe }}</div>
</div>
</div>
<div class="card shadow-sm mt-4">
<div class="card-body">
<h5>Central Register of Associations (ZVR) Number: 1758485319</h5>
<p>
Our statutes can be found in our Git
<a href="https://git.private.coffee/PrivateCoffee/statuten"
>in German (legally binding)</a
>
and
<a
href="https://git.private.coffee/PrivateCoffee/Statuten/src/branch/english"
>in English</a
>.
</p>
<p class="contact-info" id="contact-info">
Interested in joining the association? Reach out via
<a href="mailto:support@private.coffee">email</a> or
<a href="https://matrix.pcof.fi/#/#private.coffee:private.coffee"
>Matrix</a
>
for more information.
</p>
</div>
</div>
</div>
{% endblock %}

View file

@ -1,167 +1,187 @@
{% extends "base.html" %}
{% block title %}Privacy Policy{% endblock %}
{% extends "base.html" %} {% block title %}Privacy Policy{% endblock %}
{% block content %}
<div class="container">
<h1>Privacy Policy</h1>
<p>
This is the privacy policy for the website private.coffee. It describes how
we collect and use your personal data.
</p>
<p>
This privacy policy is effective as of 2024-04-26. It may be updated from
time to time, so please check back regularly.
</p>
<p>
If you have any questions about this privacy policy, please contact us at
<a href="mailto:support@private.coffee">support@private.coffee</a>.
</p>
<h2>Who are we?</h2>
<p>The data controller for private.coffee is:</p>
<address>
Private.coffee &dash; Verein zur Förderung von Privatsphäre und digitaler
Souver&auml;nit&auml;t<br />
c/o Klaus-Uwe Mitterer<br />
Gartengasse 22/7/3<br />
8010 Graz<br />
Austria<br />
</address>
<p>Central Register of Associations (ZVR) Number: 1758485319</p>
<p>
Email:
<a href="mailto:support@private.coffee">support@private.coffee</a>
</p>
<h2>What data do we collect?</h2>
<p>We collect the following data from you:</p>
<ul>
<li>
Your IP address, which is automatically collected by our web server for
some of our services.
</li>
<li>
Any data you provide to us, such as your email address, when you create an
account on one of our services.
</li>
<li>
Usage data that is collected automatically by our services, such as the
time you last logged in, or the number of times you have logged in, as
well as any content you create using our services.
</li>
<li>
Any information, including personal data and payment information, that you
provide to us when you make a donation or join our association.
</li>
</ul>
<h2>How do we use your data?</h2>
<p>
We use your data to provide you with the services you requested. This
includes:
</p>
<ul>
<li>Communication between our web server and your browser</li>
<li>Storing your preferences or your created content</li>
<li>Detection of abuse or resource exhaustion on our servers</li>
<li>Providing support to you</li>
<li>Processing donations and memberships</li>
</ul>
<p>All of those are what is called "legitimate interests" in legal speak.</p>
<p>
We do not use your data for any other purposes, including marketing,
advertising, or tracking, we do not share your data with third parties
(unless required by law), we do not use your data to create profiles or make
automated decisions, and we do not cross-reference your data between
different services or any other sources.
</p>
<h2>Where do we store your data?</h2>
<p>
We store your data on our web servers, which are located in Austria. We also
use servers in Germany, but those are not public-facing and do not store or
process any personal data.
</p>
<h2>How long do we store your data?</h2>
<ul>
<li>
IP addresses collected by our web server are stored for up to 48 hours.
After that, the log files that contain them are deleted automatically.
</li>
<li>
Data associated with an account you have on one of our services is stored
for as long as you have an account on that service. If you delete your
account, your data will be deleted automatically. The service will have a
dedicated privacy policy, please consult that if you have any specific
questions.
</li>
<li>
If you send a support request to us, we will store your email address and
any other data you provide to us for up to 30 days in our support system.
After that, the data will be deleted automatically.
</li>
<li>
Data associated with a donation is stored for as long as required by law,
which is currently 7 years in Austria. After that, the data will be
deleted.
</li>
<li>
Data associated with a membership is stored for as long as you are a
member of our association. If you leave the association, your data will be
deleted automatically. This does not apply to data that is required by law
to be stored for a longer period of time, such as financial records, which
are stored for 7 years regardless of your membership status.
</li>
</ul>
<h2>What are your data protection rights?</h2>
<p>You have the following data protection rights:</p>
<ul>
<li>You have the right to request access to your personal data.</li>
<li>You have the right to request correction of your personal data.</li>
<li>You have the right to request erasure of your personal data.</li>
<li>
You have the right to request restriction of processing of your personal
data.
</li>
<li>You have the right to object to processing of your personal data.</li>
<li>You have the right to request transfer of your personal data.</li>
</ul>
<p>If you make a request, we have one month to respond to you.</p>
<p>
If you would like to exercise any of these rights, please contact us at
<a href="mailto:support@private.coffee">support@private.coffee</a>.
</p>
<p>
Your privacy is important to us - after all, that's why we're all here - and
we will do our best to respond to your request as soon as possible. Please
note that we may need to verify your identity before we can respond to your
request - we will not share your data with anyone else.
</p>
<p>
If you are not satisfied with our response, or believe that we are
processing your data in a way that is not compliant with the law, you have
the right to lodge a complaint with the supervisory authority in your
country. In Austria, this is the Austrian Data Protection Authority (<a
href="https://www.dsb.gv.at/"
>https://www.dsb.gv.at/</a
>). However, we like to think of ourselves as nice people and will try to
help you out directly, and are always open to suggestions for improvement,
so please do get in touch with us if you have any questions or concerns.
</p>
<h2>What are cookies?</h2>
<p>
Cookies are small text files that are placed on your computer or mobile
device when you visit a website. They are widely used to make websites work,
or work more efficiently, as well as to provide information to the owners of
the site. Cookies are stored on your device, and can be accessed by the
website that created them. They are not harmful to your device, and do not
directly contain any personal data, but are used by our services to identify
you between multiple visits.
</p>
<p>
Cookies are used on some of our services to provide you with a better
experience. For example, we use cookies to remember your preferences and
settings - for example, to allow you to login to our services - and to
provide you with a better experience when browsing our services. We do not
use cookies to track your activity, either on our services or on other
websites. In legal/technical terms, we exclusively use "strictly necessary"
first-party cookies, which is also why you don't see any cookie banners on
our website.
</p>
<div class="text-center mb-5">
<h1 class="special-header fancy-text-primary">Privacy Policy</h1>
<p class="lead">
This is the privacy policy for the website private.coffee. It describes
how we collect and use your personal data.
</p>
</div>
<div class="section">
<p>
This privacy policy is effective as of 2024-04-26. It may be updated from
time to time, so please check back regularly.
</p>
<p>
If you have any questions about this privacy policy, please contact us at
<a href="mailto:support@private.coffee">support@private.coffee</a>.
</p>
</div>
<div class="section">
<h2>Who are we?</h2>
<p>The data controller for private.coffee is:</p>
<address>
Private.coffee &dash; Verein zur Förderung von Privatsphäre und digitaler
Souver&auml;nit&auml;t<br />
c/o Klaus-Uwe Mitterer<br />
Gartengasse 22/7/3<br />
8010 Graz<br />
Austria<br />
</address>
<p>Central Register of Associations (ZVR) Number: 1758485319</p>
<p>
Email:
<a href="mailto:support@private.coffee">support@private.coffee</a>
</p>
</div>
<div class="section">
<h2>What data do we collect?</h2>
<p>We collect the following data from you:</p>
<ul>
<li>
Your IP address, which is automatically collected by our web server for
some of our services.
</li>
<li>
Any data you provide to us, such as your email address, when you create
an account on one of our services.
</li>
<li>
Usage data that is collected automatically by our services, such as the
time you last logged in, or the number of times you have logged in, as
well as any content you create using our services.
</li>
<li>
Any information, including personal data and payment information, that
you provide to us when you make a donation or join our association.
</li>
</ul>
</div>
<div class="section">
<h2>How do we use your data?</h2>
<p>
We use your data to provide you with the services you requested. This
includes:
</p>
<ul>
<li>Communication between our web server and your browser</li>
<li>Storing your preferences or your created content</li>
<li>Detection of abuse or resource exhaustion on our servers</li>
<li>Providing support to you</li>
<li>Processing donations and memberships</li>
</ul>
<p>
All of those are what is called "legitimate interests" in legal speak.
</p>
<p>
We do not use your data for any other purposes, including marketing,
advertising, or tracking, we do not share your data with third parties
(unless required by law), we do not use your data to create profiles or
make automated decisions, and we do not cross-reference your data between
different services or any other sources.
</p>
</div>
<div class="section">
<h2>Where do we store your data?</h2>
<p>
We store your data on our web servers, which are located in Austria. We
also use servers in Germany, but those are not public-facing and do not
store or process any personal data.
</p>
</div>
<div class="section">
<h2>How long do we store your data?</h2>
<ul>
<li>
IP addresses collected by our web server are stored for up to 48 hours.
After that, the log files that contain them are deleted automatically.
</li>
<li>
Data associated with an account you have on one of our services is
stored for as long as you have an account on that service. If you delete
your account, your data will be deleted automatically. The service will
have a dedicated privacy policy, please consult that if you have any
specific questions.
</li>
<li>
If you send a support request to us, we will store your email address
and any other data you provide to us for up to 30 days in our support
system. After that, the data will be deleted automatically.
</li>
<li>
Data associated with a donation is stored for as long as required by
law, which is currently 7 years in Austria. After that, the data will be
deleted.
</li>
<li>
Data associated with a membership is stored for as long as you are a
member of our association. If you leave the association, your data will
be deleted automatically. This does not apply to data that is required
by law to be stored for a longer period of time, such as financial
records, which are stored for 7 years regardless of your membership
status.
</li>
</ul>
</div>
<div class="section">
<h2>What are your data protection rights?</h2>
<p>You have the following data protection rights:</p>
<ul>
<li>You have the right to request access to your personal data.</li>
<li>You have the right to request correction of your personal data.</li>
<li>You have the right to request erasure of your personal data.</li>
<li>
You have the right to request restriction of processing of your personal
data.
</li>
<li>You have the right to object to processing of your personal data.</li>
<li>You have the right to request transfer of your personal data.</li>
</ul>
<p>If you make a request, we have one month to respond to you.</p>
<p>
If you would like to exercise any of these rights, please contact us at
<a href="mailto:support@private.coffee">support@private.coffee</a>.
</p>
<p>
Your privacy is important to us - after all, that's why we're all here -
and we will do our best to respond to your request as soon as possible.
Please note that we may need to verify your identity before we can respond
to your request - we will not share your data with anyone else.
</p>
<p>
If you are not satisfied with our response, or believe that we are
processing your data in a way that is not compliant with the law, you have
the right to lodge a complaint with the supervisory authority in your
country. In Austria, this is the Austrian Data Protection Authority (<a
href="https://www.dsb.gv.at/"
>https://www.dsb.gv.at/</a
>). However, we like to think of ourselves as nice people and will try to
help you out directly, and are always open to suggestions for improvement,
so please do get in touch with us if you have any questions or concerns.
</p>
</div>
<div class="section">
<h2>What are cookies?</h2>
<p>
Cookies are small text files that are placed on your computer or mobile
device when you visit a website. They are widely used to make websites
work, or work more efficiently, as well as to provide information to the
owners of the site. Cookies are stored on your device, and can be accessed
by the website that created them. They are not harmful to your device, and
do not directly contain any personal data, but are used by our services to
identify you between multiple visits.
</p>
<p>
Cookies are used on some of our services to provide you with a better
experience. For example, we use cookies to remember your preferences and
settings - for example, to allow you to login to our services - and to
provide you with a better experience when browsing our services. We do not
use cookies to track your activity, either on our services or on other
websites. In legal/technical terms, we exclusively use "strictly
necessary" first-party cookies, which is also why you don't see any cookie
banners on our website.
</p>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,6 @@
<div class="alert alert-warning text-center" role="alert">
This is a development version of the Private.coffee website. For the live
version, please visit
<a href="https://private.coffee" class="alert-link">https://private.coffee</a
>.
</div>

View file

@ -8,7 +8,15 @@
<body>
<div style="font-family: Arial, sans-serif; background-color: #f2f2f2; color: #333; line-height: 1.6; padding: 20px; max-width: 600px; margin: auto;">
<h2 style="color: #333;">Welcome to Private.coffee</h2>
<p>Thanks for using our Element instance. Private.coffee is a collection of services that respect your privacy, here are some others:</p>
<p>Thanks for using our Element instance! Now, why don't you join our rooms?</p>
<ul style="list-style: none; padding: 0;">
<li style="padding: 8px 0;"><a style="color: #1a5dab; text-decoration: none;" href="https://element.private.coffee/#/#private-coffee:private.coffee">#private-coffee:private.coffee</a> - The Private.coffee Space, containing all rooms</li>
<li style="padding: 8px 0;"><a style="color: #1a5dab; text-decoration: none;" href="https://element.private.coffee/#/#private.coffee:private.coffee">#private.coffee:private.coffee</a> - General support for our services</li>
<li style="padding: 8px 0;"><a style="color: #1a5dab; text-decoration: none;" href="https://element.private.coffee/#/#matrix:private.coffee">#matrix:private.coffee</a> - Support for our Matrix server</li>
<li style="padding: 8px 0;"><a style="color: #1a5dab; text-decoration: none;" href="https://element.private.coffee/#/#coffeebreak:private.coffee">#coffeebreak:private.coffee</a> - ☕ Coffee Break ☕ - our off-topic room</li>
</ul>
<hr>
<p>Private.coffee operates a collection of services that respect your privacy, here are some others:</p>
<ul style="list-style: none; padding: 0;">
{% for service in services.services %}
{% if not service.exclude_from_simple %}

View file

@ -2,143 +2,154 @@
{% block title %}Terms of Service{% endblock %}
{% block content %}
<div class="container">
<h1>Terms of Service</h1>
<p>
These are the terms of service for the website private.coffee and all
services provided under this domain and its subdomains. Please read them
carefully.
</p>
<h2>1. Who are we?</h2>
<p>The website private.coffee is run by:</p>
<address>
Private.coffee &dash; Verein zur Förderung von Privatsphäre und digitaler
Souver&auml;nit&auml;t<br />
c/o Klaus-Uwe Mitterer<br />
Gartengasse 22/7/3<br />
8010 Graz<br />
Austria<br />
</address>
<p>Central Register of Associations (ZVR) Number: 1758485319</p>
<p>
Email:
<a href="mailto:support@private.coffee">support@private.coffee</a>
</p>
<h2>2. What services do we provide?</h2>
<p>
The website private.coffee provides a collection of services that respect
your privacy. These services include:
</p>
<ul>
<li>
Proxy servers to several proprietary services (like YouTube, Twitter,
etc.)
</li>
<li>Matrix server</li>
<li>etc.</li>
</ul>
<p>
You can find more information about these services on the
<a href="/">main page</a>.
</p>
<h2>3. What are your obligations?</h2>
<p>
a. We provide these services to you for free. In return, we ask you to
respect our terms of service. If you do not respect our terms of service, we
reserve the right to terminate your account and delete your data.
</p>
<p>
b. We hope that our community will be diverse, respectful and friendly. As
such, any form of harassment, bullying, or abuse will not be tolerated. If
you are found to be harassing, bullying, or abusing other users, spreading
hate, lies or misinformation, we will terminate your account and delete your
data. Note that we may and will report you to the appropriate authorities if
we find your actions to be illegal. If you find yourself on the receiving
end of harassment, bullying, or abuse, please report it to us as soon as
possible.
</p>
<p>
c. You are responsible for your own actions and any content you post on our
services.
</p>
<p>
d. You are responsible for keeping your passwords, devices, private keys,
etc., secure. If you lose access, we may not be able to recover your data.
If third parties gain access to your account, we will not be able to prevent
them from accessing your data or restore any data that was lost.
</p>
<p>
e. You are required to follow the laws governing our platform (especially
the laws of Austria and the European Union) as well as any laws or
regulations that apply to you personally. If you are found to be violating
the law, we will terminate your account and delete your data. If we are
required to do so by law, we will also report you to the authorities, or
cooperate with the authorities in any way necessary.
</p>
<p>
f. You are responsible for any damage you cause to our services or other
users. This includes, but is not limited to, denial of service attacks,
spamming, etc. If you are found to be causing damage to our services or
other users, we will terminate your account and delete your data. We may
also report you to the appropriate authorities and request compensation for
any damage you caused, including legal fees.
</p>
<p>
g. If you are a minor, you may be legally required to have a parent's or
guardian's permission to use our services. Unless otherwise stated, our
services are not intended for minors.
</p>
<p>
h. In the end, this is our platform, and you are our guest. We reserve the
right to terminate your account and delete your data at any time for any
reason. We will try to give you as much notice as possible before doing so,
but we are not required to do so.
</p>
<h2>4. What are our obligations?</h2>
<p>
a. We will do our best to provide you with a stable and reliable service.
However, we cannot guarantee that our services will be available at all
times. We may need to take our services offline for maintenance or other
reasons. In case of scheduled outages, will try to give you as much notice
as possible.
</p>
<p>
b. We will do our best to keep your data secure. However, we cannot
guarantee that your data will be secure at all times. We will do our best to
prevent unauthorized access to your data, but we cannot guarantee that we
will be able to do so. If we become aware of any unauthorized access to your
data, we will notify you as soon as possible and take all reasonable steps
to prevent further unauthorized access. However, we are not responsible for
any damage that may result from unauthorized access to your data.
</p>
<p>
c. We will do our best to prevent data loss. However, we cannot guarantee
that your data will not be lost at any time. We will do our best to prevent
data loss, but we cannot guarantee that we will be able to do so. If we
become aware of any data loss, we will take all reasonable steps to restore
your data. If we are unable to restore your data, we are not responsible for
any damage that may result from the loss of your data.
</p>
<p>
d. We will do our best to keep our services available free of charge. If at
any time we decide to cease our operations, or start charging for our
services, we will give you as much notice as possible. We will also try to
find a suitable replacement for our services and, where possible, help you
migrate your data to the new service.
</p>
<p>
e. We commit to providing you with a service that respects your privacy. We
will not sell your data to third parties, and we will not use your data for
any purpose other than providing you with our services. We will not share
your data with third parties unless we are required to do so by law.
</p>
<p>
f. We commit to keeping our community diverse, respectful and friendly. As
such, we will actively monitor and moderate our community. We will not
tolerate any form of harassment, bullying, or abuse. If we become aware of
any harassment, bullying, or abuse, we will take all reasonable steps to
prevent it from continuing. If we are unable to prevent it from continuing,
we will terminate the accounts of the users involved and delete their data.
We may also report the users involved to the appropriate authorities.
</p>
<div class="text-center mb-5">
<h1 class="special-header fancy-text-primary">Terms of Service</h1>
<p class="lead">
These are the terms of service for the website private.coffee and all
services provided under this domain and its subdomains. Please read them
carefully.
</p>
</div>
<div class="section">
<h2>1. Who are we?</h2>
<p>The website private.coffee is run by:</p>
<address>
Private.coffee &dash; Verein zur Förderung von Privatsphäre und digitaler
Souver&auml;nit&auml;t<br />
c/o Klaus-Uwe Mitterer<br />
Gartengasse 22/7/3<br />
8010 Graz<br />
Austria<br />
</address>
<p>Central Register of Associations (ZVR) Number: 1758485319</p>
<p>
Email:
<a href="mailto:support@private.coffee">support@private.coffee</a>
</p>
</div>
<div class="section">
<h2>2. What services do we provide?</h2>
<p>
The website private.coffee provides a collection of services that respect
your privacy. These services include:
</p>
<ul>
<li>Information about the Private.coffee association</li>
<li>
Proxy servers to several proprietary services (like YouTube, Twitter,
etc.)
</li>
<li>Matrix server</li>
<li>etc.</li>
</ul>
<p>
You can find more information about these services on the
<a href="/">main page</a>.
</p>
</div>
<div class="section">
<h2>3. What are your obligations?</h2>
<p>
a. We provide these services to you for free. In return, we ask you to
respect our terms of service. If you do not respect our terms of service, we
reserve the right to terminate your account and delete your data.
</p>
<p>
b. We hope that our community will be diverse, respectful and friendly. As
such, any form of harassment, bullying, or abuse will not be tolerated. If
you are found to be harassing, bullying, or abusing other users, spreading
hate, lies or misinformation, we will terminate your account and delete your
data. Note that we may and will report you to the appropriate authorities if
we find your actions to be illegal. If you find yourself on the receiving
end of harassment, bullying, or abuse, please report it to us as soon as
possible.
</p>
<p>
c. You are responsible for your own actions and any content you post on our
services.
</p>
<p>
d. You are responsible for keeping your passwords, devices, private keys,
etc., secure. If you lose access, we may not be able to recover your data.
If third parties gain access to your account, we will not be able to prevent
them from accessing your data or restore any data that was lost.
</p>
<p>
e. You are required to follow the laws governing our platform (especially
the laws of Austria and the European Union) as well as any laws or
regulations that apply to you personally. If you are found to be violating
the law, we will terminate your account and delete your data. If we are
required to do so by law, we will also report you to the authorities, or
cooperate with the authorities in any way necessary.
</p>
<p>
f. You are responsible for any damage you cause to our services or other
users. This includes, but is not limited to, denial of service attacks,
spamming, etc. If you are found to be causing damage to our services or
other users, we will terminate your account and delete your data. We may
also report you to the appropriate authorities and request compensation for
any damage you caused, including legal fees.
</p>
<p>
g. If you are a minor, you may be legally required to have a parent's or
guardian's permission to use our services. Unless otherwise stated, our
services are not intended for minors.
</p>
<p>
h. In the end, this is our platform, and you are our guest. We reserve the
right to terminate your account and delete your data at any time for any
reason. We will try to give you as much notice as possible before doing so,
but we are not required to do so.
</p>
</div>
<div class="section">
<h2>4. What are our obligations?</h2>
<p>
a. We will do our best to provide you with a stable and reliable service.
However, we cannot guarantee that our services will be available at all
times. We may need to take our services offline for maintenance or other
reasons. In case of scheduled outages, will try to give you as much notice
as possible.
</p>
<p>
b. We will do our best to keep your data secure. However, we cannot
guarantee that your data will be secure at all times. We will do our best to
prevent unauthorized access to your data, but we cannot guarantee that we
will be able to do so. If we become aware of any unauthorized access to your
data, we will notify you as soon as possible and take all reasonable steps
to prevent further unauthorized access. However, we are not responsible for
any damage that may result from unauthorized access to your data.
</p>
<p>
c. We will do our best to prevent data loss. However, we cannot guarantee
that your data will not be lost at any time. We will do our best to prevent
data loss, but we cannot guarantee that we will be able to do so. If we
become aware of any data loss, we will take all reasonable steps to restore
your data. If we are unable to restore your data, we are not responsible for
any damage that may result from the loss of your data.
</p>
<p>
d. We will do our best to keep our services available free of charge. If at
any time we decide to cease our operations, or start charging for our
services, we will give you as much notice as possible. We will also try to
find a suitable replacement for our services and, where possible, help you
migrate your data to the new service.
</p>
<p>
e. We commit to providing you with a service that respects your privacy. We
will not sell your data to third parties, and we will not use your data for
any purpose other than providing you with our services. We will not share
your data with third parties unless we are required to do so by law.
</p>
<p>
f. We commit to keeping our community diverse, respectful and friendly. As
such, we will actively monitor and moderate our community. We will not
tolerate any form of harassment, bullying, or abuse. If we become aware of
any harassment, bullying, or abuse, we will take all reasonable steps to
prevent it from continuing. If we are unable to prevent it from continuing,
we will terminate the accounts of the users involved and delete their data.
We may also report the users involved to the appropriate authorities.
</p>
</div>
</div>
{% endblock %}
{% endblock %}