mirror of
https://github.com/Lissy93/awesome-privacy.git
synced 2026-03-11 08:55:33 +00:00
Starts web app
This commit is contained in:
parent
475aa2b812
commit
5def0fe53f
22 changed files with 11026 additions and 0 deletions
21
web/.gitignore
vendored
Normal file
21
web/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# build output
|
||||
dist/
|
||||
|
||||
# generated types
|
||||
.astro/
|
||||
|
||||
# dependencies
|
||||
node_modules/
|
||||
|
||||
# logs
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
# environment variables
|
||||
.env
|
||||
.env.production
|
||||
|
||||
# macOS-specific files
|
||||
.DS_Store
|
||||
4
web/.vscode/extensions.json
vendored
Normal file
4
web/.vscode/extensions.json
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"recommendations": ["astro-build.astro-vscode"],
|
||||
"unwantedRecommendations": []
|
||||
}
|
||||
11
web/.vscode/launch.json
vendored
Normal file
11
web/.vscode/launch.json
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"command": "./node_modules/.bin/astro dev",
|
||||
"name": "Development server",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
}
|
||||
]
|
||||
}
|
||||
54
web/README.md
Normal file
54
web/README.md
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
# Astro Starter Kit: Basics
|
||||
|
||||
```sh
|
||||
npm create astro@latest -- --template basics
|
||||
```
|
||||
|
||||
[](https://stackblitz.com/github/withastro/astro/tree/latest/examples/basics)
|
||||
[](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/basics)
|
||||
[](https://codespaces.new/withastro/astro?devcontainer_path=.devcontainer/basics/devcontainer.json)
|
||||
|
||||
> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
|
||||
|
||||

|
||||
|
||||
## 🚀 Project Structure
|
||||
|
||||
Inside of your Astro project, you'll see the following folders and files:
|
||||
|
||||
```text
|
||||
/
|
||||
├── public/
|
||||
│ └── favicon.svg
|
||||
├── src/
|
||||
│ ├── components/
|
||||
│ │ └── Card.astro
|
||||
│ ├── layouts/
|
||||
│ │ └── Layout.astro
|
||||
│ └── pages/
|
||||
│ └── index.astro
|
||||
└── package.json
|
||||
```
|
||||
|
||||
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
|
||||
|
||||
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
|
||||
|
||||
Any static assets, like images, can be placed in the `public/` directory.
|
||||
|
||||
## 🧞 Commands
|
||||
|
||||
All commands are run from the root of the project, from a terminal:
|
||||
|
||||
| Command | Action |
|
||||
| :------------------------ | :----------------------------------------------- |
|
||||
| `npm install` | Installs dependencies |
|
||||
| `npm run dev` | Starts local dev server at `localhost:4321` |
|
||||
| `npm run build` | Build your production site to `./dist/` |
|
||||
| `npm run preview` | Preview your build locally, before deploying |
|
||||
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
|
||||
| `npm run astro -- --help` | Get help using the Astro CLI |
|
||||
|
||||
## 👀 Want to learn more?
|
||||
|
||||
Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).
|
||||
4
web/astro.config.mjs
Normal file
4
web/astro.config.mjs
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
import { defineConfig } from 'astro/config';
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({});
|
||||
6534
web/package-lock.json
generated
Normal file
6534
web/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
23
web/package.json
Normal file
23
web/package.json
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"name": "web",
|
||||
"type": "module",
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"start": "astro dev",
|
||||
"build": "astro check && astro build",
|
||||
"preview": "astro preview",
|
||||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/check": "^0.5.4",
|
||||
"astro": "^4.3.6",
|
||||
"js-yaml": "^4.1.0",
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
"@types/node": "^20.11.19",
|
||||
"sass": "^1.70.0"
|
||||
}
|
||||
}
|
||||
161
web/public/awesome-privacy.yml
Normal file
161
web/public/awesome-privacy.yml
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
categories:
|
||||
- name: Essentials
|
||||
sections:
|
||||
- name: Password Managers
|
||||
services:
|
||||
- name: 2-Factor Authentication
|
||||
services:
|
||||
- name: File Encryption
|
||||
services:
|
||||
- name: Browsers
|
||||
services:
|
||||
- name: Search Engines
|
||||
services:
|
||||
|
||||
- name: Communication
|
||||
sections:
|
||||
- name: Encrypted Messaging
|
||||
services:
|
||||
- name: P2P Messaging
|
||||
services:
|
||||
- name: Encrypted Email
|
||||
services:
|
||||
- name: Email Clients
|
||||
services:
|
||||
- name: Mail Forwarding
|
||||
services:
|
||||
- name: Email Security Tools
|
||||
services:
|
||||
- name: VOIP Clients
|
||||
services:
|
||||
- name: Virtual Phone Numbers
|
||||
services:
|
||||
- name: Team Collaboration Platforms
|
||||
services:
|
||||
|
||||
- name: Security Tools
|
||||
sections:
|
||||
- name: Browser Extensions
|
||||
services:
|
||||
- name: Mobile Apps
|
||||
services:
|
||||
- name: Online Tools
|
||||
services:
|
||||
|
||||
- name: Networking
|
||||
sections:
|
||||
- name: Virtual Private Networks
|
||||
services:
|
||||
- name: Self-Hosted Network Security
|
||||
services:
|
||||
- name: Mix Networks
|
||||
services:
|
||||
- name: Proxies
|
||||
services:
|
||||
- name: DNS Providers
|
||||
services:
|
||||
- name: DNS Clients
|
||||
services:
|
||||
- name: Firewalls
|
||||
services:
|
||||
- name: Ad Blockers
|
||||
services:
|
||||
- name: Host Block Lists
|
||||
services:
|
||||
- name: Router Firmware
|
||||
services:
|
||||
- name: Network Analysis
|
||||
services:
|
||||
- name: Cloud Hosting
|
||||
services:
|
||||
- name: Domain Registrars
|
||||
services:
|
||||
- name: DNS Hosting
|
||||
services:
|
||||
- name: Pre-Configured Mail-Servers
|
||||
services:
|
||||
|
||||
- name: Productivity
|
||||
sections:
|
||||
- name: Digital Notes
|
||||
services:
|
||||
- name: Cloud Productivity Suites
|
||||
services:
|
||||
- name: Backup and Sync
|
||||
services:
|
||||
- name: Encrypted Cloud Storage
|
||||
services:
|
||||
- name: File Drop
|
||||
services:
|
||||
- name: Browser Sync
|
||||
services:
|
||||
- name: Secure Conference Calls
|
||||
services:
|
||||
|
||||
- name: Utilities
|
||||
sections:
|
||||
- name: Virtual Machines
|
||||
services:
|
||||
- name: PGP Managers
|
||||
services:
|
||||
- name: Metadata Removal
|
||||
services:
|
||||
- name: Data Erasers
|
||||
services:
|
||||
|
||||
|
||||
- name: Social
|
||||
sections:
|
||||
- name: Social Networks
|
||||
services:
|
||||
- name: Video Platforms
|
||||
services:
|
||||
- name: Blogging Platforms
|
||||
services:
|
||||
- name: News Readers
|
||||
services:
|
||||
- name: Proxy Sites
|
||||
services:
|
||||
|
||||
|
||||
- name: Operating Systems
|
||||
sections:
|
||||
- name: Mobile Operating Systems
|
||||
services:
|
||||
- name: Desktop Operating Systems
|
||||
services:
|
||||
- name: Linux Defences
|
||||
services:
|
||||
- name: Windows Defences
|
||||
services:
|
||||
- name: Mac OS Defences
|
||||
services:
|
||||
- name: Anti-Malware
|
||||
services:
|
||||
|
||||
- name: Development
|
||||
sections:
|
||||
- name: Code Hosting
|
||||
services:
|
||||
|
||||
- name: Home Automation
|
||||
sections:
|
||||
- name: Home Automation
|
||||
services:
|
||||
- name: Voice Assistants
|
||||
services:
|
||||
|
||||
- name: Finance
|
||||
sections:
|
||||
- name: Cryptocurrencies
|
||||
services:
|
||||
- name: Crypto Wallets
|
||||
services:
|
||||
- name: Crypto Exchanges
|
||||
services:
|
||||
- name: Virtual Credit Cards
|
||||
services:
|
||||
- name: Other Payment Methods
|
||||
services:
|
||||
- name: Secure Budgeting
|
||||
services:
|
||||
9
web/public/favicon.svg
Normal file
9
web/public/favicon.svg
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 128 128">
|
||||
<path d="M50.4 78.5a75.1 75.1 0 0 0-28.5 6.9l24.2-65.7c.7-2 1.9-3.2 3.4-3.2h29c1.5 0 2.7 1.2 3.4 3.2l24.2 65.7s-11.6-7-28.5-7L67 45.5c-.4-1.7-1.6-2.8-2.9-2.8-1.3 0-2.5 1.1-2.9 2.7L50.4 78.5Zm-1.1 28.2Zm-4.2-20.2c-2 6.6-.6 15.8 4.2 20.2a17.5 17.5 0 0 1 .2-.7 5.5 5.5 0 0 1 5.7-4.5c2.8.1 4.3 1.5 4.7 4.7.2 1.1.2 2.3.2 3.5v.4c0 2.7.7 5.2 2.2 7.4a13 13 0 0 0 5.7 4.9v-.3l-.2-.3c-1.8-5.6-.5-9.5 4.4-12.8l1.5-1a73 73 0 0 0 3.2-2.2 16 16 0 0 0 6.8-11.4c.3-2 .1-4-.6-6l-.8.6-1.6 1a37 37 0 0 1-22.4 2.7c-5-.7-9.7-2-13.2-6.2Z" />
|
||||
<style>
|
||||
path { fill: #000; }
|
||||
@media (prefers-color-scheme: dark) {
|
||||
path { fill: #FFF; }
|
||||
}
|
||||
</style>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 749 B |
49
web/src/components/Card.astro
Normal file
49
web/src/components/Card.astro
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
---
|
||||
interface Props {
|
||||
title: string;
|
||||
body: string;
|
||||
href: string;
|
||||
}
|
||||
|
||||
const { href, title, body } = Astro.props;
|
||||
---
|
||||
|
||||
<li class="link-card">
|
||||
<a href={href}>
|
||||
<h2>
|
||||
{title}
|
||||
<span>→</span>
|
||||
</h2>
|
||||
<p>
|
||||
{body}
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
<style lang="scss">
|
||||
.link-card {
|
||||
color: var(--foreground);
|
||||
background: var(--background);
|
||||
border: 2px solid var(--foreground);
|
||||
box-shadow: 6px 6px 0 var(--foreground);
|
||||
font-family: "Lekton", sans-serif;
|
||||
font-weight: 700;
|
||||
transition: all ease-in-out 0.1s;
|
||||
list-style: none;
|
||||
&:hover {
|
||||
box-shadow: 8px 8px 0 var(--foreground);
|
||||
background: var(--accent);
|
||||
color: var(--background);
|
||||
|
||||
}
|
||||
a {
|
||||
box-sizing: border-box;
|
||||
color: currentColor;
|
||||
text-decoration: none;
|
||||
transition: all ease-in-out 0.1s;
|
||||
}
|
||||
h2 {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
99
web/src/components/Hero.astro
Normal file
99
web/src/components/Hero.astro
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
|
||||
|
||||
<div class="hero">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 260">
|
||||
<g transform="translate(0,260) scale(0.1,-0.1)"
|
||||
fill="var(--accent-fg)" stroke="none">
|
||||
<path d="M1380 2464 c-543 -69 -956 -465 -1036 -994 -43 -288 25 -581 192
|
||||
-830 25 -37 56 -78 71 -91 l25 -24 -7 25 c-4 14 -11 27 -15 30 -11 9 -89 127
|
||||
-120 184 -54 97 -107 262 -126 386 -10 70 -7 272 6 337 48 240 145 434 302
|
||||
599 372 391 974 471 1423 189 204 -128 341 -282 442 -495 71 -149 102 -291
|
||||
104 -470 1 -148 -11 -227 -60 -390 -13 -43 -85 -184 -134 -264 -61 -99 -38
|
||||
-100 27 -1 158 237 224 534 182 815 -73 481 -430 864 -906 971 -83 19 -298 32
|
||||
-370 23z"/>
|
||||
<path d="M1675 2215 c-33 -7 -126 -17 -208 -22 -124 -8 -151 -12 -175 -30 -15
|
||||
-11 -74 -101 -130 -199 -86 -148 -103 -173 -100 -141 2 20 3 37 3 37 -16 0
|
||||
-161 -58 -223 -89 -142 -71 -204 -155 -172 -231 23 -56 124 -135 216 -170 46
|
||||
-18 9 25 -55 64 -180 110 -172 205 25 305 119 59 174 75 189 51 11 -17 34 -11
|
||||
58 15 12 14 60 92 107 173 56 97 94 151 110 159 14 6 95 17 180 22 85 6 173
|
||||
16 195 21 58 14 132 12 163 -4 42 -21 59 -46 72 -101 27 -113 51 -183 68 -198
|
||||
10 -9 71 -30 136 -46 204 -52 296 -107 296 -180 0 -30 -8 -43 -58 -91 -32 -30
|
||||
-97 -77 -144 -103 -47 -26 -96 -59 -109 -73 l-24 -26 53 20 c119 46 274 158
|
||||
308 224 36 70 3 134 -102 190 -66 35 -270 98 -320 98 -19 0 -25 13 -48 113
|
||||
-36 149 -48 171 -109 202 -57 28 -107 31 -202 10z"/>
|
||||
<path d="M588 1283 c32 -43 114 -153 181 -246 l122 -167 -57 -63 c-65 -72
|
||||
-107 -133 -157 -234 l-37 -72 67 -61 c170 -156 392 -261 623 -296 288 -43 579
|
||||
24 832 193 91 60 228 190 228 215 0 50 -107 279 -165 352 -15 19 -16 19 -75
|
||||
-9 -91 -43 -79 -54 31 -29 24 5 30 0 63 -54 37 -62 87 -174 100 -226 7 -27 1
|
||||
-35 -66 -101 -415 -406 -1108 -415 -1535 -22 -25 23 -43 48 -43 61 0 34 75
|
||||
162 139 236 81 93 85 103 66 139 -8 17 -76 113 -150 214 -74 102 -135 189
|
||||
-135 195 0 6 49 11 123 14 67 2 128 7 135 11 31 20 -11 27 -174 27 l-175 0 59
|
||||
-77z"/>
|
||||
<path d="M2125 1351 c-11 -18 21 -26 128 -29 59 -3 107 -8 107 -12 0 -5 -46
|
||||
-70 -102 -147 -178 -242 -209 -293 -180 -293 5 0 68 82 142 183 74 100 155
|
||||
210 182 245 l48 62 -159 0 c-88 0 -162 -4 -166 -9z"/>
|
||||
<path d="M967 1323 c-23 -26 -22 -46 9 -107 63 -126 163 -172 286 -130 l46 15
|
||||
47 -33 c43 -31 53 -33 140 -36 75 -3 101 0 136 15 59 27 106 68 129 114 25 48
|
||||
25 81 1 103 -16 15 -34 16 -142 10 -142 -8 -318 7 -460 37 -152 33 -171 34
|
||||
-192 12z m309 -68 c127 -18 313 -22 412 -11 59 8 62 7 62 -14 0 -47 -53 -111
|
||||
-118 -144 -45 -23 -147 -31 -201 -16 -26 7 -59 26 -78 45 l-34 34 -42 -19
|
||||
c-50 -23 -137 -26 -175 -6 -40 21 -78 65 -101 116 -35 78 -34 79 69 53 50 -12
|
||||
143 -30 206 -38z"/>
|
||||
</g>
|
||||
</svg>
|
||||
<h1>Awesome Privacy</h1>
|
||||
<p class="intro">
|
||||
Your guide to finding privacy-respecting alternatives to popular software and services.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
.hero {
|
||||
background: var(--accent-fg);
|
||||
color: var(--accent-fg);
|
||||
border-radius: var(--curve-sm);
|
||||
padding: 2rem 4rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2rem;
|
||||
}
|
||||
svg {
|
||||
position: absolute;
|
||||
top: -32px;
|
||||
left: 50%;
|
||||
transform: translatex(-50%);
|
||||
width: 220px;
|
||||
height: auto;
|
||||
opacity: 0.6;
|
||||
display: none;
|
||||
}
|
||||
h1 {
|
||||
margin: 0;
|
||||
font-size: 5rem;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
text-align: center;
|
||||
font-family: 'Libre Franklin', sans-serif;
|
||||
color: var(--accent-3);
|
||||
-webkit-text-fill-color: var(--accent-3);
|
||||
-webkit-text-stroke-width: 2px;
|
||||
-webkit-text-stroke-color: var(--foreground);
|
||||
text-shadow: 3px 3px 0 var(--foreground);
|
||||
}
|
||||
.intro {
|
||||
text-align: center;
|
||||
font-size: 1.6rem;
|
||||
padding: 0.5rem 1rem;
|
||||
color: var(--accent-fg);
|
||||
background: var(--accent-3);
|
||||
border: 2px solid var(--foreground);
|
||||
box-shadow: 6px 6px 0 var(--foreground);
|
||||
font-family: "Lekton", sans-serif;
|
||||
font-weight: 700;
|
||||
max-width: 735px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
</style>
|
||||
1
web/src/env.d.ts
vendored
Normal file
1
web/src/env.d.ts
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/// <reference types="astro/client" />
|
||||
48
web/src/layouts/Layout.astro
Normal file
48
web/src/layouts/Layout.astro
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
---
|
||||
|
||||
interface Props {
|
||||
title: string;
|
||||
}
|
||||
|
||||
const { title } = 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} />
|
||||
<title>{title}</title>
|
||||
</head>
|
||||
<body>
|
||||
<slot />
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<style is:global>
|
||||
@import '../styles/values.css';
|
||||
@import '../styles/typography.css';
|
||||
</style>
|
||||
|
||||
|
||||
<style is:global>
|
||||
:root {
|
||||
--accent: 136, 58, 234;
|
||||
--accent-light: 224, 204, 250;
|
||||
--accent-dark: 49, 10, 101;
|
||||
--accent-gradient: linear-gradient(
|
||||
45deg,
|
||||
rgb(var(--accent)),
|
||||
rgb(var(--accent-light)) 30%,
|
||||
white 60%
|
||||
);
|
||||
}
|
||||
html {
|
||||
background: var(--background);
|
||||
background-size: 224px;
|
||||
}
|
||||
</style>
|
||||
68
web/src/pages/[...section].astro
Normal file
68
web/src/pages/[...section].astro
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
---
|
||||
|
||||
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';
|
||||
|
||||
const { title, otherSections, services } = Astro.props;
|
||||
|
||||
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: { section: slug },
|
||||
props: { title, otherSections, services },
|
||||
};
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
<Layout title="Awesome Privacy">
|
||||
|
||||
<h1>{title}</h1>
|
||||
</Layout>
|
||||
|
||||
<style lang="scss">
|
||||
main {
|
||||
margin: auto;
|
||||
padding: 1rem;
|
||||
width: 1000px;
|
||||
max-width: calc(100% - 2rem);
|
||||
|
||||
font-size: 20px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
</style>
|
||||
73
web/src/pages/[category].astro
Normal file
73
web/src/pages/[category].astro
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
---
|
||||
|
||||
import Layout from '../layouts/Layout.astro';
|
||||
import Card from '../components/Card.astro';
|
||||
import Hero from '../components/Hero.astro';
|
||||
|
||||
|
||||
import yaml from 'js-yaml';
|
||||
import type { AwesomePrivacy, Section, Service } from '../types/Service';
|
||||
|
||||
interface Props {
|
||||
title: string;
|
||||
sections: Section[];
|
||||
}
|
||||
|
||||
const { title, sections } = Astro.props;
|
||||
|
||||
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) => {
|
||||
return data.categories.map((category) => {
|
||||
return {
|
||||
category: slugify(category.name),
|
||||
title: category.name,
|
||||
sections: category.sections,
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
return pages.map(({ category, title, sections }) => {
|
||||
return {
|
||||
params: { category },
|
||||
props: { title, sections },
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
---
|
||||
|
||||
<Layout title="Awesome Privacy">
|
||||
<!-- <Hero /> -->
|
||||
<main>
|
||||
<h1>Title: {title}</h1>
|
||||
<!-- {sections.map((section) => (
|
||||
<section>
|
||||
<h2>{section.name}</h2>
|
||||
</section>
|
||||
))} -->
|
||||
</main>
|
||||
</Layout>
|
||||
|
||||
<style lang="scss">
|
||||
main {
|
||||
margin: auto;
|
||||
padding: 1rem;
|
||||
width: 1000px;
|
||||
max-width: calc(100% - 2rem);
|
||||
color: red;
|
||||
font-size: 20px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
</style>
|
||||
67
web/src/pages/category/index.astro
Normal file
67
web/src/pages/category/index.astro
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
---
|
||||
|
||||
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>
|
||||
26
web/src/pages/index.astro
Normal file
26
web/src/pages/index.astro
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
|
||||
import Layout from '../layouts/Layout.astro';
|
||||
import Card from '../components/Card.astro';
|
||||
import Hero from '../components/Hero.astro';
|
||||
|
||||
---
|
||||
|
||||
<Layout title="Awesome Privacy">
|
||||
<Hero />
|
||||
<main>
|
||||
<Card title="Email" body="" href="/" />
|
||||
</main>
|
||||
</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>
|
||||
30
web/src/styles/typography.css
Normal file
30
web/src/styles/typography.css
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
@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');
|
||||
|
||||
html {
|
||||
font-family: system-ui, sans-serif;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family:
|
||||
Menlo,
|
||||
Monaco,
|
||||
Lucida Console,
|
||||
Liberation Mono,
|
||||
DejaVu Sans Mono,
|
||||
Bitstream Vera Sans Mono,
|
||||
Courier New,
|
||||
monospace;
|
||||
}
|
||||
|
||||
.heading, h1, h2, h3, h4, h5, h6 {
|
||||
font-family: "Libre Franklin", sans-serif;
|
||||
font-optical-sizing: auto;
|
||||
font-weight: 800;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-family: "Lekton", sans-serif;
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
}
|
||||
13
web/src/styles/values.css
Normal file
13
web/src/styles/values.css
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
:root {
|
||||
--accent: #f72b77;
|
||||
--accent-fg: #fff;
|
||||
|
||||
--accent-2: #ffdf60;
|
||||
--accent-3: #5f53f4;
|
||||
|
||||
--foreground: #13151a;
|
||||
|
||||
--curve-sm: 4px;
|
||||
--curve-md: 6px;
|
||||
--curve-lg: 12px;
|
||||
}
|
||||
35
web/src/types/Service.ts
Normal file
35
web/src/types/Service.ts
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
|
||||
|
||||
export interface ShortService {
|
||||
name: string;
|
||||
description: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
export interface Service {
|
||||
name: string;
|
||||
description: string;
|
||||
url: string;
|
||||
github: string;
|
||||
followWith?: string;
|
||||
}
|
||||
|
||||
export interface Section {
|
||||
name: string;
|
||||
services: Service[];
|
||||
notableMentions: ShortService[];
|
||||
furtherInfo: string;
|
||||
}
|
||||
|
||||
export interface ServiceStats {
|
||||
isOpenSource: boolean;
|
||||
author: string;
|
||||
authorUrl: string;
|
||||
}
|
||||
|
||||
export interface AwesomePrivacy {
|
||||
categories: Array<{
|
||||
name: string;
|
||||
sections: Array<Section>;
|
||||
}>;
|
||||
}
|
||||
3
web/tsconfig.json
Normal file
3
web/tsconfig.json
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"extends": "astro/tsconfigs/strict"
|
||||
}
|
||||
3693
web/yarn.lock
Normal file
3693
web/yarn.lock
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue