Merge pull request #108 from Supercolbat/dev‎‎​

UI/UX changes
This commit is contained in:
Joey L 2023-08-07 00:38:31 +00:00 committed by GitHub
commit a5c9d5ebb3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 992 additions and 681 deletions

View File

@ -11,3 +11,6 @@ node_modules
pnpm-lock.yaml pnpm-lock.yaml
package-lock.json package-lock.json
yarn.lock yarn.lock
# Ignore NixOS flake lock
flake.lock

76
flake.lock generated Normal file
View File

@ -0,0 +1,76 @@
{
"nodes": {
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1689068808,
"narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
"type": "github"
},
"original": {
"id": "flake-utils",
"type": "indirect"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1691209513,
"narHash": "sha256-V8e6wywJ34DgwP4sDSWpHMPx3OC+k1l/xPSQTfdPj5U=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "cc0e47cd36a2d6815eba5abf3317e519abd35571",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "master",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs",
"systems": "systems_2"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_2": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

26
flake.nix Normal file
View File

@ -0,0 +1,26 @@
{
inputs.nixpkgs.url = "github:NixOS/nixpkgs/master";
inputs.systems.url = "github:nix-systems/default";
outputs = {
self,
nixpkgs,
flake-utils,
systems,
}:
flake-utils.lib.eachSystem (import systems)
(system: let
pkgs = import nixpkgs {
inherit system;
};
in {
devShells.default = pkgs.mkShell {
buildInputs = [
pkgs.nodejs
# Package manager
pkgs.nodePackages.pnpm
];
};
});
}

View File

@ -12,30 +12,30 @@
"format": "prettier --plugin-search-dir . --write ." "format": "prettier --plugin-search-dir . --write ."
}, },
"devDependencies": { "devDependencies": {
"@iconify-json/ic": "^1.1.12", "@iconify-json/ic": "^1.1.13",
"@iconify-json/simple-icons": "^1.1.41", "@iconify-json/simple-icons": "^1.1.63",
"@sveltejs/adapter-node": "^1.1.4", "@sveltejs/adapter-node": "^1.3.1",
"@sveltejs/kit": "^1.1.4", "@sveltejs/kit": "^1.22.4",
"@types/sanitize-html": "^2.8.0", "@types/sanitize-html": "^2.9.0",
"@unocss/reset": "^0.48.4", "@unocss/reset": "^0.48.5",
"axios": "^1.2.4", "axios": "^1.4.0",
"dayjs": "^1.11.7", "dayjs": "^1.11.9",
"prettier": "^2.8.3", "prettier": "^3.0.1",
"prettier-plugin-svelte": "^2.9.0", "prettier-plugin-svelte": "^3.0.3",
"sanitize-html": "^2.8.1", "sanitize-html": "^2.11.0",
"svelte": "^3.55.1", "svelte": "^3.59.2",
"svelte-check": "^3.0.2", "svelte-check": "^3.4.6",
"svelte-dark-mode": "^2.1.0", "svelte-dark-mode": "^2.1.0",
"tslib": "^2.4.1", "tslib": "^2.6.1",
"typescript": "^4.9.4", "typescript": "^4.9.5",
"unocss": "^0.48.4", "unocss": "^0.48.5",
"vite": "^4.0.4" "vite": "^4.4.8"
}, },
"type": "module", "type": "module",
"dependencies": { "dependencies": {
"@auth/core": "^0.2.5", "@auth/core": "^0.2.5",
"@auth/sveltekit": "^0.1.12", "@auth/sveltekit": "^0.1.12",
"joi": "^17.7.0", "joi": "^17.9.2",
"snarkdown": "^2.0.0", "snarkdown": "^2.0.0",
"svelte-hcaptcha": "^0.1.1" "svelte-hcaptcha": "^0.1.1"
} }

938
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -17,9 +17,22 @@ html.light {
--alt: #ddd; --alt: #ddd;
--alt-text: #333; --alt-text: #333;
--black: #151515; --black: #151515;
--body-text: #666;
color-scheme: light; color-scheme: light;
} }
html.dark {
--primary: #151515;
--secondary: #1d1d1d;
--tertiary: #353535;
--text: #ffffffde;
--grey: #5454547a;
--alt: #333;
--alt-text: #ddd;
--body-text: #bbb;
color-scheme: dark;
}
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
html { html {
--primary: #151515; --primary: #151515;
@ -29,6 +42,7 @@ html.light {
--grey: #5454547a; --grey: #5454547a;
--alt: #333; --alt: #333;
--alt-text: #ddd; --alt-text: #ddd;
--body-text: #bbb;
color-scheme: dark; color-scheme: dark;
} }
} }
@ -50,26 +64,35 @@ a:hover {
} }
h1 { h1 {
@apply text-4xl font-bold my-8 border-b-2 border-accent pb-2; @apply text-4xl font-bold mt-8 mb-2 border-b-2 border-accent pb-2;
} }
.h1-no-lg { .h1-no-lg {
@apply my-8 border-b-2 border-accent pb-2; @apply mt-8 mb-2 border-b-2 border-accent pb-2;
} }
h2 { h2 {
@apply text-3xl font-bold my-8; @apply text-3xl font-bold mt-8 mb-2;
} }
h3 { h3 {
@apply text-2xl font-bold my-8; @apply text-2xl font-bold mt-8 mb-2;
} }
h4 { h4 {
@apply text-xl font-bold my-8; @apply text-xl font-bold mt-8 mb-2;
} }
details { p {
color: var(--body-text);
}
/* Between-paragraph spacing */
p + p {
@apply mt-4;
}
summary {
@apply cursor-pointer; @apply cursor-pointer;
} }

View File

@ -1,4 +1,4 @@
<!DOCTYPE html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />

View File

@ -5,7 +5,13 @@ import type { Provider } from "@auth/core/providers";
import type { Profile } from "@auth/core/types"; import type { Profile } from "@auth/core/types";
import { redirect, type Handle } from "@sveltejs/kit"; import { redirect, type Handle } from "@sveltejs/kit";
import { sequence } from "@sveltejs/kit/hooks"; import { sequence } from "@sveltejs/kit/hooks";
import { announcements, pubnixUsers, blogPosts, blogTags, blogAuthors } from "./stores"; import {
announcements,
pubnixUsers,
blogPosts,
blogTags,
blogAuthors
} from "./stores";
import axios from "axios"; import axios from "axios";
import { Agent } from "https"; import { Agent } from "https";
@ -74,10 +80,10 @@ export const fetchGhost = async (action: string, additional?: string) => {
const updateMap = async () => { const updateMap = async () => {
try { try {
const res = await axios( const res = await axios(env.KUMA_URL, {
env.KUMA_URL, httpsAgent: agent,
{ httpsAgent: agent, timeout: 10000 } timeout: 10000
); });
if (res.status === 200) { if (res.status === 200) {
announcements.set(res.data); announcements.set(res.data);
@ -89,10 +95,10 @@ const updateMap = async () => {
} }
try { try {
const res = await axios( const res = await axios("https://publapi.p.projectsegfau.lt/users", {
"https://publapi.p.projectsegfau.lt/users", httpsAgent: agent,
{ httpsAgent: agent, timeout: 10000 } timeout: 10000
); });
if (res.status === 200) { if (res.status === 200) {
pubnixUsers.set(res.data); pubnixUsers.set(res.data);

View File

@ -2,7 +2,9 @@
<h1 class="text-5xl font-extrabold text-accent my-0 border-b-0 pb-0"> <h1 class="text-5xl font-extrabold text-accent my-0 border-b-0 pb-0">
Project Segfault Project Segfault
</h1> </h1>
<p class="text-2xl">Open source development and hosted services.</p> <p class="text-2xl text-text">
Open-source development and hosted services.
</p>
<div class="flex gap-4 flex-col w-full sm:(flex-row justify-center)"> <div class="flex gap-4 flex-col w-full sm:(flex-row justify-center)">
<a <a
href="/instances" href="/instances"

View File

@ -7,16 +7,17 @@
const links = [ const links = [
{ href: "/instances", text: "Instances" }, { href: "/instances", text: "Instances" },
{ href: "/donate", text: "Donate" },
{ href: "/pubnix", text: "Pubnix" }, { href: "/pubnix", text: "Pubnix" },
{ href: "/contact", text: "Contact" },
{ href: "/team", text: "Team" },
{ {
href: "https://wiki.projectsegfau.lt/", href: "https://wiki.projectsegfau.lt/",
text: "Wiki", text: "Wiki",
external: true external: true
}, },
{ href: "/blog", text: "Blog" }, { href: "/blog", text: "Blog" },
{ href: "/donate", text: "Donate" },
{ href: "/contact", text: "Contact" },
{ href: "/team", text: "Team" },
{ {
href: "https://status.projectsegfau.lt/", href: "https://status.projectsegfau.lt/",
text: "Status", text: "Status",
@ -83,6 +84,8 @@
> >
<!-- Slot for the progress bar --> <!-- Slot for the progress bar -->
<slot /> <slot />
<!-- Nav without links -->
<div class="flex items-center justify-between w-full"> <div class="flex items-center justify-between w-full">
<Logo /> <Logo />
<button <button
@ -96,11 +99,13 @@
/> />
</button> </button>
</div> </div>
{#if showMenu}
<!-- Nav with links -->
<div class={showMenu ? "contents" : "hidden"}>
<div <div
class=" class="
{linkContainerStyles} {linkContainerStyles}
lt-navPlus1:(flex-col !items-start fixed pl-4 pb-4 z-50 w-full left-0 top-16) lt-navPlus1:(flex-col !items-end fixed pr-4 pb-4 z-50 w-full left-0 top-16)
" "
transition:slide={{ duration: 300, easing: quintOut }} transition:slide={{ duration: 300, easing: quintOut }}
> >
@ -115,7 +120,7 @@
{/each} {/each}
<ThemeToggle /> <ThemeToggle />
</div> </div>
{/if} </div>
</nav> </nav>
<noscript> <noscript>

View File

@ -17,12 +17,19 @@
<button <button
on:click={toggle} on:click={toggle}
class="text-text flex items-center text-sm" class="theme-toggle button text-text flex items-center text-sm"
aria-label="Toggle theme"
> >
<div <div
class="i-ic:{theme === 'dark' class="i-ic:{theme === 'dark'
? 'outline-light-mode' ? 'outline-light-mode'
: 'outline-dark-mode'} h-4 w-4" : 'outline-dark-mode'} h-4 w-4"
/> />
<span class="ml-2 navPlus1:(hidden)">Toggle theme</span> <span class="navPlus1:(hidden)">Toggle theme</span>
</button> </button>
<style>
.theme-toggle:hover {
@apply brightness-70;
}
</style>

View File

@ -9,17 +9,15 @@
import PageTransition from "$lib/PageTransition.svelte"; import PageTransition from "$lib/PageTransition.svelte";
import type { LayoutData } from "./$types"; import type { LayoutData } from "./$types";
const title = $page.url.pathname.startsWith("/blog")
? `${$page.data.title} | Project Segfault blog`
: `${$page.data.title} | Project Segfault`;
export let data: LayoutData; export let data: LayoutData;
</script> </script>
<svelte:head> <svelte:head>
<title <title>{title}</title>
>{$page.data.title} | Project Segfault {$page.url.pathname.startsWith(
"/blog"
)
? "blog"
: ""}</title
>
{#if $page.data.description} {#if $page.data.description}
<meta <meta
name="description" name="description"

View File

@ -5,11 +5,11 @@ import { get } from "svelte/store";
export const load = (async () => { export const load = (async () => {
const meta = { const meta = {
title: "Home", title: "Home",
description: "Open source development and hosted services." description: "Open-source development and hosted services."
}; };
return { return {
announcements: get(announcements), announcements: get(announcements),
...meta ...meta
} };
}) satisfies PageServerLoad; }) satisfies PageServerLoad;

View File

@ -12,7 +12,7 @@
We have a Matrix space for general discussion, support and announcements We have a Matrix space for general discussion, support and announcements
about Project Segfault over at <a about Project Segfault over at <a
href="https://matrix.to/#/#project-segfault:projectsegfau.lt/" href="https://matrix.to/#/#project-segfault:projectsegfau.lt/"
>this link</a >#project-segfault:projectsegfau.lt</a
>. >.
</p> </p>
@ -20,7 +20,8 @@
<p> <p>
We have an XMPP MUC for general discussion about Project Segfault over at <a We have an XMPP MUC for general discussion about Project Segfault over at <a
href="https://join.jabber.network/#general@conference.projectsegfau.lt?join">this link</a href="https://join.jabber.network/#general@conference.projectsegfau.lt?join"
>#general@conference.projectsegfau.lt</a
>. >.
</p> </p>
@ -44,7 +45,7 @@
<h2>Members</h2> <h2>Members</h2>
<p> <p>
You can contact individual members by using the links provided in <a You can contact individual members by using the links provided in the <a
href="/team">the team page</a href="/team">team page</a
>. >.
</p> </p>

View File

@ -7,7 +7,7 @@
<h1>{data.title}</h1> <h1>{data.title}</h1>
<h2>What we do with donations</h2> <h2>What we do with donations?</h2>
<p> <p>
These donations primarily help us pay for our VPSes, domain names and other These donations primarily help us pay for our VPSes, domain names and other
@ -27,7 +27,7 @@
<a <a
href="https://liberapay.com/ProjectSegfault/donate" href="https://liberapay.com/ProjectSegfault/donate"
class="button !bg-amber !text-black w-fit" class="button !bg-amber !text-black w-fit"
><div class="i-simple-icons:liberapay" /> ><div class="va-icon i-simple-icons:liberapay" />
Liberapay</a Liberapay</a
> >
@ -46,23 +46,50 @@
and <a href="https://electrum-ltc.org">Electrum-LTC</a>. and <a href="https://electrum-ltc.org">Electrum-LTC</a>.
</p> </p>
<h4>Monero</h4> <p class="text-text font-bold mt-4">
<i
class="va-icon i-simple-icons:monero inline-block text-[#F60]"
aria-hidden="true"
/>
Monero
</p>
<CryptoInfo <CryptoInfo
name="Monero"
address="47L7Qsto7XcifY3CdG18ySe5Tt83kpFLDLve9jQwbc9taPBLNGv6ZrJNUKpMG9Nj9zHgCZ4FQMSyt75e8Jvx12JFLtJyFdA" address="47L7Qsto7XcifY3CdG18ySe5Tt83kpFLDLve9jQwbc9taPBLNGv6ZrJNUKpMG9Nj9zHgCZ4FQMSyt75e8Jvx12JFLtJyFdA"
qr="Monero.png" qr="Monero.png"
/> />
<h4>Bitcoin</h4> <p class="text-text font-bold mt-4">
<i
class="va-icon i-simple-icons:bitcoin inline-block text-[#F7931A]"
aria-hidden="true"
/>
Bitcoin
</p>
<CryptoInfo <CryptoInfo
name="Bitcoin"
address="bc1qrc8ywgp95a6p3zausp4nff70qzstp6h8z86sxd" address="bc1qrc8ywgp95a6p3zausp4nff70qzstp6h8z86sxd"
qr="Bitcoin.png" qr="Bitcoin.png"
/> />
<h4>Litecoin</h4> <p class="text-text font-bold mt-4">
<i
class="va-icon i-simple-icons:litecoin inline-block text-[#A6A9AA]"
aria-hidden="true"
/>
Litecoin
</p>
<CryptoInfo <CryptoInfo
name="Litecoin"
address="ltc1qn3ald586h2ntt0n3zkvwsmju2e5vndgtvvgatj" address="ltc1qn3ald586h2ntt0n3zkvwsmju2e5vndgtvvgatj"
qr="Litecoin.png" qr="Litecoin.png"
/> />
<style>
.va-icon {
vertical-align: -0.125em;
}
</style>

View File

@ -1,4 +1,5 @@
<script lang="ts"> <script lang="ts">
export let name: string = "";
export let address: string = ""; export let address: string = "";
export let qr: string = ""; export let qr: string = "";
</script> </script>
@ -13,10 +14,16 @@
{#if qr} {#if qr}
<details class="p-0"> <details class="p-0">
<summary>QR code</summary> <summary>QR code</summary>
<a
href="/qr/{qr}"
target="_blank"
rel="noreferrer"
>
<img <img
src="/qr/{qr}" src="/qr/{qr}"
alt="QR code" alt="QR code to {name} address"
class="mt-2" class="mt-2"
/> />
</a>
</details> </details>
{/if} {/if}

View File

@ -1,10 +1,18 @@
import instances from "./instances"; import instances from "./instances";
import type { PageServerLoad } from "./$types"; import type { PageServerLoad } from "./$types";
export const load = (() => { export const load = (({ url }) => {
const meta = { const meta = {
title: "Instances" title: "Instances"
}; };
return { instances, ...meta }; // If the ?short url query exists, then longUrl is false
// Every other case is true
const queryLongUrl = !url.searchParams.has("short");
return {
instances,
queryLongUrl,
...meta
};
}) satisfies PageServerLoad; }) satisfies PageServerLoad;

View File

@ -3,15 +3,17 @@
export let data: PageData; export let data: PageData;
let insturl: "short" | "long"; $: longUrl = data.queryLongUrl;
let toggle = () => { let toggle = () => {
insturl = insturl === "long" ? "short" : "long"; longUrl = !longUrl;
}; };
insturl = "long";
</script> </script>
<div class="h1-no-lg flex flex-col sm:(flex-row items-center) gap-4 !mb-0"> <div class="h1-no-lg flex flex-col sm:(flex-row items-center) gap-4 !mb-0">
<span class="text-4xl font-bold">{data.title}</span> <span class="text-4xl font-bold">{data.title}</span>
<!-- With JavaScript -->
<a <a
href="/instances/advanced" href="/instances/advanced"
class="button sm:w-fit" class="button sm:w-fit"
@ -20,28 +22,40 @@
> >
<button <button
on:click={toggle} on:click={toggle}
class="text-text flex items-center text-sm js"
>
<div
class="i-ic:{longUrl
? 'baseline-toggle-off bg-alt'
: 'baseline-toggle-on bg-accent'} h-15 w-15"
/>
Use short URL
</button>
<!-- Without JavaScript -->
<noscript>
<a
href="?{data.queryLongUrl ? 'short' : ''}"
class="text-text flex items-center text-sm" class="text-text flex items-center text-sm"
> >
<div <div
class="i-ic:{insturl === 'long' class="i-ic:{data.queryLongUrl
? 'baseline-toggle-off bg-accent' ? 'baseline-toggle-off bg-alt'
: 'baseline-toggle-on bg-amber-500'} h-15 w-15" : 'baseline-toggle-on bg-accent'} h-15 w-15"
/> />
{#if insturl === "long"} Use short URL
Long URL </a>
{:else}
Short URL
{/if}
</button>
<style>
.js {
display: none;
}
</style>
</noscript>
</div> </div>
<div class="flex flex-col"> <div class="flex flex-col">
{#if longUrl}
{#if insturl === "long"}
{#each data.instances as category} {#each data.instances as category}
<div class="flex flex-col"> <div class="flex flex-col">
<h2>{category.name}</h2> <h2>{category.name}</h2>
@ -74,7 +88,10 @@
<div class="flex flex-row flex-wrap gap-4"> <div class="flex flex-row flex-wrap gap-4">
{#each category.data as instance} {#each category.data as instance}
<a <a
href={instance.short_geo || instance.short_eu || instance.geo || instance.eu} href={instance.short_geo ||
instance.short_eu ||
instance.geo ||
instance.eu}
class="flex flex-row items-center gap-4 rounded bg-secondary p-4 w-110 no-underline text-text" class="flex flex-row items-center gap-4 rounded bg-secondary p-4 w-110 no-underline text-text"
> >
{#if instance.icon} {#if instance.icon}

View File

@ -18,50 +18,56 @@
{#each data.instances as category} {#each data.instances as category}
{#each category.data as instance} {#each category.data as instance}
<h2>{instance.name}</h2> <h2>{instance.name}</h2>
<div class="flex flex-row gap-2"> <ul class="instances flex flex-row flex-wrap gap-2">
{#if instance.geo} {#if instance.geo}
<a href={instance.geo}>GeoDNS</a> <li><a href={instance.geo}>GeoDNS</a></li>
{/if} {/if}
{#if instance.eu} {#if instance.eu}
<a href={instance.eu}>EU</a> <li><a href={instance.eu}>EU</a></li>
{/if} {/if}
{#if instance.us} {#if instance.us}
<a href={instance.us}>US</a> <li><a href={instance.us}>US</a></li>
{/if} {/if}
{#if instance.in} {#if instance.in}
<a href={instance.in}>IN</a> <li><a href={instance.in}>IN</a></li>
{/if} {/if}
{#if instance.bp} {#if instance.bp}
<a href={instance.bp}>Backup</a> <li><a href={instance.bp}>Backup</a></li>
{/if} {/if}
{#if instance.short_geo} {#if instance.short_geo}
<a href={instance.short_geo}>GeoDNS (Short URL)</a> <li><a href={instance.short_geo}>GeoDNS (Short URL)</a></li>
{/if} {/if}
{#if instance.short_eu} {#if instance.short_eu}
<a href={instance.short_eu}>EU (Short URL)</a> <li><a href={instance.short_eu}>EU (Short URL)</a></li>
{/if} {/if}
{#if instance.short_us} {#if instance.short_us}
<a href={instance.short_us}>US (Short URL)</a> <li><a href={instance.short_us}>US (Short URL)</a></li>
{/if} {/if}
{#if instance.short_in} {#if instance.short_in}
<a href={instance.short_in}>IN (Short URL)</a> <li><a href={instance.short_in}>IN (Short URL)</a></li>
{/if} {/if}
{#if instance.short_bp} {#if instance.short_bp}
<a href={instance.short_bp}>Backup (Short URL)</a> <li><a href={instance.short_bp}>Backup (Short URL)</a></li>
{/if} {/if}
{#if instance.tor} {#if instance.tor}
<a href={instance.tor}>Tor</a> <li><a href={instance.tor}>Tor</a></li>
{/if} {/if}
{#if instance.torBp} {#if instance.torBp}
<a href={instance.torBp}>Tor backup</a> <li><a href={instance.torBp}>Tor backup</a></li>
{/if} {/if}
{#if instance.i2p} {#if instance.i2p}
<a href={instance.i2p}>I2P</a> <li><a href={instance.i2p}>I2P</a></li>
{/if} {/if}
{#if instance.i2pBp} {#if instance.i2pBp}
<a href={instance.i2pBp}>I2P backup</a> <li><a href={instance.i2pBp}>I2P backup</a></li>
{/if} {/if}
</div> </ul>
{/each} {/each}
{/each} {/each}
</div> </div>
<style>
.instances li:not(:last-child)::after {
content: ",";
}
</style>

View File

@ -29,7 +29,7 @@ const instances: Instances[] = [
data: [ data: [
{ {
name: "Invidious", name: "Invidious",
description: "A frontend for YouTube.", description: "A front-end for YouTube.",
eu: "https://invidious.projectsegfau.lt/", eu: "https://invidious.projectsegfau.lt/",
short_eu: "https://i.psf.lt/", short_eu: "https://i.psf.lt/",
us: "https://inv.us.projectsegfau.lt/", us: "https://inv.us.projectsegfau.lt/",
@ -46,7 +46,7 @@ const instances: Instances[] = [
}, },
{ {
name: "Piped", name: "Piped",
description: "Another frontend for YouTube.", description: "Another front-end for YouTube.",
eu: "https://piped.projectsegfau.lt/", eu: "https://piped.projectsegfau.lt/",
short_eu: "https://pi.psf.lt/", short_eu: "https://pi.psf.lt/",
us: "https://piped.us.projectsegfau.lt/", us: "https://piped.us.projectsegfau.lt/",
@ -57,7 +57,7 @@ const instances: Instances[] = [
}, },
{ {
name: "Libreddit", name: "Libreddit",
description: "A frontend for Reddit.", description: "A front-end for Reddit.",
geo: "https://libreddit.projectsegfau.lt/", geo: "https://libreddit.projectsegfau.lt/",
short_geo: "https://lr.psf.lt/", short_geo: "https://lr.psf.lt/",
eu: "https://libreddit.eu.projectsegfau.lt/", eu: "https://libreddit.eu.projectsegfau.lt/",
@ -72,7 +72,7 @@ const instances: Instances[] = [
}, },
{ {
name: "Nitter", name: "Nitter",
description: "A frontend for Twitter.", description: "A front-end for Twitter.",
geo: "https://nitter.projectsegfau.lt/", geo: "https://nitter.projectsegfau.lt/",
short_geo: "https://n.psf.lt/", short_geo: "https://n.psf.lt/",
eu: "https://nitter.eu.projectsegfau.lt/", eu: "https://nitter.eu.projectsegfau.lt/",
@ -87,7 +87,7 @@ const instances: Instances[] = [
}, },
{ {
name: "AnonymousOverflow", name: "AnonymousOverflow",
description: "A frontend for StackOverflow.", description: "A front-end for StackOverflow.",
geo: "https://overflow.projectsegfau.lt/", geo: "https://overflow.projectsegfau.lt/",
short_geo: "https://o.psf.lt/", short_geo: "https://o.psf.lt/",
eu: "https://overflow.eu.projectsegfau.lt/", eu: "https://overflow.eu.projectsegfau.lt/",
@ -101,7 +101,7 @@ const instances: Instances[] = [
}, },
{ {
name: "BreezeWiki", name: "BreezeWiki",
description: "A frontend for Fandom.", description: "A front-end for Fandom.",
geo: "https://bw.projectsegfau.lt/", geo: "https://bw.projectsegfau.lt/",
short_geo: "https://bw.psf.lt/", short_geo: "https://bw.psf.lt/",
eu: "https://bw.eu.projectsegfau.lt/", eu: "https://bw.eu.projectsegfau.lt/",
@ -116,7 +116,7 @@ const instances: Instances[] = [
}, },
{ {
name: "GotHub", name: "GotHub",
description: "A frontend for GitHub.", description: "A front-end for GitHub.",
geo: "https://gothub.projectsegfau.lt/", geo: "https://gothub.projectsegfau.lt/",
short_geo: "https://gh.psf.lt/", short_geo: "https://gh.psf.lt/",
eu: "https://gothub.eu.projectsegfau.lt/", eu: "https://gothub.eu.projectsegfau.lt/",
@ -130,7 +130,7 @@ const instances: Instances[] = [
}, },
{ {
name: "HyperPipe", name: "HyperPipe",
description: "A frontend for YT Music.", description: "A front-end for YT Music.",
geo: "https://hyperpipe.projectsegfau.lt/", geo: "https://hyperpipe.projectsegfau.lt/",
short_geo: "https://hp.psf.lt/", short_geo: "https://hp.psf.lt/",
eu: "https://hyperpipe.eu.projectsegfau.lt/", eu: "https://hyperpipe.eu.projectsegfau.lt/",
@ -143,7 +143,7 @@ const instances: Instances[] = [
}, },
{ {
name: "Rimgo", name: "Rimgo",
description: "A frontend for Imgur.", description: "A front-end for Imgur.",
geo: "https://rimgo.projectsegfau.lt/", geo: "https://rimgo.projectsegfau.lt/",
short_geo: "https://rg.psf.lt/", short_geo: "https://rg.psf.lt/",
eu: "https://rimgo.eu.projectsegfau.lt/", eu: "https://rimgo.eu.projectsegfau.lt/",
@ -157,7 +157,7 @@ const instances: Instances[] = [
}, },
{ {
name: "Safetwitch", name: "Safetwitch",
description: "A frontend for Twitch.", description: "A front-end for Twitch.",
geo: "https://safetwitch.projectsegfau.lt/", geo: "https://safetwitch.projectsegfau.lt/",
short_geo: "https://tw.psf.lt/", short_geo: "https://tw.psf.lt/",
eu: "https://safetwitch.eu.projectsegfau.lt/", eu: "https://safetwitch.eu.projectsegfau.lt/",
@ -171,7 +171,7 @@ const instances: Instances[] = [
}, },
{ {
name: "Scribe", name: "Scribe",
description: "A frontend for Medium.", description: "A front-end for Medium.",
geo: "https://scribe.projectsegfau.lt/", geo: "https://scribe.projectsegfau.lt/",
short_geo: "https://sc.psf.lt/", short_geo: "https://sc.psf.lt/",
eu: "https://scribe.eu.projectsegfau.lt/", eu: "https://scribe.eu.projectsegfau.lt/",
@ -185,7 +185,7 @@ const instances: Instances[] = [
}, },
{ {
name: "SimplyTranslate", name: "SimplyTranslate",
description: "A frontend for many translation engines.", description: "A front-end for many translation engines.",
geo: "https://simplytranslate.projectsegfau.lt/", geo: "https://simplytranslate.projectsegfau.lt/",
short_geo: "https://tl.psf.lt/", short_geo: "https://tl.psf.lt/",
eu: "https://simplytranslate.eu.projectsegfau.lt/", eu: "https://simplytranslate.eu.projectsegfau.lt/",
@ -198,7 +198,7 @@ const instances: Instances[] = [
}, },
{ {
name: "Teddit", name: "Teddit",
description: "Another frontend for Reddit.", description: "Another front-end for Reddit.",
geo: "https://teddit.projectsegfau.lt/", geo: "https://teddit.projectsegfau.lt/",
short_geo: "https://t.psf.lt/", short_geo: "https://t.psf.lt/",
eu: "https://teddit.eu.projectsegfau.lt/", eu: "https://teddit.eu.projectsegfau.lt/",
@ -209,7 +209,7 @@ const instances: Instances[] = [
short_in: "https://t.in.psf.lt/", short_in: "https://t.in.psf.lt/",
tor: "http://teddit.pjsfkvpxlinjamtawaksbnnaqs2fc2mtvmozrzckxh7f3kis6yea25ad.onion", tor: "http://teddit.pjsfkvpxlinjamtawaksbnnaqs2fc2mtvmozrzckxh7f3kis6yea25ad.onion",
icon: "/icons/teddit.png" icon: "/icons/teddit.png"
}, }
] ]
}, },
{ {
@ -217,7 +217,8 @@ const instances: Instances[] = [
data: [ data: [
{ {
name: "Matrix", name: "Matrix",
description: "An open network for secure, decentralized communication.", description:
"An open network for secure, decentralized communication.",
eu: "https://wiki.projectsegfau.lt/Matrix", eu: "https://wiki.projectsegfau.lt/Matrix",
short_eu: "https://w.psf.lt/Matrix", short_eu: "https://w.psf.lt/Matrix",
icon: "/icons/matrix.svg" icon: "/icons/matrix.svg"
@ -258,7 +259,7 @@ const instances: Instances[] = [
}, },
{ {
name: "SearXNG", name: "SearXNG",
description: "A private meta-search engine.", description: "A private metasearch engine.",
eu: "https://search.projectsegfau.lt/", eu: "https://search.projectsegfau.lt/",
short_eu: "https://s.psf.lt/", short_eu: "https://s.psf.lt/",
us: "https://search.us.projectsegfau.lt/", us: "https://search.us.projectsegfau.lt/",
@ -271,7 +272,8 @@ const instances: Instances[] = [
}, },
{ {
name: "Gitea", name: "Gitea",
description: "A web interface for Git, alternative to GitHub.", description:
"A web interface for Git. An alternative to GitHub.",
eu: "https://git.projectsegfau.lt/", eu: "https://git.projectsegfau.lt/",
short_eu: "https://git.psf.lt/", short_eu: "https://git.psf.lt/",
tor: "http://git.pjsfkvpxlinjamtawaksbnnaqs2fc2mtvmozrzckxh7f3kis6yea25ad.onion", tor: "http://git.pjsfkvpxlinjamtawaksbnnaqs2fc2mtvmozrzckxh7f3kis6yea25ad.onion",
@ -280,14 +282,14 @@ const instances: Instances[] = [
}, },
{ {
name: "Hedgedoc", name: "Hedgedoc",
description: "Collaborative markdown notes.", description: "Collaborative Markdown notes.",
eu: "https://doc.projectsegfau.lt/", eu: "https://doc.projectsegfau.lt/",
short_eu: "https://d.psf.lt/", short_eu: "https://d.psf.lt/",
icon: "/icons/hedgedoc.svg" icon: "/icons/hedgedoc.svg"
}, },
{ {
name: "LibreTranslate", name: "LibreTranslate",
description: "Free and Open Source Machine Translation API.", description: "Free and open-source machine translation API.",
in: "https://libretranslate.projectsegfau.lt", in: "https://libretranslate.projectsegfau.lt",
short_in: "https://lt.psf.lt/", short_in: "https://lt.psf.lt/",
icon: "/icons/libretranslate.png" icon: "/icons/libretranslate.png"
@ -301,7 +303,7 @@ const instances: Instances[] = [
}, },
{ {
name: "Kbin", name: "Kbin",
description: "Federated reddit alternative.", description: "Federated Reddit alternative.",
eu: "https://kbin.projectsegfau.lt/", eu: "https://kbin.projectsegfau.lt/",
short_eu: "https://kb.psf.lt/", short_eu: "https://kb.psf.lt/",
icon: "/icons/kbin.svg" icon: "/icons/kbin.svg"
@ -317,28 +319,28 @@ const instances: Instances[] = [
}, },
{ {
name: "Jitsi", name: "Jitsi",
description: "An open source video conferencing platform.", description: "An open-source video conferencing platform.",
eu: "https://jitsi.projectsegfau.lt/", eu: "https://jitsi.projectsegfau.lt/",
short_eu: "https://j.psf.lt/", short_eu: "https://j.psf.lt/",
icon: "/icons/jitsi.svg" icon: "/icons/jitsi.svg"
}, },
{ {
name: "Vaultwarden", name: "Vaultwarden",
description: "An open source password manager.", description: "An open-source password manager.",
eu: "https://pass.projectsegfau.lt/", eu: "https://pass.projectsegfau.lt/",
short_eu: "https://vw.psf.lt/", short_eu: "https://vw.psf.lt/",
tor: "http://pass.pjsfkvpxlinjamtawaksbnnaqs2fc2mtvmozrzckxh7f3kis6yea25ad.onion", tor: "http://pass.pjsfkvpxlinjamtawaksbnnaqs2fc2mtvmozrzckxh7f3kis6yea25ad.onion",
icon: "/icons/vaultwarden.svg" icon: "/icons/vaultwarden.svg"
}, },
{ {
name: "Plausible analytics", name: "Plausible Analytics",
description: "Analytics for our website.", description: "Analytics for our website.",
eu: "https://analytics.projectsegfau.lt/", eu: "https://analytics.projectsegfau.lt/",
icon: "/icons/plausible.png" icon: "/icons/plausible.png"
}, },
{ {
name: "Healthchecks", name: "Healthchecks",
description: "Simple and Effective Cron Job Monitoring.", description: "Simple and effective cron job monitoring.",
eu: "https://healthchecks.projectsegfau.lt/", eu: "https://healthchecks.projectsegfau.lt/",
short_eu: "https://hc.psf.lt/", short_eu: "https://hc.psf.lt/",
icon: "/icons/healthchecks.svg" icon: "/icons/healthchecks.svg"
@ -358,7 +360,8 @@ const instances: Instances[] = [
data: [ data: [
{ {
name: "Pubnix", name: "Pubnix",
description: "A Unix server open to the public with non-commercial recreational goals.", description:
"A Unix server open to the public for non-commercial recreational usage.",
eu: "https://p.projectsegfau.lt/", eu: "https://p.projectsegfau.lt/",
short_eu: "https://p.psf.lt/", short_eu: "https://p.psf.lt/",
icon: "/icons/pubnix.png" icon: "/icons/pubnix.png"
@ -399,14 +402,15 @@ const instances: Instances[] = [
}, },
{ {
name: "SimpleLogin", name: "SimpleLogin",
description: "An open source email alias creator/manager", description: "An open-source email alias creator/manager",
eu: "https://sl.projectsegfau.lt/", eu: "https://sl.projectsegfau.lt/",
short_eu: "https://sl.psf.lt/", short_eu: "https://sl.psf.lt/",
icon: "/icons/simplelogin.svg" icon: "/icons/simplelogin.svg"
}, },
{ {
name: "Dendrite", name: "Dendrite",
description: "Another matrix server, running on Project Segfault's India node!", description:
"Another Matrix server running on Project Segfault's India node!",
eu: "https://w.psf.lt/Matrix#Dendrite", eu: "https://w.psf.lt/Matrix#Dendrite",
icon: "/icons/matrix.svg" icon: "/icons/matrix.svg"
} }

View File

@ -24,22 +24,22 @@
<h3>What do I do if a user is disturbing me?</h3> <h3>What do I do if a user is disturbing me?</h3>
<p> <p>
If some user of our services is disturbing you, you should immediately If you are being disturbed by a user on our services, then you should
contact us. You can do that either by <a immediately contact us. You can do that by sending us an <a
href="mailto:contact@projectsegfau.lt">emailing us</a href="mailto:contact@projectsegfau.lt">email</a
> >
or sending us a message on or through our Matrix
<a href="https://matrix.to/#/#support:projectsegfau.lt" <a href="https://matrix.to/#/#support:projectsegfau.lt">support channel</a>.
>the Matrix support channel</a If you prefer to keep your report private on Matrix, contact one of our team
>. If you prefer to keep your report private on Matrix, contact one of our members directly. You can find their info on our
team members. You can find their info on <a href="/team">our team page</a>. <a href="/team">team page</a>.
</p> </p>
<h3>How can I trust you?</h3> <h3>How can I trust you?</h3>
<p> <p>
We have written a privacy policy, which is accessible through this website! We have a <a href="/legal/privacy-policy">privacy policy</a> which outlines how
You can find it <a href="/legal/privacy-policy">here</a>. we collect and handle your data.
</p> </p>
<style> <style>

View File

@ -12,20 +12,20 @@
Do not use our services to (D)DOS or attempt to disrupt someone elses Do not use our services to (D)DOS or attempt to disrupt someone elses
online stability. online stability.
</li> </li>
<li>Do not use our services to dox someone.</li> <li class="mt-2">Do not use our services to dox someone.</li>
<li> <li class="mt-2">
Do not do anything on our services that would be illegal in France, the Do not do anything on our services that would be illegal in France, the
USA, Luxembourg, and India. (Example: CSAM, Loli, Drugs etc...) USA, Luxembourg, and India. (Example: CSAM, Loli, Drugs etc...)
</li> </li>
<li>Do not harass people using our services.</li> <li class="mt-2">Do not harass people using our services.</li>
<li> <li class="mt-2">
While we do try to keep your data safe, you have to acknowledge that we While we do try to keep your data safe, you have to acknowledge that we
are not responsible if anything unintentional happens (such as data are not responsible if anything unintentional happens (such as data
loss, inability to extract your data due to the server being down or loss, inability to extract your data due to the server being down or
something else.). It is also your responsibility to keep a backup of something else.). It is also your responsibility to keep a backup of
your data if it matters to you. your data if it matters to you.
</li> </li>
<li> <li class="mt-2">
The services provided by Project Segfault are provided as is. We do not The services provided by Project Segfault are provided as is. We do not
warrant the reliability, accessibility or quality of our services and we warrant the reliability, accessibility or quality of our services and we
are not responsible for ANY DAMAGES WHATSOEVER by using our services. are not responsible for ANY DAMAGES WHATSOEVER by using our services.

View File

@ -10,5 +10,5 @@ export const load = (async () => {
return { return {
users: get(pubnixUsers), users: get(pubnixUsers),
...meta ...meta
} };
}) satisfies PageServerLoad; }) satisfies PageServerLoad;

View File

@ -49,28 +49,38 @@
</div> </div>
<div class="children:text-text flex flex-row items-center gap-4 text-lg"> <div class="children:text-text flex flex-row items-center gap-4 text-lg">
{#if user.email} {#if user.email}
<a href="mailto:{user.email}"><div class="i-ic:outline-email" /></a> <a
href="mailto:{user.email}"
aria-label="Email"><div class="i-ic:outline-email" /></a
>
{/if} {/if}
{#if user.matrix} {#if user.matrix}
<a href="https://matrix.to/#/{user.matrix}" <a
><div class="i-simple-icons:matrix" /></a href="https://matrix.to/#/{user.matrix}"
aria-label="Matrix"><div class="i-simple-icons:matrix" /></a
> >
{/if} {/if}
{#if user.fediverse} {#if user.fediverse}
<a href="https://{user.fediverse}" <a
href="https://{user.fediverse}"
aria-label="Fediverse"
><div class="i-simple-icons:mastodon" /></a ><div class="i-simple-icons:mastodon" /></a
> >
{/if} {/if}
{#if user.website} {#if user.website}
<a href={user.website}><div class="i-ic:outline-language" /></a> <a
href={user.website}
aria-label="Website"><div class="i-ic:outline-language" /></a
>
{/if} {/if}
{#if user.capsule} {#if user.capsule}
<a <a
href="https://geminiproxy.p.projectsegfau.lt/gemini/{user.capsule}" href="https://geminiproxy.p.projectsegfau.lt/gemini/{user.capsule}"
aria-label="Gemini"
class="no-underline text-base">Gemini</a class="no-underline text-base">Gemini</a
> >
{/if} {/if}

View File

@ -22,16 +22,15 @@
> >
<h2>How do I get started?</h2> <h2>How do I get started?</h2>
<span <span
>First, you need to register an account. You can do that <a >First, you need to <a href="/pubnix/register">register an account</a>.
href="/pubnix/register">here</a After registering, you need to wait a while because we manually check each
>. After registering, you need to wait a while because we manually check registration. If you get accepted, you will receive an email.</span
each registration. If you get accepted, you will receive an email.</span
> >
<h2>What's your systems specs?</h2> <h2>What are your system's specs?</h2>
<span>Guess you'll have to find out. Join today!</span> <span>Guess you'll have to find out. Join today!</span>
<h2>I joined, but I have no idea what to do.</h2> <h2>I joined, but I have no idea what to do.</h2>
<span <span
>No worries! We have put out tutorials on how to do common things on our <a >No worries! We put out tutorials on how to do common things on our <a
href="https://wiki.projectsegfau.lt/index.php?title=Category%3APubnix" href="https://wiki.projectsegfau.lt/index.php?title=Category%3APubnix"
>wiki</a >wiki</a
>.</span >.</span
@ -41,6 +40,9 @@
>Yep! We have a <a href="https://matrix.to/#/#pubnix:projectsegfau.lt" >Yep! We have a <a href="https://matrix.to/#/#pubnix:projectsegfau.lt"
>Matrix room</a >Matrix room</a
> >
and an <a href="https://join.jabber.network/#pubnix@conference.projectsegfau.lt?join">XMPP MUC</a> to and an
discuss the pubnix.</span <a
href="https://join.jabber.network/#pubnix@conference.projectsegfau.lt?join"
>XMPP MUC</a
> to discuss the pubnix.</span
> >

View File

@ -47,13 +47,10 @@
rows="5" rows="5"
required required
/> />
<div>
<label for="h-captcha-response"
><HCaptcha sitekey={siteKey} />
</label>
</div> </div>
<div>
<label for="h-captcha-response"><HCaptcha sitekey={siteKey} /> </label>
</div> </div>
{#if form?.success} {#if form?.success}
@ -64,8 +61,18 @@
{form.message} {form.message}
{/if} {/if}
<div style="display:block;" > <div style="display:block;">
<input type="checkbox" style="display:inline-block;width: 1em;margin-right: 10px;" required><p style="display:inline-block;word-break: break-all;">I agree to the <a href="/legal/tos">Terms of Service</p>. <input
id="tos"
type="checkbox"
required
/>
<label
for="tos"
style="display:inline-block;word-break: break-all;"
>
I agree to the <a href="/legal/tos">Terms of Service</a>.
</label>
</div> </div>
<button <button
@ -81,12 +88,20 @@
form > div { form > div {
@apply flex flex-col items-start gap-2 w-fit; @apply flex flex-col items-start gap-2 w-fit;
} }
form > div > label {
form label:not([for="tos"]) {
@apply text-xl font-semibold; @apply text-xl font-semibold;
} }
form > div > input,
form > div > textarea, form input,
form > button { form textarea,
@apply w-110 lt-sm\:w-70 px-2 py-1 bg-secondary rounded flex items-center gap-2 text-lg; form button {
@apply w-110 lt-sm\:w-70 px-2 py-1 bg-secondary rounded flex justify-center items-center gap-2 text-lg;
border: 1pt solid var(--alt);
}
form input[type="checkbox"] {
display: inline-block;
width: min-content;
} }
</style> </style>

View File

@ -10,5 +10,5 @@ export const load = (async () => {
return { return {
users: get(pubnixUsers), users: get(pubnixUsers),
...meta ...meta
} };
}) satisfies PageServerLoad; }) satisfies PageServerLoad;

View File

@ -20,40 +20,55 @@
</div> </div>
<div class="children:text-text flex flex-row gap-4 text-lg"> <div class="children:text-text flex flex-row gap-4 text-lg">
{#if member.website} {#if member.website}
<a href={member.website} <a
href={member.website}
aria-label="Website"
><div class="i-ic:outline-language" /></a ><div class="i-ic:outline-language" /></a
> >
{/if} {/if}
{#if member.matrix} {#if member.matrix}
<a href={member.matrix} <a
href={member.matrix}
aria-label="Matrix"
><div class="i-simple-icons:matrix" /></a ><div class="i-simple-icons:matrix" /></a
> >
{/if} {/if}
{#if member.xmpp} {#if member.xmpp}
<a href={member.xmpp}><div class="i-simple-icons:xmpp" /></a <a
href={member.xmpp}
aria-label="XMPP"><div class="i-simple-icons:xmpp" /></a
> >
{/if} {/if}
{#if member.fedi} {#if member.fedi}
<a href={member.fedi} <a
href={member.fedi}
aria-label="Fediverse"
><div class="i-simple-icons:mastodon" /></a ><div class="i-simple-icons:mastodon" /></a
> >
{/if} {/if}
{#if member.git} {#if member.git}
<a href={member.git}><div class="i-simple-icons:git" /></a> <a
href={member.git}
aria-label="Git"><div class="i-simple-icons:git" /></a
>
{/if} {/if}
{#if member.email} {#if member.email}
<a href="mailto:{member.email}" <a
><div class="i-ic:outline-email" /></a href="mailto:{member.email}"
aria-label="Email"><div class="i-ic:outline-email" /></a
> >
{/if} {/if}
{#if member.pgp} {#if member.pgp}
<a href={member.pgp}><div class="i-ic:outline-vpn-key" /></a <a
href={member.pgp}
aria-label="PGP key"
><div class="i-ic:outline-vpn-key" /></a
> >
{/if} {/if}
</div> </div>

View File

@ -37,7 +37,7 @@
}, },
{ {
"name": "py_", "name": "py_",
"description": "Self-proclaimed front-end dev", "description": "self-proclaimed front-end dev",
"position": "Webdev", "position": "Webdev",
"website": "https://py.p.psf.lt", "website": "https://py.p.psf.lt",
"matrix": "https://matrix.to/#/@py_:catgirl.cloud", "matrix": "https://matrix.to/#/@py_:catgirl.cloud",

View File

@ -22,7 +22,12 @@ export default defineConfig({
transformers: [transformerVariantGroup(), transformerDirectives()], transformers: [transformerVariantGroup(), transformerDirectives()],
safelist: ["i-ic:outline-dark-mode", "i-ic:outline-light-mode", "i-ic:baseline-toggle-on", "i-ic:baseline-toggle-off"], safelist: [
"i-ic:outline-dark-mode",
"i-ic:outline-light-mode",
"i-ic:baseline-toggle-on",
"i-ic:baseline-toggle-off"
],
theme: { theme: {
fontFamily: { fontFamily: {