Compare commits

..

No commits in common. "main" and "static" have entirely different histories.
main ... static

42 changed files with 1024 additions and 2040 deletions

View file

@ -1,50 +0,0 @@
name: Build and Deploy Static Site
on:
push:
branches:
- dev
jobs:
build:
container: node:20-bookworm
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Install dependencies
run: |
apt update
apt install -y python3 python3-pip
python3 -m pip install -r requirements.txt --break-system-packages
- name: Generate static site
run: python3 main.py --dev
- name: Deploy to pages branch
run: |
# Configure Git
git config --global user.name "Forgejo"
git config --global user.email "noreply@private.coffee"
# Move generated static site files to a temporary location
mv build ../static_site_temp
cp .gitignore ../static_site_temp
# Create a new orphan branch named 'pages-dev'
git checkout --orphan pages-dev
# Remove all files from the working directory
git rm -rf .
# Move the static site files back to the working directory
mv ../static_site_temp/* ./
mv ../static_site_temp/.* ./ 2>/dev/null || true
# Add and commit the static site files
git add .
git commit -m "Deploy static site"
# Force push to the 'pages-dev' branch
git push origin pages-dev --force

View file

@ -1,50 +0,0 @@
name: Build and Deploy Static Site (Pride Theme)
on:
push:
branches:
- main
jobs:
build:
container: node:20-bookworm
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Install dependencies
run: |
apt update
apt install -y python3 python3-pip
python3 -m pip install -r requirements.txt --break-system-packages
- name: Generate static site
run: python3 main.py --theme pride
- name: Deploy to pages branch
run: |
# Configure Git
git config --global user.name "Forgejo"
git config --global user.email "noreply@private.coffee"
# Move generated static site files to a temporary location
mv build ../static_site_temp
cp .gitignore ../static_site_temp
# Create a new orphan branch named 'pages-pride'
git checkout --orphan pages-pride
# Remove all files from the working directory
git rm -rf .
# Move the static site files back to the working directory
mv ../static_site_temp/* ./
mv ../static_site_temp/.* ./ 2>/dev/null || true
# Add and commit the static site files
git add .
git commit -m "Deploy static site"
# Force push to the 'pages-pride' branch
git push origin pages-pride --force

View file

@ -3,7 +3,7 @@ name: Build and Deploy Static Site
on: on:
push: push:
branches: branches:
- main - static
jobs: jobs:
build: build:
@ -30,7 +30,6 @@ jobs:
# Move generated static site files to a temporary location # Move generated static site files to a temporary location
mv build ../static_site_temp mv build ../static_site_temp
cp .gitignore ../static_site_temp
# Create a new orphan branch named 'pages' # Create a new orphan branch named 'pages'
git checkout --orphan pages git checkout --orphan pages

View file

@ -1,5 +0,0 @@
{
"files.associations": {
"*.html": "jinja-html"
}
}

View file

@ -5,9 +5,8 @@
This is the source code for the [Private.coffee](https://private.coffee) This is the source code for the [Private.coffee](https://private.coffee)
website. website.
It is a simple Jinja2 static website generator that compiles the templates in It is a simple Flask application that generates the HTML for the website based
the `templates` directory in conjunction with the JSON files in the `data` on the services defined in the `services.json` file.
directory to generate the static HTML files in the `build` directory.
## Development ## Development
@ -19,9 +18,7 @@ pip install -r requirements.txt
python main.py python main.py
``` ```
The website will be built into the `build` directory, and you can view it by The website will be available at `http://localhost:9810`.
opening the `index.html` file in your browser or using the included HTTP server
(`python main.py --serve`).
## License ## License

View file

@ -37,10 +37,6 @@
color: #fff; color: #fff;
} }
.button-wrapper:not(:last-child) {
margin-bottom: 1rem;
}
.btn-outline-primary { .btn-outline-primary {
--bs-btn-color: #f570b9; --bs-btn-color: #f570b9;
--bs-btn-border-color: #f570b9; --bs-btn-border-color: #f570b9;
@ -85,7 +81,7 @@ h5 {
font-size: x-large; font-size: x-large;
} }
.card-body :not(p):not(:first-child):not(.dropdown-content):not(.dropdown-toggle-area) { .card-body .btn-primary:not(:first-child) {
margin-top: 10px; margin-top: 10px;
} }
@ -123,36 +119,6 @@ h5 {
color: #604c2e; color: #604c2e;
} }
/* Image Styles */
#logoContainer {
background-size: contain;
background-repeat: no-repeat;
max-width: 400px;
max-height: 400px;
width: 80vh;
height: 80vh;
}
#smallLogoContainer {
background-size: contain;
background-repeat: no-repeat;
width: 64px;
height: 64px;
}
.homemade,
.fork {
right: -0.5rem;
height: 1.5rem;
width: 1.5rem;
position: absolute;
}
.homemade svg,
.fork svg {
fill: var(--bs-primary-bg-subtle) !important;
}
.bs-icon.bs-icon-primary svg { .bs-icon.bs-icon-primary svg {
fill: var(--bs-primary-bg-subtle); fill: var(--bs-primary-bg-subtle);
} }
@ -165,6 +131,10 @@ h5 {
fill: var(--bs-primary-bg-subtle); fill: var(--bs-primary-bg-subtle);
} }
.bg-pride-gradient {
background: linear-gradient(45deg, #FF7878, #FFC898, #FFF89A, #CDF2CA, #A2CDCD, #D1E8E4, #CAB8FF);
}
/* Responsive Styles */ /* Responsive Styles */
@media (max-width: 991px) { @media (max-width: 991px) {
p.text-center.special-header { p.text-center.special-header {
@ -293,52 +263,3 @@ h5 {
text-decoration: none; text-decoration: none;
color: black; color: black;
} }
/* Accordion Styles */
.accordion {
border: 1px solid #ddd;
border-radius: 5px;
}
.accordion-item {
border-bottom: 1px solid #ddd;
}
.accordion-header {
display: flex;
align-items: center;
padding: 1rem;
cursor: pointer;
background-color: #f9f9f9;
font-size: 1.25rem;
font-weight: bold;
border-bottom: 1px solid #ddd;
}
.accordion-header:hover {
background-color: #e9e9e9;
}
.icon-container {
display: flex;
align-items: center;
margin-right: 1rem;
}
.bs-icon {
position: relative;
}
.accordion-body {
padding: 1rem;
display: none;
}
.accordion-item[open] .accordion-body {
display: block;
}
.accordion-header .bs-icon svg {
width: 32px;
}

View file

@ -1,7 +0,0 @@
#logoContainer {
background-image: url(../../img/logo-inv_grad.svg);
}
#smallLogoContainer {
background-image: url(../../img/logo-inv_grad.svg);
}

View file

@ -1,11 +0,0 @@
.bg-primary-gradient {
background: linear-gradient(45deg, #FF7878, #FFC898, #FFF89A, #CDF2CA, #A2CDCD, #D1E8E4, #CAB8FF);
}
#logoContainer {
background-image: url(../../img/logo-white.svg);
}
#smallLogoContainer {
background-image: url(../../img/logo-inv_grad.svg);
}

View file

@ -1,6 +0,0 @@
Unless otherwise specified, the files in this directory are taken from
[Phosphor Icons](https://phosphoricons.com/) and are licensed under the
MIT License. For details, please see the Phosphor Icons website.
The file `rainbow.svg` was created by us at [Private.coffee](https://private.coffee)
and is also licensed under the MIT License.

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M231.65,194.55,198.46,36.75a16,16,0,0,0-19-12.39L132.65,34.42a16.08,16.08,0,0,0-12.3,19l33.19,157.8A16,16,0,0,0,169.16,224a16.25,16.25,0,0,0,3.38-.36l46.81-10.06A16.09,16.09,0,0,0,231.65,194.55ZM136,50.15c0-.06,0-.09,0-.09l46.8-10,3.33,15.87L139.33,66Zm6.62,31.47,46.82-10.05,3.34,15.9L146,97.53Zm6.64,31.57,46.82-10.06,13.3,63.24-46.82,10.06ZM216,197.94l-46.8,10-3.33-15.87L212.67,182,216,197.85C216,197.91,216,197.94,216,197.94ZM104,32H56A16,16,0,0,0,40,48V208a16,16,0,0,0,16,16h48a16,16,0,0,0,16-16V48A16,16,0,0,0,104,32ZM56,48h48V64H56Zm0,32h48v96H56Zm48,128H56V192h48v16Z"></path></svg>

Before

Width:  |  Height:  |  Size: 700 B

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M208,56H180.28L166.65,35.56A8,8,0,0,0,160,32H96a8,8,0,0,0-6.65,3.56L75.71,56H48A24,24,0,0,0,24,80V192a24,24,0,0,0,24,24H208a24,24,0,0,0,24-24V80A24,24,0,0,0,208,56Zm8,136a8,8,0,0,1-8,8H48a8,8,0,0,1-8-8V80a8,8,0,0,1,8-8H80a8,8,0,0,0,6.66-3.56L100.28,48h55.43l13.63,20.44A8,8,0,0,0,176,72h32a8,8,0,0,1,8,8ZM128,88a44,44,0,1,0,44,44A44.05,44.05,0,0,0,128,88Zm0,72a28,28,0,1,1,28-28A28,28,0,0,1,128,160Z"></path></svg>

Before

Width:  |  Height:  |  Size: 523 B

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M224,152V136a96.37,96.37,0,0,0-64-90.51V40a16,16,0,0,0-16-16H112A16,16,0,0,0,96,40v5.49A96.37,96.37,0,0,0,32,136v16a16,16,0,0,0-16,16v24a16,16,0,0,0,16,16H224a16,16,0,0,0,16-16V168A16,16,0,0,0,224,152Zm-16-16v16H160V62.67A80.36,80.36,0,0,1,208,136ZM144,40V152H112V40ZM48,136A80.36,80.36,0,0,1,96,62.67V152H48Zm176,56H32V168H224v24Z"></path></svg>

Before

Width:  |  Height:  |  Size: 455 B

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M128,112a28,28,0,0,0-8,54.83V184a8,8,0,0,0,16,0V166.83A28,28,0,0,0,128,112Zm0,40a12,12,0,1,1,12-12A12,12,0,0,1,128,152Zm80-72H176V56a48,48,0,0,0-96,0V80H48A16,16,0,0,0,32,96V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V96A16,16,0,0,0,208,80ZM96,56a32,32,0,0,1,64,0V80H96ZM208,208H48V96H208V208Z"></path></svg>

Before

Width:  |  Height:  |  Size: 417 B

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M228.92,49.69a8,8,0,0,0-6.86-1.45L160.93,63.52,99.58,32.84a8,8,0,0,0-5.52-.6l-64,16A8,8,0,0,0,24,56V200a8,8,0,0,0,9.94,7.76l61.13-15.28,61.35,30.68A8.15,8.15,0,0,0,160,224a8,8,0,0,0,1.94-.24l64-16A8,8,0,0,0,232,200V56A8,8,0,0,0,228.92,49.69ZM104,52.94l48,24V203.06l-48-24ZM40,62.25l48-12v127.5l-48,12Zm176,131.5-48,12V78.25l48-12Z"></path></svg>

Before

Width:  |  Height:  |  Size: 454 B

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M244.24,60a8,8,0,0,0-7.75-.4c-42.93,21-73.59,11.16-106,.78-34-10.89-69.25-22.14-117.95,1.64A8,8,0,0,0,8,69.24V189.17a8,8,0,0,0,11.51,7.19c42.93-21,73.59-11.16,106.05-.78,19.24,6.15,38.84,12.42,61,12.42,17.09,0,35.73-3.72,56.91-14.06a8,8,0,0,0,4.49-7.18V66.83A8,8,0,0,0,244.24,60ZM232,181.67c-40.6,18.17-70.25,8.69-101.56-1.32-19.24-6.15-38.84-12.42-61-12.42a122,122,0,0,0-45.4,9V74.33c40.6-18.17,70.25-8.69,101.56,1.32S189.14,96,232,79.09ZM128,96a32,32,0,1,0,32,32A32,32,0,0,0,128,96Zm0,48a16,16,0,1,1,16-16A16,16,0,0,1,128,144ZM56,96v48a8,8,0,0,1-16,0V96a8,8,0,1,1,16,0Zm144,64V112a8,8,0,1,1,16,0v48a8,8,0,1,1-16,0Z"></path></svg>

Before

Width:  |  Height:  |  Size: 740 B

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M104,40H56A16,16,0,0,0,40,56v48a16,16,0,0,0,16,16h48a16,16,0,0,0,16-16V56A16,16,0,0,0,104,40Zm0,64H56V56h48v48Zm0,32H56a16,16,0,0,0-16,16v48a16,16,0,0,0,16,16h48a16,16,0,0,0,16-16V152A16,16,0,0,0,104,136Zm0,64H56V152h48v48ZM200,40H152a16,16,0,0,0-16,16v48a16,16,0,0,0,16,16h48a16,16,0,0,0,16-16V56A16,16,0,0,0,200,40Zm0,64H152V56h48v48Zm-64,72V144a8,8,0,0,1,16,0v32a8,8,0,0,1-16,0Zm80-16a8,8,0,0,1-8,8H184v40a8,8,0,0,1-8,8H144a8,8,0,0,1,0-16h24V144a8,8,0,0,1,16,0v8h24A8,8,0,0,1,216,160Zm0,32v16a8,8,0,0,1-16,0V192a8,8,0,0,1,16,0Z"></path></svg>

Before

Width:  |  Height:  |  Size: 654 B

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M140,180a12,12,0,1,1-12-12A12,12,0,0,1,140,180ZM128,72c-22.06,0-40,16.15-40,36v4a8,8,0,0,0,16,0v-4c0-11,10.77-20,24-20s24,9,24,20-10.77,20-24,20a8,8,0,0,0-8,8v8a8,8,0,0,0,16,0v-.72c18.24-3.35,32-17.9,32-35.28C168,88.15,150.06,72,128,72Zm104,56A104,104,0,1,1,128,24,104.11,104.11,0,0,1,232,128Zm-16,0a88,88,0,1,0-88,88A88.1,88.1,0,0,0,216,128Z"></path></svg>

Before

Width:  |  Height:  |  Size: 466 B

View file

@ -1,16 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" width="135" height="20" role="img" aria-label="LGBTIQ+"> <svg xmlns="http://www.w3.org/2000/svg" width="94" height="20" role="img" aria-label="LGBTIQ+">
<!-- This file was created as part of the Private.coffee project
It is licensed under the MIT license
For more information, please visit https://private.coffee -->
<title>LGBTIQ+</title> <title>LGBTIQ+</title>
<rect rx="3" width="135" height="20" fill="#555"></rect> <rect rx="3" width="94" height="20" fill="#555"/>
<rect x="53" width="82" height="20" fill="#e05d44"></rect> <rect x="37" width="57" height="20" fill="#e05d44"/>
<rect x="66.5" width="68.5" height="20" fill="#fecc00"></rect> <rect x="46.5" width="47.5" height="20" fill="#fecc00"/>
<rect x="80" width="55" height="20" fill="#61c354"></rect> <rect x="56" width="37" height="20" fill="#61c354"/>
<rect x="93.5" width="41.5" height="20" fill="#007ec6"></rect> <rect x="65.5" width="27" height="20" fill="#007ec6"/>
<rect x="107" width="28" height="20" fill="#744ca1"></rect> <rect x="75" width="17" height="20" fill="#744ca1"/>
<rect x="120.5" width="14.5" height="20" rx="3" ry="3" fill="#8b00ff"></rect> <rect x="84.5" width="9.5" height="20" rx="3" ry="3" fill="#8b00ff"/>
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="8"> <g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="8">
<text x="27" y="15" fill="#fff">LGBTIQ+</text> <text x="18.5" y="15" fill="#fff">LGBTIQ+</text>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 956 B

After

Width:  |  Height:  |  Size: 757 B

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M106.91,149.09A71.53,71.53,0,0,1,128,200a8,8,0,0,1-16,0,56,56,0,0,0-56-56,8,8,0,0,1,0-16A71.53,71.53,0,0,1,106.91,149.09ZM56,80a8,8,0,0,0,0,16A104,104,0,0,1,160,200a8,8,0,0,0,16,0A120,120,0,0,0,56,80Zm118.79,1.21A166.9,166.9,0,0,0,56,32a8,8,0,0,0,0,16A151,151,0,0,1,163.48,92.52,151,151,0,0,1,208,200a8,8,0,0,0,16,0A166.9,166.9,0,0,0,174.79,81.21ZM60,184a12,12,0,1,0,12,12A12,12,0,0,0,60,184Z"></path></svg>

Before

Width:  |  Height:  |  Size: 516 B

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M184,24H72A32,32,0,0,0,40,56V184a32,32,0,0,0,32,32h8L65.6,235.2a8,8,0,1,0,12.8,9.6L100,216h56l21.6,28.8a8,8,0,1,0,12.8-9.6L176,216h8a32,32,0,0,0,32-32V56A32,32,0,0,0,184,24ZM56,120V80h64v40Zm80-40h64v40H136ZM72,40H184a16,16,0,0,1,16,16v8H56V56A16,16,0,0,1,72,40ZM184,200H72a16,16,0,0,1-16-16V136H200v48A16,16,0,0,1,184,200ZM96,172a12,12,0,1,1-12-12A12,12,0,0,1,96,172Zm88,0a12,12,0,1,1-12-12A12,12,0,0,1,184,172Z"></path></svg>

Before

Width:  |  Height:  |  Size: 536 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 14 KiB

View file

@ -1,44 +0,0 @@
{
"bridges": [
{
"name": "Telegram",
"mxid": "@telegrambot:private.coffee"
},
{
"name": "WhatsApp",
"mxid": "@whatsappbot:private.coffee"
},
{
"name": "Signal",
"mxid": "@signalbot:private.coffee"
},
{
"name": "Discord",
"mxid": "@discordbot:private.coffee"
},
{
"name": "Slack",
"mxid": "@slackbot:private.coffee"
},
{
"name": "LinkedIn",
"mxid": "@linkedinbot:private.coffee"
},
{
"name": "GPT-4o",
"mxid": "@gptbot:private.coffee"
},
{
"name": "RSS/Atom feeds",
"mxid": "@rssbot:private.coffee"
},
{
"name": "Instagram",
"mxid": "@instagrambot:private.coffee"
},
{
"name": "Facebook",
"mxid": "@facebookbot:private.coffee"
}
]
}

View file

@ -1,18 +1,19 @@
{ {
"2024": { "2024": {
"04": { "4": {
"Membership Fees": { "Membership Fees": {
"EUR": 365 "EUR": 365
}, },
"Server Costs": { "Server Costs": {
"EUR": -216.57 "EUR": -216.57
}, },
"Domain Names": {},
"Administrative Expenses": { "Administrative Expenses": {
"EUR": -36.10, "EUR": -36.10,
"Notes": "Administrative fee for the formation of the association" "Notes": "Administrative fee for the formation of the association"
} }
}, },
"05": { "5": {
"Membership Fees": { "Membership Fees": {
"EUR": 390 "EUR": 390
}, },
@ -25,7 +26,7 @@
"Notes": "Includes setup costs and two monthly payments for new server" "Notes": "Includes setup costs and two monthly payments for new server"
} }
}, },
"06": { "6": {
"Membership Fees": { "Membership Fees": {
"EUR": 382.42 "EUR": 382.42
}, },
@ -36,39 +37,9 @@
"EUR": -49.05 "EUR": -49.05
} }
}, },
"07": { "7": {
"Membership Fees": { "Membership Fees": {
"EUR": 422.42 "EUR": 20
},
"Donations": {
"XMR": 1.0
},
"Server Costs": {
"EUR": -264.99
}
},
"08": {
"Membership Fees": {
"EUR": 402.42
},
"Server Costs": {
"EUR": -416.47
}
},
"09": {
"Membership Fees": {
"EUR": 468.11
},
"Server Costs": {
"EUR": -243.46
},
"Bank Fees": {
"EUR": -53.32
}
},
"10": {
"Membership Fees": {
"EUR": 30.23
} }
} }
} }

View file

@ -3,11 +3,8 @@
{ {
"name": "Matrix", "name": "Matrix",
"url": "https://element.private.coffee", "url": "https://element.private.coffee",
"homemade": false,
"fork": false,
"tiny_description": "decentralized messaging",
"short_description": "Matrix is an open network for secure, decentralized communication.", "short_description": "Matrix is an open network for secure, decentralized communication.",
"long_description": "Private.coffee runs a Matrix server. You can use it to chat with other people at Private.coffee or around the world. Public registrations are currently disabled, send an email to support@private.coffee to request an account.", "long_description": "Private.coffee runs a Matrix server. You can use it to chat with other people at Private.coffee or around the world. Use it with a client of your choice, or use our Element web client.",
"status": "OK", "status": "OK",
"links": [ "links": [
{ {
@ -19,10 +16,6 @@
"url": "http://element.coffee2m3bjsrrqqycx6ghkxrnejl2q6nl7pjw2j4clchjj6uk5zozad.onion" "url": "http://element.coffee2m3bjsrrqqycx6ghkxrnejl2q6nl7pjw2j4clchjj6uk5zozad.onion"
} }
] ]
},
{
"name": "Go to Hydrogen",
"url": "https://hydrogen.private.coffee"
} }
], ],
"icon": "matrix-logo", "icon": "matrix-logo",
@ -32,9 +25,6 @@
{ {
"name": "CryptPad", "name": "CryptPad",
"url": "https://cryptpad.private.coffee", "url": "https://cryptpad.private.coffee",
"homemade": false,
"fork": false,
"tiny_description": "collaborative document editing",
"short_description": "Private, encrypted, real-time collaborative editor.", "short_description": "Private, encrypted, real-time collaborative editor.",
"long_description": "CryptPad is a private, encrypted, zero-knowledge, realtime collaborative editor, similar to Google Docs and Office 365.", "long_description": "CryptPad is a private, encrypted, zero-knowledge, realtime collaborative editor, similar to Google Docs and Office 365.",
"status": "OK", "status": "OK",
@ -48,12 +38,35 @@
"exclude_from_index": false, "exclude_from_index": false,
"exclude_from_simple": false "exclude_from_simple": false
}, },
{
"name": "Piped / Invidious",
"url": "https://piped.private.coffee",
"short_description": "Watch YouTube videos without Google tracking.",
"long_description": "Piped and Invidious are alternative front-ends to YouTube. They allow you to watch YouTube videos without Google tracking you.",
"status": "OK",
"links": [
{
"name": "Go to Piped",
"url": "https://piped.private.coffee"
},
{
"name": "Go to Invidious",
"url": "https://invidious.private.coffee",
"alternatives": [
{
"name": "Tor",
"url": "http://invidious.coffee2m3bjsrrqqycx6ghkxrnejl2q6nl7pjw2j4clchjj6uk5zozad.onion"
}
]
}
],
"icon": "video",
"exclude_from_index": false,
"exclude_from_simple": false
},
{ {
"name": "Transfer.coffee", "name": "Transfer.coffee",
"url": "https://transfer.coffee", "url": "https://transfer.coffee",
"homemade": "https://git.private.coffee/PrivateCoffee/transfer.coffee",
"fork": false,
"tiny_description": "secure direct file transfer",
"short_description": "Transfer files securely using peer-to-peer connections.", "short_description": "Transfer files securely using peer-to-peer connections.",
"long_description": "Transfer.coffee allows you to transfer files securely using peer-to-peer connections. Your files are never stored on our servers.", "long_description": "Transfer.coffee allows you to transfer files securely using peer-to-peer connections. Your files are never stored on our servers.",
"status": "OK", "status": "OK",
@ -70,9 +83,6 @@
{ {
"name": "MyIP.Coffee", "name": "MyIP.Coffee",
"url": "https://myip.coffee", "url": "https://myip.coffee",
"homemade": "https://git.private.coffee/PrivateCoffee/myip.coffee",
"fork": false,
"tiny_description": "check your IP address",
"short_description": "Check your IP address.", "short_description": "Check your IP address.",
"long_description": "MyIP.Coffee allows you to check your current IPv4 and IPv6 addresses.", "long_description": "MyIP.Coffee allows you to check your current IPv4 and IPv6 addresses.",
"status": "OK", "status": "OK",
@ -86,33 +96,11 @@
"exclude_from_index": false, "exclude_from_index": false,
"exclude_from_simple": false "exclude_from_simple": false
}, },
{
"name": "Overleaf",
"url": "https://overleaf.private.coffee",
"homemade": false,
"fork": false,
"tiny_description": "collaborative LaTeX editor",
"short_description": "Overleaf is an online LaTeX editor for writing and sharing documents.",
"long_description": "Overleaf is an online LaTeX editor for writing and sharing documents. It allows you to write documents in LaTeX, and to collaborate with others.",
"status": "OK",
"links": [
{
"name": "Go to Overleaf",
"url": "https://overleaf.private.coffee"
}
],
"icon": "leaf",
"exclude_from_index": false,
"exclude_from_simple": false
},
{ {
"name": "Mastodon", "name": "Mastodon",
"url": "https://cuddly.space", "url": "https://cuddly.space",
"homemade": false,
"fork": false,
"tiny_description": "decentralized social network",
"short_description": "Mastodon is a decentralized social network.", "short_description": "Mastodon is a decentralized social network.",
"long_description": "Mastodon is a decentralized social network. You can use it to post short messages, follow other people, and more. Registrations are open to everyone on Cuddly Space.", "long_description": "Mastodon is a decentralized social network. You can use it to post short messages, follow other people, and more.",
"status": "OK", "status": "OK",
"links": [ "links": [
{ {
@ -131,9 +119,6 @@
{ {
"name": "Forgejo", "name": "Forgejo",
"url": "https://git.private.coffee", "url": "https://git.private.coffee",
"homemade": false,
"fork": false,
"tiny_description": "self-hosted Git forge",
"short_description": "Forgejo is our in-house Git forge.", "short_description": "Forgejo is our in-house Git forge.",
"long_description": "Forgejo is our in-house Git forge. You can use it to host your Git repositories, and to collaborate with others.", "long_description": "Forgejo is our in-house Git forge. You can use it to host your Git repositories, and to collaborate with others.",
"status": "OK", "status": "OK",
@ -150,9 +135,6 @@
{ {
"name": "BigBlueButton", "name": "BigBlueButton",
"url": "https://bbb.private.coffee", "url": "https://bbb.private.coffee",
"homemade": false,
"fork": false,
"tiny_description": "video conferencing",
"short_description": "BigBlueButton is an open-source video conferencing system.", "short_description": "BigBlueButton is an open-source video conferencing system.",
"long_description": "BigBlueButton is an open-source video conferencing system. You can use it to hold video conferences, webinars, and more.", "long_description": "BigBlueButton is an open-source video conferencing system. You can use it to hold video conferences, webinars, and more.",
"status": "OK", "status": "OK",
@ -169,9 +151,6 @@
{ {
"name": "HedgeDoc", "name": "HedgeDoc",
"url": "https://hedgedoc.private.coffee", "url": "https://hedgedoc.private.coffee",
"homemade": false,
"fork": false,
"tiny_description": "collaborative markdown editor",
"short_description": "HedgeDoc is an open-source collaborative markdown editor.", "short_description": "HedgeDoc is an open-source collaborative markdown editor.",
"long_description": "HedgeDoc is an open-source collaborative markdown editor. You can use it to write and edit documents in markdown, and to collaborate with others.", "long_description": "HedgeDoc is an open-source collaborative markdown editor. You can use it to write and edit documents in markdown, and to collaborate with others.",
"status": "OK", "status": "OK",
@ -185,88 +164,9 @@
"exclude_from_index": false, "exclude_from_index": false,
"exclude_from_simple": false "exclude_from_simple": false
}, },
{
"name": "FacilMap",
"url": "https://facilmap.private.coffee",
"homemade": false,
"fork": false,
"tiny_description": "open-source map editor",
"short_description": "FacilMap is an open-source map editor.",
"long_description": "FacilMap is an open-source map editor. You can use it to create and edit maps, and to share them with others.",
"status": "OK",
"links": [
{
"name": "Go to FacilMap",
"url": "https://facilmap.private.coffee"
}
],
"icon": "map-trifold",
"exclude_from_index": false,
"exclude_from_simple": false
},
{
"name": "OTS - One Time Secrets",
"url": "https://ots.private.coffee",
"homemade": false,
"fork": false,
"tiny_description": "share secrets securely",
"short_description": "OTS is a service for sharing secrets securely.",
"long_description": "OTS is a service for sharing secrets securely. You can use it to share passwords, API keys, and other sensitive information.",
"status": "OK",
"links": [
{
"name": "Go to OTS",
"url": "https://ots.private.coffee"
}
],
"icon": "lock-key",
"exclude_from_index": false,
"exclude_from_simple": false
},
{
"name": "QRMaker",
"url": "https://qrmaker.private.coffee",
"homemade": "https://git.private.coffee/PrivateCoffee/QRMaker",
"fork": false,
"tiny_description": "QR code generator",
"short_description": "QRMaker is a service for generating QR codes.",
"long_description": "QRMaker is a service for generating QR codes. You can use it to create QR codes for URLs, text, and more, directly in your browser.",
"status": "OK",
"links": [
{
"name": "Go to QRMaker",
"url": "https://qrmaker.private.coffee"
}
],
"icon": "qr-code",
"exclude_from_index": false,
"exclude_from_simple": false
},
{
"name": "FreshRSS",
"url": "https://freshrss.private.coffee",
"homemade": false,
"fork": false,
"tiny_description": "RSS feed reader",
"short_description": "FreshRSS is a RSS feed reader.",
"long_description": "FreshRSS is a RSS feed reader. You can use it to subscribe to RSS feeds and read the latest articles from your favorite websites.",
"status": "OK",
"links": [
{
"name": "Go to FreshRSS",
"url": "https://freshrss.private.coffee"
}
],
"icon": "rss",
"exclude_from_index": false,
"exclude_from_simple": false
},
{ {
"name": "redlib", "name": "redlib",
"url": "https://redlib.private.coffee", "url": "https://redlib.private.coffee",
"homemade": false,
"fork": false,
"tiny_description": "tracking-free Reddit",
"short_description": "redlib is a privacy-friendly alternative front-end to Reddit.", "short_description": "redlib is a privacy-friendly alternative front-end to Reddit.",
"long_description": "redlib is a privacy-friendly alternative front-end to Reddit. It allows you to browse Reddit without being tracked.", "long_description": "redlib is a privacy-friendly alternative front-end to Reddit. It allows you to browse Reddit without being tracked.",
"status": "OK", "status": "OK",
@ -280,50 +180,9 @@
"exclude_from_index": false, "exclude_from_index": false,
"exclude_from_simple": false "exclude_from_simple": false
}, },
{
"name": "CyberChef",
"url": "https://cyberchef.private.coffee",
"homemade": false,
"fork": false,
"tiny_description": "Web app for encryption and encoding",
"short_description": "CyberChef is a web app for encryption, encoding, compression, and data analysis.",
"long_description": "CyberChef is a web app for encryption, encoding, compression, and data analysis. It allows you to perform a wide range of operations on your data within your browser.",
"status": "OK",
"links": [
{
"name": "Go to CyberChef",
"url": "https://cyberchef.private.coffee"
}
],
"icon": "lock-key",
"exclude_from_index": false,
"exclude_from_simple": false
},
{
"name": "Travelynx",
"url": "https://traveling.coffee",
"homemade": false,
"fork": false,
"tiny_description": "rail journey logger (German)",
"short_description": "Travelynx is a service for logging your rail journeys. (German)",
"long_description": "Travelynx is a service for logging your rail journeys, primarily for Germany and surrounding Europe. You can use it to keep track of the trains you've taken, and to view statistics about your trips.",
"status": "OK",
"links": [
{
"name": "Go to Travelynx",
"url": "https://traveling.coffee"
}
],
"icon": "train",
"exclude_from_index": false,
"exclude_from_simple": false
},
{ {
"name": "AllTube", "name": "AllTube",
"url": "https://alltube.private.coffee", "url": "https://alltube.private.coffee",
"homemade": false,
"fork": "https://git.private.coffee/PrivateCoffee/alltube",
"tiny_description": "universal video downloader",
"short_description": "Download videos from YouTube, Vimeo, and more.", "short_description": "Download videos from YouTube, Vimeo, and more.",
"long_description": "AllTube is a video downloader powered by yt-dlp. It allows you to download videos from YouTube, Vimeo, and many other sites. You can also stream the download through our server for extra privacy.", "long_description": "AllTube is a video downloader powered by yt-dlp. It allows you to download videos from YouTube, Vimeo, and many other sites. You can also stream the download through our server for extra privacy.",
"status": "OK", "status": "OK",
@ -337,56 +196,9 @@
"exclude_from_index": false, "exclude_from_index": false,
"exclude_from_simple": false "exclude_from_simple": false
}, },
{
"name": "Invidious",
"url": "https://invidious.private.coffee",
"homemade": false,
"fork": "https://git.private.coffee/PrivateCoffee/invidious",
"tiny_description": "tracking-free YouTube",
"short_description": "Watch YouTube videos without Google tracking.",
"long_description": "Invidious is an alternative front-end to YouTube. Unfortunately, it is under attack from Google, and is mostly unusable at the moment.",
"status": "NOK",
"links": [
{
"name": "Go to Invidious",
"url": "https://invidious.private.coffee",
"alternatives": [
{
"name": "Tor",
"url": "http://invidious.coffee2m3bjsrrqqycx6ghkxrnejl2q6nl7pjw2j4clchjj6uk5zozad.onion"
}
]
}
],
"icon": "video",
"exclude_from_index": false,
"exclude_from_simple": false
},
{
"name": "Piped",
"url": "https://piped.private.coffee",
"homemade": false,
"fork": false,
"tiny_description": "tracking-free YouTube",
"short_description": "Watch YouTube videos without Google tracking.",
"long_description": "Piped is an alternative front-end to YouTube. Unfortunately, it is under attack from Google, and is mostly unusable at the moment.",
"status": "NOK",
"links": [
{
"name": "Go to Piped",
"url": "https://piped.private.coffee"
}
],
"icon": "video",
"exclude_from_index": true,
"exclude_from_simple": true
},
{ {
"name": "Structables", "name": "Structables",
"url": "https://structables.private.coffee", "url": "https://structables.private.coffee",
"homemade": "https://git.private.coffee/PrivateCoffee/structables",
"fork": false,
"tiny_description": "tracking-free Instructables",
"short_description": "Browse Instructables without being tracked.", "short_description": "Browse Instructables without being tracked.",
"long_description": "Structables allows you to browse Instructables without being tracked.", "long_description": "Structables allows you to browse Instructables without being tracked.",
"status": "OK", "status": "OK",
@ -400,144 +212,9 @@
"exclude_from_index": false, "exclude_from_index": false,
"exclude_from_simple": false "exclude_from_simple": false
}, },
{
"name": "Quetre",
"url": "https://quetre.private.coffee",
"homemade": false,
"fork": false,
"tiny_description": "tracking-free Quora",
"short_description": "Quetre is a privacy-friendly alternative front-end to Quora.",
"long_description": "Quetre is a privacy-friendly alternative front-end to Quora. It allows you to browse Quora without being tracked or having to log in.",
"status": "OK",
"links": [
{
"name": "Go to Quetre",
"url": "https://quetre.private.coffee",
"alternatives": [
{
"name": "Tor",
"url": "http://quetre.coffee2m3bjsrrqqycx6ghkxrnejl2q6nl7pjw2j4clchjj6uk5zozad.onion"
}
]
}
],
"icon": "question",
"exclude_from_index": false,
"exclude_from_simple": false
},
{
"name": "Wikimore",
"url": "https://wikimore.private.coffee",
"homemade": "https://git.private.coffee/PrivateCoffee/wikimore",
"fork": false,
"tiny_description": "censorship-free Wikipedia",
"short_description": "Wikimore is a privacy-friendly alternative front-end to Wikimedia wikis.",
"long_description": "Wikimore is a privacy-friendly alternative front-end to Wikipedia and other Wikimedia wikis.",
"status": "OK",
"links": [
{
"name": "Go to Wikimore",
"url": "https://wikimore.private.coffee",
"alternatives": [
{
"name": "Tor",
"url": "http://wikimore.coffee2m3bjsrrqqycx6ghkxrnejl2q6nl7pjw2j4clchjj6uk5zozad.onion"
}
]
}
],
"icon": "books",
"exclude_from_index": false,
"exclude_from_simple": false
},
{
"name": "Priviblur",
"url": "https://priviblur.private.coffee",
"homemade": false,
"fork": false,
"tiny_description": "tracking-free Tumblr",
"short_description": "Priviblur is a privacy-friendly alternative front-end to Tumblr.",
"long_description": "Priviblur is a privacy-friendly alternative front-end to Tumblr. It allows you to browse Tumblr without being tracked.",
"status": "OK",
"links": [
{
"name": "Go to Priviblur",
"url": "https://priviblur.private.coffee",
"alternatives": [
{
"name": "Tor",
"url": "http://priviblur.coffee2m3bjsrrqqycx6ghkxrnejl2q6nl7pjw2j4clchjj6uk5zozad.onion"
}
]
}
],
"icon": "camera",
"exclude_from_index": false,
"exclude_from_simple": false
},
{
"name": "BiblioReads",
"url": "https://biblioreads.private.coffee",
"homemade": false,
"fork": false,
"tiny_description": "tracking-free Goodreads",
"short_description": "BiblioReads is a privacy-friendly alternative front-end to Goodreads.",
"long_description": "BiblioReads is a privacy-friendly alternative front-end to Goodreads. It allows you to browse Goodreads without being tracked.",
"status": "OK",
"links": [
{
"name": "Go to BiblioReads",
"url": "https://biblioreads.private.coffee"
}
],
"icon": "books",
"exclude_from_index": false,
"exclude_from_simple": false
},
{
"name": "Small",
"url": "https://small.private.coffee",
"homemade": "https://git.private.coffee/PrivateCoffee/small",
"fork": false,
"tiny_description": "tracking-free Medium",
"short_description": "Small is a privacy-friendly alternative front-end to Medium.",
"long_description": "Small is a privacy-friendly alternative front-end to Medium. It allows you to browse Medium without being tracked.",
"status": "OK",
"links": [
{
"name": "Go to Small",
"url": "https://small.private.coffee"
}
],
"icon": "pencil-ruler",
"exclude_from_index": false,
"exclude_from_simple": false
},
{
"name": "Scribe",
"url": "https://scribe.private.coffee",
"homemade": false,
"fork": false,
"tiny_description": "tracking-free Medium",
"short_description": "Scribe is a privacy-friendly alternative front-end to Medium.",
"long_description": "Scribe is a privacy-friendly alternative front-end to Medium. It allows you to browse Medium without being tracked.",
"status": "OK",
"links": [
{
"name": "Go to Scribe",
"url": "https://scribe.private.coffee"
}
],
"icon": "pencil-ruler",
"exclude_from_index": false,
"exclude_from_simple": false
},
{ {
"name": "LibreTranslate", "name": "LibreTranslate",
"url": "https://translate.private.coffee", "url": "https://translate.private.coffee",
"homemade": false,
"fork": false,
"tiny_description": "self-hosted translation",
"short_description": "LibreTranslate is a self-hosted translation service powered by Argos Translate.", "short_description": "LibreTranslate is a self-hosted translation service powered by Argos Translate.",
"long_description": "LibreTranslate is a self-hosted translation service powered by Argos Translate. It allows you to translate text between many languages.", "long_description": "LibreTranslate is a self-hosted translation service powered by Argos Translate. It allows you to translate text between many languages.",
"status": "OK", "status": "OK",
@ -548,16 +225,13 @@
} }
], ],
"icon": "translate", "icon": "translate",
"exclude_from_index": true, "exclude_from_index": false,
"exclude_from_simple": true "exclude_from_simple": false
}, },
{ {
"name": "wishthis", "name": "wishthis",
"url": "https://wishthis.private.coffee", "url": "https://wishthis.private.coffee",
"homemade": false, "short_description": "wishthis is a service for creating wishlists.",
"fork": false,
"tiny_description": "create and share wishlists",
"short_description": "wishthis is a service for creating and sharing wishlists.",
"long_description": "wishthis is a service for creating wishlists. You can use it to create wishlists for yourself, or to share them with others.", "long_description": "wishthis is a service for creating wishlists. You can use it to create wishlists for yourself, or to share them with others.",
"status": "OK", "status": "OK",
"links": [ "links": [
@ -570,56 +244,9 @@
"exclude_from_index": false, "exclude_from_index": false,
"exclude_from_simple": false "exclude_from_simple": false
}, },
{
"name": "BreezeWiki",
"url": "https://breezewiki.private.coffee",
"homemade": false,
"fork": false,
"tiny_description": "tracking-free Fandom",
"short_description": "BreezeWiki is a privacy-friendly alternative front-end to Fandom.",
"long_description": "BreezeWiki is a privacy-friendly alternative front-end to Fandom. It allows you to browse Fandom wikis without ads or tracking.",
"status": "OK",
"links": [
{
"name": "Go to BreezeWiki",
"url": "https://breezewiki.private.coffee",
"alternatives": [
{
"name": "Tor",
"url": "http://breezewiki.coffee2m3bjsrrqqycx6ghkxrnejl2q6nl7pjw2j4clchjj6uk5zozad.onion"
}
]
}
],
"icon": "books",
"exclude_from_index": false,
"exclude_from_simple": false
},
{
"name": "Ducks for Ducks",
"url": "https://ducksforducks.private.coffee",
"homemade": "https://git.private.coffee/PrivateCoffee/ducksforducks",
"fork": false,
"tiny_description": "a private front-end to Geeks for Geeks",
"short_description": "Ducks for Ducks is a privacy-friendly alternative front-end to Geeks for Geeks.",
"long_description": "Ducks for Ducks is a privacy-friendly alternative front-end to Geeks for Geeks. It allows you to browse Geeks for Geeks without ads or tracking.",
"status": "OK",
"links": [
{
"name": "Go to Ducks for Ducks",
"url": "https://ducksforducks.private.coffee"
}
],
"icon": "books",
"exclude_from_index": false,
"exclude_from_simple": false
},
{ {
"name": "NocoDB", "name": "NocoDB",
"url": "https://nocodb.private.coffee", "url": "https://nocodb.private.coffee",
"homemade": false,
"fork": false,
"tiny_description": "Airtable alternative",
"short_description": "NocoDB is a self-hosted alternative to Airtable.", "short_description": "NocoDB is a self-hosted alternative to Airtable.",
"long_description": "NocoDB is a self-hosted alternative to Airtable. It allows you to create databases and tables, and to view and edit them in a spreadsheet-like interface. (Note: If you are unable to create tables upon registration, simply wait a minute or two, log out and then log in again. Note that your email address will be visible to all registered users!)", "long_description": "NocoDB is a self-hosted alternative to Airtable. It allows you to create databases and tables, and to view and edit them in a spreadsheet-like interface. (Note: If you are unable to create tables upon registration, simply wait a minute or two, log out and then log in again. Note that your email address will be visible to all registered users!)",
"status": "OK", "status": "OK",
@ -636,9 +263,6 @@
{ {
"name": "Penpot", "name": "Penpot",
"url": "https://penpot.private.coffee", "url": "https://penpot.private.coffee",
"homemade": false,
"fork": false,
"tiny_description": "open-source design platform",
"short_description": "Penpot is an open-source design and prototyping platform.", "short_description": "Penpot is an open-source design and prototyping platform.",
"long_description": "Penpot is an open-source design and prototyping platform. It allows you to create designs and prototypes, and to collaborate with others.", "long_description": "Penpot is an open-source design and prototyping platform. It allows you to create designs and prototypes, and to collaborate with others.",
"status": "OK", "status": "OK",
@ -649,34 +273,12 @@
} }
], ],
"icon": "pencil-ruler", "icon": "pencil-ruler",
"exclude_from_index": true,
"exclude_from_simple": true
},
{
"name": "tldraw",
"url": "https://tldraw.private.coffee",
"homemade": false,
"fork": false,
"tiny_description": "collaborative whiteboard",
"short_description": "tldraw is a collaborative whiteboard.",
"long_description": "tldraw is a collaborative whiteboard. You can use it to draw and write with others in real-time.",
"status": "OK",
"links": [
{
"name": "Go to tldraw",
"url": "https://tldraw.private.coffee"
}
],
"icon": "pencil-ruler",
"exclude_from_index": false, "exclude_from_index": false,
"exclude_from_simple": false "exclude_from_simple": false
}, },
{ {
"name": "YOURLS", "name": "YOURLS",
"url": "https://pcof.fi", "url": "https://pcof.fi",
"homemade": false,
"fork": false,
"tiny_description": "URL shortener",
"short_description": "URL shortener for creating handy links.", "short_description": "URL shortener for creating handy links.",
"long_description": "Use our URL shortener at pcof.fi to turn long, complicated URLs into something more handy.", "long_description": "Use our URL shortener at pcof.fi to turn long, complicated URLs into something more handy.",
"status": "OK", "status": "OK",
@ -693,9 +295,6 @@
{ {
"name": "Rallly", "name": "Rallly",
"url": "https://rallly.private.coffee", "url": "https://rallly.private.coffee",
"homemade": false,
"fork": false,
"tiny_description": "collaborative scheduling (Doodle)",
"short_description": "Rallly is a free collaborative scheduling service for voting and polls.", "short_description": "Rallly is a free collaborative scheduling service for voting and polls.",
"long_description": "Rallly is a free collaborative scheduling service. It allows you to create polls and vote on them, similar to Doodle. Pro features are enabled for free after signing in.", "long_description": "Rallly is a free collaborative scheduling service. It allows you to create polls and vote on them, similar to Doodle. Pro features are enabled for free after signing in.",
"status": "OK", "status": "OK",
@ -712,38 +311,38 @@
{ {
"name": "LibreY", "name": "LibreY",
"url": "https://librey.private.coffee", "url": "https://librey.private.coffee",
"homemade": false,
"fork": false,
"tiny_description": "search engine",
"short_description": "Privacy-friendly metasearch engine.", "short_description": "Privacy-friendly metasearch engine.",
"long_description": "LibreY is an open-source, privacy-friendly metasearch engine. It allows you to search for web, image, video, torrents, and more, and it can also search onion sites.", "long_description": "LibreY is an open-source, privacy-friendly metasearch engine. It allows you to search for web, image, video, torrents, and more, and it can also search onion sites.",
"status": "OK", "status": "OK",
"links": [ "links": [
{ {
"name": "Go to LibreY", "name": "Go to LibreY",
"url": "https://librey.private.coffee", "url": "https://librey.private.coffee"
"alternatives": [
{
"name": "Tor",
"url": "http://librey.coffee2m3bjsrrqqycx6ghkxrnejl2q6nl7pjw2j4clchjj6uk5zozad.onion"
},
{
"name": "I2P",
"url": "http://xna5ydrj54ncvujz3f4c6y5i547hjwywygnr4uz6shz3f62suxwq.b32.i2p"
}
]
} }
], ],
"icon": "magnifying-glass", "icon": "magnifying-glass",
"exclude_from_index": false, "exclude_from_index": false,
"exclude_from_simple": false "exclude_from_simple": false
}, },
{
"name": "Overleaf",
"url": "https://overleaf.private.coffee",
"short_description": "Overleaf is an online LaTeX editor for writing and sharing documents.",
"long_description": "Overleaf is an online LaTeX editor for writing and sharing documents. It allows you to write documents in LaTeX, and to collaborate with others.",
"status": "OK",
"links": [
{
"name": "Go to Overleaf",
"url": "https://overleaf.private.coffee"
}
],
"icon": "leaf",
"exclude_from_index": false,
"exclude_from_simple": false
},
{ {
"name": "GotHub", "name": "GotHub",
"url": "https://gothub.private.coffee", "url": "https://gothub.private.coffee",
"homemade": false,
"fork": false,
"tiny_description": "tracking-free GitHub",
"short_description": "Alternative GitHub interface that respects privacy.", "short_description": "Alternative GitHub interface that respects privacy.",
"long_description": "Gothub is an alternative GitHub interface that respects your privacy. It is currently in alpha, but you can browse and download repositories, and you can also clone them using git+https (although the text on the main page would disagree).", "long_description": "Gothub is an alternative GitHub interface that respects your privacy. It is currently in alpha, but you can browse and download repositories, and you can also clone them using git+https (although the text on the main page would disagree).",
"status": "OK", "status": "OK",
@ -760,9 +359,6 @@
{ {
"name": "Binternet", "name": "Binternet",
"url": "https://binternet.private.coffee", "url": "https://binternet.private.coffee",
"homemade": false,
"fork": false,
"tiny_description": "tracking-free Pinterest",
"short_description": "Binternet is a privacy-friendly alternative front-end to Pinterest.", "short_description": "Binternet is a privacy-friendly alternative front-end to Pinterest.",
"long_description": "Binternet is a privacy-friendly alternative front-end to Pinterest. It allows you to browse Pinterest without being tracked.", "long_description": "Binternet is a privacy-friendly alternative front-end to Pinterest. It allows you to browse Pinterest without being tracked.",
"status": "OK", "status": "OK",
@ -775,120 +371,6 @@
"icon": "images", "icon": "images",
"exclude_from_index": false, "exclude_from_index": false,
"exclude_from_simple": false "exclude_from_simple": false
},
{
"name": "Moner.ooo",
"url": "https://monerooo.private.coffee",
"homemade": false,
"fork": "https://git.private.coffee/kumi/moner.ooo",
"tiny_description": "Monero/fiat exchange rates",
"short_description": "Moner.ooo is a service for checking Monero/fiat exchange rates.",
"long_description": "Moner.ooo is a service for checking Monero/fiat exchange rates. It allows you to see the current exchange rates for Monero in various fiat currencies.",
"status": "OK",
"links": [
{
"name": "Go to Moner.ooo",
"url": "https://monerooo.private.coffee"
}
],
"icon": "money-wavy",
"exclude_from_index": false,
"exclude_from_simple": false
},
{
"name": "httpbin",
"url": "https://httpbin.private.coffee",
"homemade": false,
"fork": false,
"tiny_description": "HTTP request testing service",
"short_description": "httpbin is a service for testing HTTP requests.",
"long_description": "httpbin is a service for testing HTTP requests. You can use it to see what your browser sends to a server, and to test various HTTP methods.",
"status": "OK",
"links": [
{
"name": "Go to httpbin",
"url": "https://httpbin.private.coffee"
}
],
"icon": "network",
"exclude_from_index": false,
"exclude_from_simple": false
},
{
"name": "Overpass",
"url": "https://overpass.private.coffee",
"homemade": false,
"fork": false,
"tiny_description": "OpenStreetMap API",
"short_description": "Overpass is an API for OpenStreetMap.",
"long_description": "Overpass is an API for OpenStreetMap. You can use it to query OpenStreetMap data, and to get the results in various formats.",
"status": "OK",
"links": [
{
"name": "Go to Overpass",
"url": "https://overpass.private.coffee"
}
],
"icon": "map-trifold",
"exclude_from_index": false,
"exclude_from_simple": false
},
{
"name": "GoogleDonts",
"url": "https://googledonts.private.coffee",
"homemade": "https://git.private.coffee/PrivateCoffee/googledonts",
"fork": false,
"tiny_description": "privacy-friendly Google Fonts proxy",
"short_description": "GoogleDonts is a privacy-friendly proxy to Google Fonts.",
"long_description": "GoogleDonts is a privacy-friendly proxy to Google Fonts. It allows you to use Google Fonts without being tracked by Google.",
"status": "OK",
"links": [
{
"name": "Go to GoogleDonts",
"url": "https://googledonts.private.coffee"
}
],
"icon": "hard-hat",
"exclude_from_index": false,
"exclude_from_simple": false
},
{
"name": "nocdnbs",
"url": "https://nocdnbs.private.coffee",
"homemade": "https://git.private.coffee/PrivateCoffee/nocdnbs",
"fork": false,
"tiny_description": "privacy-friendly cdnjs proxy",
"short_description": "nocdnbs is a privacy-friendly proxy to cdnjs.cloudflare.com",
"long_description": "nocdnbs is a privacy-friendly proxy to cdnjs.cloudflare.com. It allows you to use the cdnjs.cloudflare.com library without being tracked by Cloudflare.",
"status": "OK",
"links": [
{
"name": "Go to nocdnbs",
"url": "https://nocdnbs.private.coffee"
}
],
"icon": "hard-hat",
"exclude_from_index": false,
"exclude_from_simple": false
},
{
"name": "nobsdelivr",
"url": "https://nobsdelivr.private.coffee",
"homemade": "https://git.private.coffee/PrivateCoffee/nobsdelivr",
"fork": false,
"tiny_description": "privacy-friendly jsDelivr proxy",
"short_description": "nobsdelivr is a privacy-friendly proxy to cdn.jsdelivr.net",
"long_description": "nobsdelivr is a privacy-friendly proxy to cdn.jsdelivr.net. It allows you to use the cdn.jsdelivr.net library without being tracked by jsDelivr.",
"status": "OK",
"links": [
{
"name": "Go to nobsdelivr",
"url": "https://nobsdelivr.private.coffee"
}
],
"icon": "hard-hat",
"exclude_from_index": false,
"exclude_from_simple": false
} }
] ]
} }

View file

@ -30,12 +30,12 @@ def get_transparency_data(data, year=None, month=None, allow_current=False):
month = max(data[year].keys()) month = max(data[year].keys())
year = str(year) year = str(year)
month = str(month).zfill(2) month = str(month)
if ( if (
not allow_current not allow_current
and year == str(datetime.now().year) and year == str(datetime.now().year)
and month == str(datetime.now().month).zfill(2) and month == str(datetime.now().month)
): ):
try: try:
month = max([m for m in data[year].keys() if m != str(datetime.now().month)]) month = max([m for m in data[year].keys() if m != str(datetime.now().month)])

111
main.py
View file

@ -1,13 +1,10 @@
from jinja2 import Environment, FileSystemLoader, TemplateNotFound from jinja2 import Environment, FileSystemLoader, TemplateNotFound
import json import json
import pathlib import pathlib
import os
import datetime import datetime
import shutil import shutil
from http.server import SimpleHTTPRequestHandler
from socketserver import TCPServer
from threading import Thread
from argparse import ArgumentParser from argparse import ArgumentParser
from helpers.finances import ( from helpers.finances import (
@ -16,60 +13,37 @@ from helpers.finances import (
get_latest_month, get_latest_month,
) )
class StaticPageHandler(SimpleHTTPRequestHandler):
def __init__(self, *args, **kwargs):
super().__init__(*args, directory="build", **kwargs)
# Configure Jinja2 environment # Configure Jinja2 environment
env = Environment(loader=FileSystemLoader("templates")) env = Environment(loader=FileSystemLoader('templates'))
# Set up the output directory for static files # Set up the output directory for static files
output_dir = pathlib.Path("build") output_dir = pathlib.Path('build')
output_dir.mkdir(exist_ok=True, parents=True) output_dir.mkdir(exist_ok=True, parents=True)
# Define the icon filter # Define the icon filter
def icon(icon_name): def icon(icon_name):
icon_path = pathlib.Path("assets") / f"dist/icons/{icon_name}.svg" icon_path = pathlib.Path('assets') / f"dist/icons/{icon_name}.svg"
try: try:
with open(icon_path, "r", encoding="utf-8") as file: with open(icon_path, 'r', encoding='utf-8') as file:
file_content = file.read() file_content = file.read()
except FileNotFoundError: except FileNotFoundError:
file_content = "" file_content = ''
return file_content return file_content
env.filters['icon'] = icon
env.filters["icon"] = icon
# Filter for rendering a month name from a number
def month_name(month_number):
return datetime.date(1900, int(month_number), 1).strftime("%B")
env.filters["month_name"] = month_name
def render_template_to_file(template_name, output_name, **kwargs): def render_template_to_file(template_name, output_name, **kwargs):
try: try:
template = env.get_template(template_name) template = env.get_template(template_name)
output_path = output_dir / output_name output_path = output_dir / output_name
kwargs.setdefault("theme", "plain") with open(output_path, 'w', encoding='utf-8') as f:
with open(output_path, "w", encoding="utf-8") as f:
f.write(template.render(**kwargs)) f.write(template.render(**kwargs))
except TemplateNotFound: except TemplateNotFound:
print(f"Template {template_name} not found.") print(f"Template {template_name} not found.")
def generate_static_site(development_mode=False):
def generate_static_site(development_mode=False, theme="plain"):
# Common context # Common context
kwargs = { kwargs = {}
"timestamp": int(datetime.datetime.now().timestamp()),
"theme": theme,
}
if development_mode: if development_mode:
kwargs.update( kwargs.update(
{ {
@ -87,41 +61,27 @@ def generate_static_site(development_mode=False, theme="plain"):
(pathlib.Path(__file__).parent / "data" / "finances.json").read_text() (pathlib.Path(__file__).parent / "data" / "finances.json").read_text()
) )
# Load bridges data
bridges = json.loads(
(pathlib.Path(__file__).parent / "data" / "bridges.json").read_text()
)
# Iterate over all templates in the templates directory # Iterate over all templates in the templates directory
templates_path = pathlib.Path("templates") templates_path = pathlib.Path('templates')
for template_file in templates_path.glob("*.html"): for template_file in templates_path.glob('*.html'):
template_name = template_file.stem template_name = template_file.stem
context = kwargs.copy() context = kwargs.copy()
context["path"] = f"{template_name}.html" if template_name != "index" else ""
if template_name in ["index", "simple"]: if template_name in ["index", "simple"]:
context.update({"services": services}) context.update({"services": services})
if template_name == "bridges": if template_name == "membership":
context.update({"bridges": bridges})
if template_name.startswith("membership"):
allow_current = development_mode allow_current = development_mode
finances_month, finances_year = get_latest_month(finances, allow_current) finances_month, finances_year = get_latest_month(finances, allow_current)
finances_period = datetime.date(finances_year, finances_month, 1) finances_period = datetime.date(finances_year, finances_month, 1)
finances_period_str = finances_period.strftime("%B %Y") finances_period_str = finances_period.strftime("%B %Y")
finances_table = generate_transparency_table( finances_table = generate_transparency_table(
get_transparency_data( get_transparency_data(finances, finances_year, finances_month, allow_current)
finances, finances_year, finances_month, allow_current
) )
) context.update({
context.update(
{
"finances": finances_table, "finances": finances_table,
"finances_period": finances_period_str, "finances_period": finances_period_str,
} })
)
if template_name == "transparency": if template_name == "transparency":
finance_data = {} finance_data = {}
@ -130,13 +90,11 @@ def generate_static_site(development_mode=False, theme="plain"):
if year not in finance_data: if year not in finance_data:
finance_data[year] = {} finance_data[year] = {}
finance_data[year][month] = generate_transparency_table( finance_data[year][month] = generate_transparency_table(
get_transparency_data(finances, year, month, True) get_transparency_data(finances, year, month)
) )
context.update({"finances": finance_data}) context.update({"finances": finance_data})
render_template_to_file( render_template_to_file(f"{template_name}.html", f"{template_name}.html", **context)
f"{template_name}.html", f"{template_name}.html", **context
)
# Generate metrics # Generate metrics
balances = get_transparency_data(finances, allow_current=True)["end_balance"] balances = get_transparency_data(finances, allow_current=True)["end_balance"]
@ -150,40 +108,21 @@ def generate_static_site(development_mode=False, theme="plain"):
response += f'privatecoffee_balance{{currency="{currency}"}} {balance}\n' response += f'privatecoffee_balance{{currency="{currency}"}} {balance}\n'
metrics_path = output_dir / "metrics.txt" metrics_path = output_dir / "metrics.txt"
with open(metrics_path, "w", encoding="utf-8") as f: with open(metrics_path, 'w', encoding='utf-8') as f:
f.write(response) f.write(response)
# Copy static assets # Copy static assets
for folder in ["assets", "data"]: assets_src = pathlib.Path('assets')
src = pathlib.Path(folder) assets_dst = output_dir / 'assets'
dst = output_dir / folder if assets_dst.exists():
if dst.exists(): shutil.rmtree(assets_dst)
shutil.rmtree(dst) shutil.copytree(assets_src, assets_dst)
shutil.copytree(src, dst)
print("Static site generated successfully.") print("Static site generated successfully.")
if __name__ == "__main__": if __name__ == "__main__":
parser = ArgumentParser(description="Generate the private.coffee static site.") parser = ArgumentParser(description="Generate the private.coffee static site.")
parser.add_argument("--dev", action="store_true", help="Enable development mode") parser.add_argument("--dev", action="store_true", help="Enable development mode")
parser.add_argument(
"--serve", action="store_true", help="Serve the site after building"
)
parser.add_argument(
"--port", type=int, default=8000, help="Port to serve the site on"
)
parser.add_argument(
"--theme", type=str, default="plain", help="Theme to use for the site"
)
args = parser.parse_args() args = parser.parse_args()
generate_static_site(development_mode=args.dev, theme=args.theme) generate_static_site(development_mode=args.dev)
if args.serve:
server = TCPServer(("", args.port), StaticPageHandler)
print(f"Serving on http://localhost:{args.port}")
thread = Thread(target=server.serve_forever)
thread.start()
thread.join()

View file

@ -1 +1,2 @@
flask
jinja2 jinja2

View file

@ -3,73 +3,52 @@
<!-- This file was created as part of the Private.coffee project <!-- This file was created as part of the Private.coffee project
It is licensed under the MIT license It is licensed under the MIT license
For more information, please visit https://private.coffee --> For more information, please visit https://private.coffee -->
<head> <head>
<meta charset="utf8" /> <meta charset="utf8" />
<meta name="viewport" <meta
content="width=device-width, initial-scale=1.0, shrink-to-fit=no" /> name="viewport"
<meta name="description" content="width=device-width, initial-scale=1.0, shrink-to-fit=no"
content="Private.coffee is a privacy-focused non-profit association, dedicated to supporting privacy and digital sovereignty." /> />
<meta name="keywords" <title>{% block title %}{% endblock %} - Private.coffee</title>
content="privacy, digital sovereignty, non-profit, association, privacy-focused" /> <link rel="stylesheet" href="/assets/dist/css/bootstrap.min.css" />
<meta name="author" content="Private.coffee" /> <link rel="stylesheet" href="/assets/css/base.css" />
<meta property="og:title"
content="Private.coffee - Empowering Privacy with Open Source" />
<meta property="og:description"
content="Private.coffee is a privacy-focused non-profit association, dedicated to supporting privacy and digital sovereignty." />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://private.coffee/" />
<meta property="og:image"
content="https://private.coffee/assets/img/logo-inv_grad.png" />
<meta property="og:site_name" content="Private.coffee" />
<meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="Private.coffee" />
<meta name="twitter:description"
content="Private.coffee is a privacy-focused non-profit association, dedicated to supporting privacy and digital sovereignty." />
<meta name="twitter:image"
content="https://private.coffee/assets/img/logo-inv_grad.png" />
<link rel="icon" type="image/png" href="assets/img/logo-inv_grad.png" />
<title>
{% block title %}{% endblock title %}
- Private.coffee</title>
<link rel="stylesheet" href="assets/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="assets/css/base.css?v={{ timestamp }}" />
<link rel="stylesheet"
href="assets/css/theme/{{ theme }}.css?v={{ timestamp }}" />
</head> </head>
<body> <body>
<nav class="navbar navbar-expand-md py-3 navbar-light" id="mainNav"> <nav
class="navbar navbar-expand-md py-3 navbar-light"
id="mainNav"
>
<div class="container"> <div class="container">
<div class="row d-lg-flex align-items-lg-center"> <div class="row d-lg-flex align-items-lg-center">
<div class="col p-0"> <div class="col p-0">
<a href="/"> <a href="/"
<div id="smallLogoContainer"></div> ><img src="/assets/img/logo-inv_grad.svg" style="height: 60px"
</a> /></a>
</div> </div>
<div class="col d-flex"> <div class="col d-flex">
<a class="navbar-brand d-flex align-items-center" href="/"> <a class="navbar-brand d-flex align-items-center" href="/">
<p class="mb-0" <p
style="line-height: 1.2rem; class="mb-0"
color: var(--bs-tertiary-color)"> style="line-height: 1.2rem; color: var(--bs-tertiary-color)"
<span class="ps-2 fancy-text-primary"><span style="color: rgb(35, 35, 35)">Private.coffee</span></span> >
<br class="that-br" /> <span class="ps-2 fancy-text-primary"
<span class="ps-2 slogan">Empowering Privacy with Open Source</span> ><span style="color: rgb(35, 35, 35)"
>Private.coffee</span
></span
><br class="that-br" /><span class="ps-2 slogan"
>Empowering Privacy with Open Source</span
>
</p> </p>
</a> </a>
</div> </div>
</div> </div>
<div class="navbar" id="navcol-1"> <div class="navbar" id="navcol-1">
<ul class="navbar-nav mx-auto"> <ul class="navbar-nav mx-auto">
<li class="nav-item"> <li class="nav-item"><a class="nav-link active" href="/index.html">Home</a></li>
<a class="nav-link active" href="/index.html">Home</a> <li class="nav-item"><a class="nav-link" href="https://status.private.coffee/">Status</a></li>
</li> </ul><a class="btn btn-primary shadow navbar-btn" role="button" href="/membership.html">JOIN &amp; SUPPORT</a>
<li class="nav-item">
<a class="nav-link" href="https://status.private.coffee/">Status</a>
</li>
</ul>
<a class="btn btn-primary shadow navbar-btn"
role="button"
href="/membership.html">JOIN &amp; SUPPORT</a>
</div>
</div> </div>
</nav> </nav>
{% if warning %}{{ warning|safe }}{% endif %} {% if warning %}{{ warning|safe }}{% endif %}
@ -77,41 +56,40 @@
<footer class="bg-primary-gradient"> <footer class="bg-primary-gradient">
<div class="container py-4 py-lg-5"> <div class="container py-4 py-lg-5">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-sm-4 col-md-3 text-center text-lg-start d-flex flex-column"> <div
class="col-sm-4 col-md-3 text-center text-lg-start d-flex flex-column"
>
<h3 class="fs-6 fw-bold">Legal Stuff</h3> <h3 class="fs-6 fw-bold">Legal Stuff</h3>
<ul class="list-unstyled"> <ul class="list-unstyled">
<li> <li><a href="/legal.html">Legal Notice</a></li>
<a href="/legal.html">Legal Notice</a> <li><a href="/privacy.html">Privacy Notice</a></li>
</li> <li><a href="/terms.html">Terms of Service</a></li>
<li>
<a href="/privacy.html">Privacy Notice</a>
</li>
<li>
<a href="/terms.html">Terms of Service</a>
</li>
</ul> </ul>
</div> </div>
<div class="col-sm-4 col-md-3 text-center text-lg-start d-flex flex-column"></div> <div
<div class="col-lg-3 text-center text-lg-start d-flex flex-column align-items-center order-first align-items-lg-start order-lg-last"> class="col-sm-4 col-md-3 text-center text-lg-start d-flex flex-column"
></div>
<div
class="col-lg-3 text-center text-lg-start d-flex flex-column align-items-center order-first align-items-lg-start order-lg-last"
>
<div class="fw-bold d-flex align-items-center mb-2"> <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">{{ "coffee" | icon | safe }}</span><span>Private.coffee</span> <span
class="bs-icon-sm bs-icon-circle bs-icon-primary d-flex justify-content-center align-items-center bs-icon me-2"
>{{ "coffee" | icon | safe }}</span
><span>Private.coffee</span>
</div> </div>
<p class="text-muted"> <p class="text-muted">
Private.coffee is a privacy-focused non-profit association, Private.coffee is a privacy-focused non-profit association, dedicated
dedicated to supporting privacy and digital sovereignty. to supporting privacy and digital sovereignty.
</p> </p>
</div> </div>
</div> </div>
<hr /> <hr />
<div class="text-muted d-flex justify-content-between align-items-center pt-3"> <div
class="text-muted d-flex justify-content-between align-items-center pt-3"
>
<p class="mb-0">Made with ❤️ and ☕ by Private.coffee</p> <p class="mb-0">Made with ❤️ and ☕ by Private.coffee</p>
<p class="mb-0"> <p class="mb-0">{{ "rainbow" | icon | safe }}</p>
<a href="https://git.private.coffee/privatecoffee/privatecoffee-website">
<img src="https://shields.private.coffee/gitea/last-commit/privatecoffee/privatecoffee-website?gitea_url=https://git.private.coffee&logo=forgejo" />
</a>
<a href="https://pride.coffee">{{ "rainbow" | icon | safe }}</a>
</p>
</div>
</div> </div>
</footer> </footer>
</body> </body>

View file

@ -1,29 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bridges and bots</title>
</head>
<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;">Bridges and bots</h2>
<p>These are the bridges and bots available to Private.coffee Matrix users:</p>
<ul style="list-style: none; padding: 0;">
{% for bridge in bridges.bridges %}
<li style="padding: 8px 0;">
<a style="color: #1a5dab;
text-decoration: none"
href="https://matrix.pcof.fi/#/{{ bridge.mxid }}">{{ bridge.name }}</a> - {{ bridge.mxid }}
</li>
{% endfor %}
</ul>
</div>
</body>
</html>

View file

@ -1,6 +1,4 @@
{% extends "base.html" %} {% extends "base.html" %} {% block title %}Home{% endblock %} {% block content
{% block title %}Home{% endblock title %}
{% block content
%} %}
<header class="bg-primary-gradient"> <header class="bg-primary-gradient">
<div class="container pt-4 pt-xl-5 pb-4 pb-xl-5"> <div class="container pt-4 pt-xl-5 pb-4 pb-xl-5">
@ -9,12 +7,9 @@
<div class="text-center"> <div class="text-center">
<h2>Empowering Privacy with Open Source</h2> <h2>Empowering Privacy with Open Source</h2>
</div> </div>
<p class="text-center special-header fancy-text-primary mb-0" <p class="text-center special-header fancy-text-primary mb-0" style="font-weight: 500;">Private.coffee</p>
style="font-weight: 500">Private.coffee</p>
</div>
<div class="col-12 col-lg-10 mx-auto justify-content-center d-flex">
<div id="logoContainer"></div>
</div> </div>
<div class="col-12 col-lg-10 mx-auto justify-content-center d-flex"><img class="mx-auto" src="/assets/img/logo-inv_grad.svg" style="max-width: 400px;width: 80vw;"></div>
</div> </div>
</div> </div>
</header> </header>
@ -30,56 +25,52 @@
</div> </div>
</div> </div>
<div class="py-5 p-lg-5"> <div class="py-5 p-lg-5">
<div class="accordion"> <div
{% for service in services.services %} class="row row-cols-1 row-cols-md-2 row-cols-lg-3 mx-auto"
{% if not style="max-width: 1200px"
>
{% for service in services.services %} {% if not
service.exclude_from_index %} service.exclude_from_index %}
<details class="accordion-item"> <div class="col mb-5">
<summary class="accordion-header"> <div class="card shadow-sm">
<div class="card-body px-4 py-5 px-md-5">
{% if service.icon %} {% if service.icon %}
<div class="bs-icon-lg d-flex justify-content-center align-items-center bs-icon" <div
title="{{ service.name }}">{{ service.icon | icon | safe }}</div> class="bs-icon-lg d-flex justify-content-center align-items-center mb-3 bs-icon"
style="top: 1rem; right: 1rem; position: absolute"
>
{{ service.icon | icon | safe }}
</div>
{% endif %} {% endif %}
{{ service.name }} <h5 class="fw-bold card-title">{{ service.name }}</h5>
{% if service.tiny_description %} <p class="text-muted card-text mb-4">
- {{ {{ service.long_description }}
service.tiny_description }} </p>
{% endif %} {% for link in service.links %} {% if link.alternatives %}
{% if service.homemade %} <div class="dropdown">
<a href="{{ service.homemade }}"> <div class="btn btn-primary shadow">
<div class="bs-icon-sm 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-sm homemade" <a class="main-link" href="{{ link.url }}">
title="Made by Private.coffee">{{ "coffee" | icon | safe }}</div> {{ link.name }}
</a> </a>
{% endif %}
{% if service.fork %}
<a href="{{ service.fork }}">
<div class="bs-icon-sm 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-sm fork"
title="Runs on a fork of the original software">{{ "git-branch" | icon | safe }}</div>
</a>
{% endif %}
</summary>
<div class="accordion-body">
<p class="text-muted card-text mb-4">{{ service.long_description }}</p>
{% for link in service.links %}
{% if link.alternatives %}
<div class="button-wrapper dropdown">
<div class="btn btn-primary w-100 shadow">
<a class="main-link" href="{{ link.url }}">{{ link.name }}</a>
<div class="dropdown-toggle-area">&#9660;</div> <div class="dropdown-toggle-area">&#9660;</div>
</div> </div>
<div class="dropdown-content"> <div class="dropdown-content">
{% for alternative in link.alternatives %}<a href="{{ alternative.url }}">{{ alternative.name }}</a>{% endfor %} {% for alternative in link.alternatives %}
<a href="{{ alternative.url }}">{{ alternative.name }}</a>
{% endfor %}
</div> </div>
</div> </div>
{% else %} {% else %}
<a class="button-wrapper btn btn-primary shadow w-100 text-center" <a
href="{{ link.url }}">{{ link.name }}</a> class="btn btn-primary shadow w-100 text-center"
{% endif %} href="{{ link.url }}"
{% endfor %} >{{ link.name }}</a
>
{% endif %} {% endfor %}
</div> </div>
</details> </div>
{% endif %} </div>
{% endfor %} {% endif %} {% endfor %}
</div> </div>
</div> </div>
</div> </div>
@ -105,17 +96,29 @@
<div class="card bg-primary-subtle"> <div class="card bg-primary-subtle">
<div class="card-body text-center px-4 py-5 px-md-5"> <div class="card-body text-center px-4 py-5 px-md-5">
<p class="fw-bold text-primary card-text mb-2">Join or donate</p> <p class="fw-bold text-primary card-text mb-2">Join or donate</p>
<h5 class="fw-bold card-title mb-3">Be a part of the open source community!</h5> <h5 class="fw-bold card-title mb-3">
<a class="btn btn-primary btn-sm" href="/membership.html">Learn more</a> Be a part of the open source community!
</h5>
<a class="btn btn-primary btn-sm" href="/membership.html"
>Learn more</a
>
</div> </div>
</div> </div>
</div> </div>
<div class="col mb-4"> <div class="col mb-4">
<div class="card bg-secondary-subtle"> <div class="card bg-secondary-subtle">
<div class="card-body text-center px-4 py-5 px-md-5"> <div class="card-body text-center px-4 py-5 px-md-5">
<p class="fw-bold text-secondary card-text mb-2">Private Hosting</p> <p class="fw-bold text-secondary card-text mb-2">
<h5 class="fw-bold card-title mb-3">Interested in Hosting Services?</h5> Private Hosting
<a class="btn btn-secondary btn-sm" href="mailto:support@private.coffee">Get in touch</a> </p>
<h5 class="fw-bold card-title mb-3">
Interested in Hosting Services?
</h5>
<a
class="btn btn-secondary btn-sm"
href="mailto:support@private.coffee"
>Get in touch</a
>
</div> </div>
</div> </div>
</div> </div>
@ -132,10 +135,16 @@
</div> </div>
</div> </div>
<div class="row d-flex justify-content-center"> <div class="row d-flex justify-content-center">
<div class="col-md-4 col-xl-4 d-flex justify-content-center justify-content-xl-start"> <div
<div class="d-flex flex-wrap flex-md-column justify-content-md-start align-items-md-start h-100"> 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="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"> <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 }} {{ "envelope" | icon | safe }}
</div> </div>
<div class="px-2"> <div class="px-2">
@ -147,16 +156,25 @@
</div> </div>
</div> </div>
<div class="row d-flex justify-content-center"> <div class="row d-flex justify-content-center">
<div class="col-md-4 col-xl-4 d-flex justify-content-center justify-content-xl-start"> <div
<div class="d-flex flex-wrap flex-md-column justify-content-md-start align-items-md-start h-100"> 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="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"> <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 }} {{ "matrix-logo" | icon | safe }}
</div> </div>
<div class="px-2"> <div class="px-2">
<h6 class="fw-bold mb-0">Matrix</h6> <h6 class="fw-bold mb-0">Matrix</h6>
<p class="text-muted mb-0"> <p class="text-muted mb-0">
<a href="https://matrix.pcof.fi/#/#private.coffee:private.coffee">#private.coffee:private.coffee</a> <a
href="https://matrix.pcof.fi/#/#private.coffee:private.coffee"
>#private.coffee:private.coffee</a
>
</p> </p>
</div> </div>
</div> </div>
@ -165,4 +183,4 @@
</div> </div>
</div> </div>
</section> </section>
{% endblock content %} {% endblock %}

View file

@ -1,11 +1,13 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block title %}Legal Notice{% endblock title %} {% block title %}Legal Notice{% endblock %}
{% block content %} {% block content %}
<section> <section>
<div class="container py-5"> <div class="container py-5">
<div class="row align-items-center"> <div class="row align-items-center">
<div class="col"> <div class="col">
<p class="text-end special-header fancy-text-primary mb-0">Legal Notice</p> <p class="text-end special-header fancy-text-primary mb-0">
Legal Notice
</p>
</div> </div>
<div class="col"> <div class="col">
<p class="text-start mb-1" style="font-size: 1.6rem"> <p class="text-start mb-1" style="font-size: 1.6rem">
@ -16,21 +18,17 @@
</p> </p>
</div> </div>
</div> </div>
<div class="container"> <div class="container">
<p>This is a legal notice for the website private.coffee</p> <p>This is a legal notice for the website private.coffee</p>
<p>The website private.coffee is run by the following entity:</p> <p>The website private.coffee is run by the following entity:</p>
<address> <address>
Private.coffee &dash; Verein zur Förderung von Privatsphäre und Private.coffee &dash; Verein zur Förderung von Privatsphäre und
digitaler Souver&auml;nit&auml;t digitaler Souver&auml;nit&auml;t<br />
<br /> c/o Klaus-Uwe Mitterer<br />
c/o Klaus-Uwe Mitterer Gartengasse 22/7/3<br />
<br /> 8010 Graz<br />
Gartengasse 22/7/3 Austria<br />
<br />
8010 Graz
<br />
Austria
<br />
</address> </address>
<p>Central Register of Associations (ZVR) Number: 1758485319</p> <p>Central Register of Associations (ZVR) Number: 1758485319</p>
<p> <p>
@ -40,4 +38,4 @@
</div> </div>
</div> </div>
</section> </section>
{% endblock content %} {% endblock %}

View file

@ -1,11 +0,0 @@
{% extends "membership.html" %}
{% block serviceinfo %}
<div class="alert alert-info">
<p>
<strong>Welcome to Private.coffee!</strong> Rallly Pro is free for all logged-in users. Upon first login, it may take up to five minutes for your account to be upgraded. If you have any issues, please contact us at <a href="mailto:support@private.coffee">support@private.coffee</a>
</p>
<p>
If you find our services useful, please consider supporting us through a donation or becoming a supporting member. This will help us keep our free services running and improve our offerings. See below for more information.
</p>
</div>
{% endblock serviceinfo %}

View file

@ -1,7 +1,4 @@
{% extends "base.html" %} {% extends "base.html" %} {% block title %}Membership / Donations{% endblock %}
{% block title %}
Membership / Donations
{% endblock title %}
{% block content %} {% block content %}
<div class="container my-5"> <div class="container my-5">
<div class="text-center mb-5"> <div class="text-center mb-5">
@ -13,7 +10,7 @@
our services and reach more people. our services and reach more people.
</p> </p>
</div> </div>
{% block serviceinfo %}{% endblock serviceinfo %}
<div class="row"> <div class="row">
<div class="col-md-4 mb-4"> <div class="col-md-4 mb-4">
<div class="card shadow-sm"> <div class="card shadow-sm">
@ -25,11 +22,16 @@
expenses. This allows us to provide services to our members and the expenses. This allows us to provide services to our members and the
public. public.
</p> </p>
<p class="card-text">Membership starts at € 5 / month!</p> <p class="card-text">
<a href="https://pcof.fi/join" class="btn btn-primary">Join us now!</a> Membership starts at € 5 / month!
</p>
<a href="https://pcof.fi/join" class="btn btn-primary">
Join us now!
</a>
</div> </div>
</div> </div>
</div> </div>
<div class="col-md-4 mb-4"> <div class="col-md-4 mb-4">
<div class="card shadow-sm"> <div class="card shadow-sm">
<div class="card-body"> <div class="card-body">
@ -39,18 +41,13 @@
direct donation to our bank account. Your donation will be used to direct donation to our bank account. Your donation will be used to
fund our activities and expand our services. fund our activities and expand our services.
</p> </p>
<p class="card-text"> <p class="card-text"><b>Account holder:</b> Private.coffee</p>
<b>Account holder:</b> Private.coffee <p class="card-text"><b>IBAN:</b> AT35 2081 5000 4554 0812</p>
</p> <p class="card-text"><b>BIC:</b> STSPAT2GXXX</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>
</div> </div>
<div class="col-md-4 mb-4"> <div class="col-md-4 mb-4">
<div class="card shadow-sm"> <div class="card shadow-sm">
<div class="card-body"> <div class="card-body">
@ -65,7 +62,9 @@
</p> </p>
<p class="card-text"> <p class="card-text">
<b>Monero (XMR):</b> <b>Monero (XMR):</b>
<code>487Ny4iBk2pKGJwjyYrumFD8xFmrS6jCSXNA8e5EvVJ49GyS54CRDVz514MBnXgNT1EioKYiagHs33sLzUAFj8i3Pwg3AMS</code> <code
>487Ny4iBk2pKGJwjyYrumFD8xFmrS6jCSXNA8e5EvVJ49GyS54CRDVz514MBnXgNT1EioKYiagHs33sLzUAFj8i3Pwg3AMS</code
>
</p> </p>
<p class="card-text"> <p class="card-text">
<b>Ethereum (ETH):</b> <code>Coming soon&trade;</code> <b>Ethereum (ETH):</b> <code>Coming soon&trade;</code>
@ -78,6 +77,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="card shadow-sm mt-4"> <div class="card shadow-sm mt-4">
<div class="card-body"> <div class="card-body">
<h5 class="card-title">Transparency Report for {{ finances_period }}</h5> <h5 class="card-title">Transparency Report for {{ finances_period }}</h5>
@ -94,22 +94,30 @@
</p> </p>
</div> </div>
</div> </div>
<div class="card shadow-sm mt-4"> <div class="card shadow-sm mt-4">
<div class="card-body"> <div class="card-body">
<h5>Central Register of Associations (ZVR) Number: 1758485319</h5> <h5>Central Register of Associations (ZVR) Number: 1758485319</h5>
<p> <p>
Our statutes can be found in our Git Our statutes can be found in our Git
<a href="https://git.private.coffee/PrivateCoffee/statuten">in German (legally binding)</a> <a href="https://git.private.coffee/PrivateCoffee/statuten"
>in German (legally binding)</a
>
and and
<a href="https://git.private.coffee/PrivateCoffee/Statuten/src/branch/english">in English</a>. <a
href="https://git.private.coffee/PrivateCoffee/Statuten/src/branch/english"
>in English</a
>.
</p> </p>
<p class="contact-info" id="contact-info"> <p class="contact-info" id="contact-info">
Interested in joining the association? Reach out via Interested in joining the association? Reach out via
<a href="mailto:support@private.coffee">email</a> or <a href="mailto:support@private.coffee">email</a> or
<a href="https://matrix.pcof.fi/#/#private.coffee:private.coffee">Matrix</a> <a href="https://matrix.pcof.fi/#/#private.coffee:private.coffee"
>Matrix</a
>
for more information. for more information.
</p> </p>
</div> </div>
</div> </div>
</div> </div>
{% endblock content %} {% endblock %}

View file

@ -1,5 +1,4 @@
{% extends "base.html" %} {% extends "base.html" %} {% block title %}Privacy Policy{% endblock %}
{% block title %}Privacy Policy{% endblock %}
{% block content %} {% block content %}
<div class="container"> <div class="container">
<div class="text-center mb-5"> <div class="text-center mb-5">
@ -24,16 +23,11 @@
<p>The data controller for private.coffee is:</p> <p>The data controller for private.coffee is:</p>
<address> <address>
Private.coffee &dash; Verein zur Förderung von Privatsphäre und digitaler Private.coffee &dash; Verein zur Förderung von Privatsphäre und digitaler
Souver&auml;nit&auml;t Souver&auml;nit&auml;t<br />
<br /> c/o Klaus-Uwe Mitterer<br />
c/o Klaus-Uwe Mitterer Gartengasse 22/7/3<br />
<br /> 8010 Graz<br />
Gartengasse 22/7/3 Austria<br />
<br />
8010 Graz
<br />
Austria
<br />
</address> </address>
<p>Central Register of Associations (ZVR) Number: 1758485319</p> <p>Central Register of Associations (ZVR) Number: 1758485319</p>
<p> <p>
@ -77,7 +71,9 @@
<li>Providing support to you</li> <li>Providing support to you</li>
<li>Processing donations and memberships</li> <li>Processing donations and memberships</li>
</ul> </ul>
<p>All of those are what is called "legitimate interests" in legal speak.</p> <p>
All of those are what is called "legitimate interests" in legal speak.
</p>
<p> <p>
We do not use your data for any other purposes, including marketing, We do not use your data for any other purposes, including marketing,
advertising, or tracking, we do not share your data with third parties advertising, or tracking, we do not share your data with third parties
@ -157,7 +153,10 @@
If you are not satisfied with our response, or believe that we are 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 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 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 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, 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. so please do get in touch with us if you have any questions or concerns.
</p> </p>

View file

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

View file

@ -6,55 +6,25 @@
<title>Private.coffee</title> <title>Private.coffee</title>
</head> </head>
<body> <body>
<div style="font-family: Arial, sans-serif; <div style="font-family: Arial, sans-serif; background-color: #f2f2f2; color: #333; line-height: 1.6; padding: 20px; max-width: 600px; margin: auto;">
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> <h2 style="color: #333;">Welcome to Private.coffee</h2>
<p>Thanks for using our Element instance! Now, why don't you join our rooms?</p> <p>Thanks for using our Element instance! Now, why don't you join our rooms?</p>
<ul style="list-style: none; padding: 0;"> <ul style="list-style: none; padding: 0;">
<li style="padding: 8px 0;"> <li style="padding: 8px 0;"><a style="color: #1a5dab; text-decoration: none;" href="https://element.private.coffee/#/#coffeespace:private.coffee">#coffeespace:private.coffee</a> - The Private.coffee Space, containing all rooms</li>
<a style="color: #1a5dab; <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>
text-decoration: none" <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>
href="https://element.private.coffee/#/#coffeespace:private.coffee">#coffeespace:private.coffee</a> - The Private.coffee Space, containing all rooms <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>
</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> </ul>
<hr> <hr>
<p>Private.coffee operates a collection of services that respect your privacy, here are some others:</p> <p>Private.coffee operates a collection of services that respect your privacy, here are some others:</p>
<ul style="list-style: none; padding: 0;"> <ul style="list-style: none; padding: 0;">
{% for service in services.services %} {% for service in services.services %}
{% if not service.exclude_from_simple %} {% if not service.exclude_from_simple %}
<li style="padding: 8px 0;"> <li style="padding: 8px 0;"><a style="color: #1a5dab; text-decoration: none;" href="{{ service.url }}">{{ service.name }}</a> - {{ service.short_description }}</li>
<a style="color: #1a5dab;
text-decoration: none"
href="{{ service.url }}">{{ service.name }}</a> - {{ service.short_description }}
</li>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
</ul> </ul>
<p> <p>For hosting inquiries for privacy-related, social, or wholesome projects, <a href="mailto:support@private.coffee" style="color: #1a5dab; text-decoration: none;">get in touch</a>!</p>
For hosting inquiries for privacy-related, social, or wholesome projects, <a href="mailto:support@private.coffee"
style="color: #1a5dab;
text-decoration: none">get in touch</a>!
</p>
</div> </div>
</body> </body>
</html> </html>

View file

@ -15,16 +15,11 @@
<p>The website private.coffee is run by:</p> <p>The website private.coffee is run by:</p>
<address> <address>
Private.coffee &dash; Verein zur Förderung von Privatsphäre und digitaler Private.coffee &dash; Verein zur Förderung von Privatsphäre und digitaler
Souver&auml;nit&auml;t Souver&auml;nit&auml;t<br />
<br /> c/o Klaus-Uwe Mitterer<br />
c/o Klaus-Uwe Mitterer Gartengasse 22/7/3<br />
<br /> 8010 Graz<br />
Gartengasse 22/7/3 Austria<br />
<br />
8010 Graz
<br />
Austria
<br />
</address> </address>
<p>Central Register of Associations (ZVR) Number: 1758485319</p> <p>Central Register of Associations (ZVR) Number: 1758485319</p>
<p> <p>

View file

@ -1,5 +1,4 @@
{% extends "base.html" %} {% extends "base.html" %} {% block title %}Membership / Donations{% endblock %}
{% block title %}Membership / Donations{% endblock %}
{% block content %} {% block content %}
<div class="container my-5"> <div class="container my-5">
<div class="text-center mb-5"> <div class="text-center mb-5">
@ -10,15 +9,17 @@
each month since our inception. each month since our inception.
</p> </p>
</div> </div>
{% for year, year_data in finances.items() %} {% for year, year_data in finances.items() %}
{% for month, month_data in year_data.items() %} {% for month, month_data in year_data.items() %}
<div class="card shadow-sm mt-4"> <div class="card shadow-sm mt-4">
<div class="card-body"> <div class="card-body">
<h5 class="card-title">Transparency Report for {{ month|month_name }} {{ year }}</h5> <h5 class="card-title">Transparency Report for {{ month }}/{{ year }}</h5>
<div class="table-responsive">{{ month_data|safe }}</div> <div class="table-responsive">{{ month_data|safe }}</div>
</div> </div>
</div> </div>
{% endfor %} {% endfor %}
{% endfor %} {% endfor %}
</div> </div>
{% endblock %} {% endblock %}