mirror of
https://github.com/Lissy93/awesome-privacy.git
synced 2026-03-11 08:55:33 +00:00
Loads of updates
This commit is contained in:
parent
5181632fde
commit
3a7427b00f
11 changed files with 201 additions and 89 deletions
|
|
@ -6,6 +6,9 @@
|
|||
|
||||
|
||||
export const iconMap: Record<string, IconDefinition> = {
|
||||
// Branding
|
||||
logo: solidIcons.faEyeSlash,
|
||||
|
||||
// GitHub Stat Icons
|
||||
github: brands.faGithubAlt,
|
||||
stars: solidIcons.faStar,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,13 @@
|
|||
---
|
||||
import FontAwesome from "@components/form/FontAwesome.svelte"
|
||||
|
||||
---
|
||||
|
||||
<div class="nav">
|
||||
<a href="/"><h1>Awesome Privacy</h1></a>
|
||||
<a href="/" class="homepage">
|
||||
<FontAwesome iconName="logo" />
|
||||
<h1>Awesome Privacy</h1>
|
||||
</a>
|
||||
<nav>
|
||||
<a href="/browse">Browse</a>
|
||||
<a href="/search">Search</a>
|
||||
|
|
@ -20,8 +25,11 @@
|
|||
gap: 1rem;
|
||||
border-bottom: 2px solid var(--foreground);
|
||||
|
||||
a {
|
||||
.homepage {
|
||||
text-decoration: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 0.5rem;
|
||||
h1 {
|
||||
margin: 0;
|
||||
font-size: 2.4rem;
|
||||
|
|
@ -29,6 +37,18 @@
|
|||
color: var(--foreground);
|
||||
font-family: "Lekton", sans-serif;
|
||||
}
|
||||
:global(svg) {
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
color: var(--accent-3);
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
&:hover {
|
||||
:global(svg) {
|
||||
color: var(--accent);
|
||||
transform: scale(1.05);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nav {
|
||||
|
|
|
|||
|
|
@ -4,23 +4,61 @@ import NavBar from '@components/scafold/NavBar.astro';
|
|||
import Footer from '@components/scafold/Footer.astro';
|
||||
|
||||
interface Props {
|
||||
title: string;
|
||||
hideNav?: boolean;
|
||||
title?: string; // Page title
|
||||
description?: string; // Overide description tag
|
||||
keywords?: string; // Overide keywords tag
|
||||
hideNav?: boolean; // Don't show the navbar (just homepage)
|
||||
author?: string; // Author of the content
|
||||
}
|
||||
|
||||
const { title, hideNav } = Astro.props;
|
||||
const {
|
||||
title='Awesome Privacy | The Ultimate List of Private Apps',
|
||||
description='Your guide to finding privacy-respecting alternatives to popular software and services.',
|
||||
keywords='security, privacy, awesome privacy, data collection, free software, open source, privacy tools, privacy respecting software',
|
||||
hideNav=false,
|
||||
author='Alicia Sykes'
|
||||
} = Astro.props;
|
||||
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="description" content="Astro description" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
<!-- Core info -->
|
||||
<title>{title}</title>
|
||||
<meta name="description" content={description}>
|
||||
<meta name="keywords" content={keywords}>
|
||||
<meta name="author" content={author}>
|
||||
|
||||
<!-- Page info, viewport, Astro credit -->
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
|
||||
<!-- Icons and colors -->
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<link rel="icon" type="image/png" sizes="64x64" href="/favicon.png">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
|
||||
|
||||
<!-- Social media meta tags (Open Graphh + Twitter) -->
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:url" content="https://awesome-privacy.xyz">
|
||||
<meta property="og:title" content={title}>
|
||||
<meta property="og:description" content={description}>
|
||||
<meta property="og:image" content="/banner.png">
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta name="twitter:url" content="https://awesome-privacy.xyz">
|
||||
<meta name="twitter:title" content={title}>
|
||||
<meta name="twitter:description" content={description}>
|
||||
<meta name="twitter:image" content="/banner.png">
|
||||
|
||||
<!-- Non-tracking hit counter -->
|
||||
<script defer
|
||||
type="text/partytown"
|
||||
data-domain="awesome-privacy.xyz"
|
||||
src="https://no-track.as93.net/js/script.js">
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
{!hideNav && <NavBar /> }
|
||||
|
|
|
|||
|
|
@ -17,11 +17,58 @@ interface Props {
|
|||
notableMentions?: ShortService[] | string,
|
||||
furtherInfo?: string,
|
||||
wordOfWarning?: string,
|
||||
alternativeTo?: string[];
|
||||
categoryName: string,
|
||||
otherSections: Section[],
|
||||
}
|
||||
|
||||
const { slug, title, otherSections, services, notableMentions, furtherInfo, wordOfWarning, categoryName, intro } = Astro.props;
|
||||
const {
|
||||
title, otherSections, services, notableMentions, furtherInfo, wordOfWarning,
|
||||
alternativeTo, categoryName, intro,
|
||||
} = Astro.props;
|
||||
|
||||
/**
|
||||
* Make a list of keywords, for the <meta keywords> tag
|
||||
*/
|
||||
const makeKeyWordTag = () => {
|
||||
const keywords = [];
|
||||
keywords.push(`free and open source ${title} software`);
|
||||
keywords.push(`private ${title} comparison`);
|
||||
alternativeTo?.forEach((alt: string) => {
|
||||
keywords.push(`privacy-respecting ${alt} alternative`);
|
||||
keywords.push(`free open source ${alt} alternative`);
|
||||
});
|
||||
services.forEach((serv: Service) => {
|
||||
keywords.push(serv.name);
|
||||
});
|
||||
keywords.push('ad free');
|
||||
keywords.push('open source software');
|
||||
keywords.push('privacy respecting apps');
|
||||
return keywords.join(', ');
|
||||
};
|
||||
|
||||
/**
|
||||
* Make a page title
|
||||
*/
|
||||
const makePageTitle = () => {
|
||||
return `${title} | Awesome Privacy`;
|
||||
};
|
||||
|
||||
/**
|
||||
* Make a string page intro, for the description tag
|
||||
*/
|
||||
const makeDescriptionTag = () => {
|
||||
let description = `A list of privacy respecting ${title}. `;
|
||||
if (services.length > 0) {
|
||||
const serviceList = services.map((serv: Service) => serv.name);
|
||||
description += `Compare ${serviceList.join(', ')} and more private apps and services. `
|
||||
} else {
|
||||
description += `Find private apps and services. This section is still a work in progress. `;
|
||||
}
|
||||
description += 'All this, and much more at Awesome Privacy, '
|
||||
description += 'the free and open source list of private software alternatives.';
|
||||
return description;
|
||||
};
|
||||
|
||||
export async function getStaticPaths() {
|
||||
|
||||
|
|
@ -37,6 +84,7 @@ const pages = await fetchData().then((data) => {
|
|||
notableMentions: section.notableMentions,
|
||||
furtherInfo: section.furtherInfo,
|
||||
wordOfWarning: section.wordOfWarning,
|
||||
alternativeTo: section.alternativeTo,
|
||||
categoryName: category.name,
|
||||
otherSections: category.sections,
|
||||
}));
|
||||
|
|
@ -45,11 +93,8 @@ const pages = await fetchData().then((data) => {
|
|||
return results;
|
||||
});
|
||||
|
||||
return pages.map(({ slug, title, otherSections, services, notableMentions, furtherInfo, wordOfWarning, categoryName, intro }) => {
|
||||
return {
|
||||
params: { section: slug },
|
||||
props: { title, otherSections, services, notableMentions, furtherInfo, wordOfWarning, categoryName, intro },
|
||||
};
|
||||
return pages.map((props: Props) => {
|
||||
return {params: { section: props.slug }, props };
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -64,7 +109,7 @@ const { previous, next } = makePaginationLinks();
|
|||
|
||||
---
|
||||
|
||||
<Layout title="Awesome Privacy">
|
||||
<Layout title={makePageTitle()} keywords={makeKeyWordTag()} description={makeDescriptionTag()} >
|
||||
<Main>
|
||||
|
||||
<h2>{title}</h2>
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ export async function getStaticPaths() {
|
|||
|
||||
---
|
||||
|
||||
<Layout title="Awesome Privacy">
|
||||
<Layout title={`${title} | Awesome Privacy`}>
|
||||
<Main>
|
||||
<SectionList title={title} sections={sections} bigTitle={true} />
|
||||
</Main>
|
||||
|
|
|
|||
|
|
@ -101,10 +101,15 @@ export const socials = [
|
|||
},
|
||||
];
|
||||
|
||||
const description = 'Privacy is a fundamental human right; '
|
||||
+ 'without it, we\'re just open books in a world where everyone\'s '
|
||||
+ 'watching. Let\'s take control back.\n'
|
||||
+ 'Migrating open-source applications which do not collect, sell or log your data is a great first step.'
|
||||
+ 'Awesome Privacy is a directory of alternative privacy-respecting software and services.';
|
||||
|
||||
---
|
||||
|
||||
<Layout title="Awesome Privacy">
|
||||
<Layout title="About | Awesome Privacy" description={description}>
|
||||
<div class="about-page">
|
||||
<Main>
|
||||
<h2>Objective</h2>
|
||||
|
|
@ -307,7 +312,7 @@ h3 {
|
|||
font-weight: 300;
|
||||
color: var(--accent-3);
|
||||
text-align: center;
|
||||
max-width: 500px;
|
||||
max-width: 550px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
small {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import SectionList from '@components/things/SectionList.astro';
|
|||
import { fetchData } from '@utils/fetch-data';
|
||||
|
||||
const categories = (await fetchData())?.categories;
|
||||
|
||||
---
|
||||
|
||||
<Layout title="Browse">
|
||||
|
|
|
|||
|
|
@ -1,67 +0,0 @@
|
|||
---
|
||||
|
||||
import yaml from 'js-yaml';
|
||||
|
||||
import Layout from '@layouts/Layout.astro';
|
||||
import Card from '@components/Card.astro';
|
||||
import Hero from '@components/Hero.astro';
|
||||
import { AwesomePrivacy, Section, Service } from '../../types/Service';
|
||||
|
||||
|
||||
export async function getStaticPaths() {
|
||||
|
||||
const fetchData = async (): Promise<AwesomePrivacy> => {
|
||||
return await fetch('http://localhost:4321/awesome-privacy.yml')
|
||||
.then((res) => res.text())
|
||||
.then((data) => yaml.load(data))
|
||||
.catch((err) => console.error(err));
|
||||
};
|
||||
|
||||
|
||||
const slugify = (title: string) => {
|
||||
return title.toLowerCase().replace(/\s/g, '-');
|
||||
};
|
||||
|
||||
|
||||
const pages = await fetchData().then((data) => {
|
||||
|
||||
const results: { slug: string, title: string, otherSections: Section[], services: Service[] }[] = [];
|
||||
data.categories.forEach((service) => {
|
||||
const sections = service.sections.map((section) => ({
|
||||
slug: `${slugify(service.name)}/${slugify(section.name)}`,
|
||||
title: section.name,
|
||||
services: section.services,
|
||||
otherSections: service.sections,
|
||||
}));
|
||||
results.push(...sections);
|
||||
});
|
||||
return results;
|
||||
});
|
||||
|
||||
return pages.map(({ slug, title, otherSections, services }) => {
|
||||
return {
|
||||
params: { slug },
|
||||
props: { title, otherSections, services },
|
||||
};
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
<Layout title="Awesome Privacy">
|
||||
|
||||
|
||||
</Layout>
|
||||
|
||||
<style lang="scss">
|
||||
main {
|
||||
margin: auto;
|
||||
padding: 1rem;
|
||||
width: 1000px;
|
||||
max-width: calc(100% - 2rem);
|
||||
color: white;
|
||||
font-size: 20px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -11,9 +11,16 @@ import Button from '@components/form/Button.astro';
|
|||
|
||||
const categories = (await fetchData())?.categories || [];
|
||||
|
||||
const description = 'Privacy is a fundamental human right; '
|
||||
+ 'without it, we\'re just open books in a world where everyone\'s '
|
||||
+ 'watching. Let\'s take control back.\n'
|
||||
+ 'Migrating open-source applications which do not collect, sell or log your data is a great first step.'
|
||||
+ 'Awesome Privacy is a directory of alternative privacy-respecting software and services.';
|
||||
|
||||
|
||||
---
|
||||
|
||||
<Layout title="Awesome Privacy" hideNav={true}>
|
||||
<Layout title="Home | Awesome Privacy" hideNav={true} description={description}>
|
||||
<Hero />
|
||||
<main>
|
||||
<h2>
|
||||
|
|
@ -40,6 +47,10 @@ const categories = (await fetchData())?.categories || [];
|
|||
Awesome Privacy is a collection of privacy-respecting services and tools.
|
||||
The aim is to help you escape big tech, and choose software that respects your privacy.
|
||||
</p>
|
||||
<p>
|
||||
Why? Because privacy is a fundamental human right; without it, we're just open books
|
||||
in a world where everyone's watching. Let's take control back.
|
||||
</p>
|
||||
<p>
|
||||
Noticed something that should be added / removed / ammended?
|
||||
We're a community-driven resource, so welcome contributions of any nature.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,59 @@
|
|||
@import url('https://fonts.googleapis.com/css2?family=Lekton:ital,wght@0,400;0,700;1,400&family=Libre+Franklin:ital,wght@0,100..900;1,100..900&family=Rubik:ital,wght@0,300..900;1,300..900&display=swap');
|
||||
/* Fallback to Google Fonts for specific weights and styles */
|
||||
@import url('https://fonts.googleapis.com/css2?family=Lekton:wght@700&family=Libre+Franklin:wght@800&family=Rubik:ital,wght@0,400;0,500;0,600;1,400;1,500;1,600&display=swap');
|
||||
|
||||
/* Rubik Font Faces */
|
||||
@font-face {
|
||||
font-family: 'Rubik';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Rubik'), url('/fonts/Rubik/Rubik-Regular.ttf') format('truetype');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Rubik';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
src: local('Rubik Italic'), url('/fonts/Rubik/Rubik-Italic.ttf') format('truetype');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Rubik';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
src: local('Rubik Medium'), url('/fonts/Rubik/Rubik-Medium.ttf') format('truetype');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Rubik';
|
||||
font-style: italic;
|
||||
font-weight: 500;
|
||||
src: local('Rubik Medium Italic'), url('/fonts/Rubik/Rubik-MediumItalic.ttf') format('truetype');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Rubik';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
src: local('Rubik SemiBold'), url('/fonts/Rubik/Rubik-SemiBold.ttf') format('truetype');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Rubik';
|
||||
font-style: italic;
|
||||
font-weight: 600;
|
||||
src: local('Rubik SemiBold Italic'), url('/fonts/Rubik/Rubik-SemiBoldItalic.ttf') format('truetype');
|
||||
}
|
||||
|
||||
/* Libre Franklin Font Faces */
|
||||
@font-face {
|
||||
font-family: 'Libre Franklin';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
src: local('Libre Franklin Bold'), url('/fonts/Libre_Franklin/LibreFranklin-Bold.ttf') format('truetype');
|
||||
}
|
||||
|
||||
/* Lekton Font Faces */
|
||||
@font-face {
|
||||
font-family: 'Lekton';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Lekton Bold'), url('/fonts/Lekton/Lekton-Bold.ttf') format('truetype');
|
||||
}
|
||||
|
||||
html {
|
||||
font-family: system-ui, sans-serif;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ export interface Section {
|
|||
notableMentions?: ShortService[] | string;
|
||||
furtherInfo?: string;
|
||||
wordOfWarning?: string;
|
||||
alternativeTo?: string[];
|
||||
}
|
||||
|
||||
export interface ServiceStats {
|
||||
|
|
|
|||
Loading…
Reference in a new issue