mirror of https://github.com/kitsune-soc/kitsune
Compare commits
10 Commits
397a351ce2
...
7282068f54
Author | SHA1 | Date |
---|---|---|
Aumetra Weisman | 7282068f54 | |
Aumetra Weisman | e5da0b2131 | |
vesdev | 4299c333ba | |
Aumetra Weisman | f78688a55d | |
Aumetra Weisman | 3acad3500d | |
Aumetra Weisman | fdb333a7ab | |
Aumetra Weisman | c81fb6c3d1 | |
Aumetra Weisman | 7ba9db488a | |
Aumetra Weisman | 9386f1742a | |
Aumetra Weisman | 6f79177bae |
352
flake.nix
352
flake.nix
|
@ -26,169 +26,209 @@
|
|||
# like so `nix build --override-input debugBuild github:boolean-option/true`
|
||||
debugBuild.url = "github:boolean-option/false/d06b4794a134686c70a1325df88a6e6768c6b212";
|
||||
};
|
||||
outputs = { self, devenv, flake-utils, nixpkgs, rust-overlay, crane, ... } @ inputs:
|
||||
(flake-utils.lib.eachDefaultSystem
|
||||
(system:
|
||||
let
|
||||
features = "--all-features";
|
||||
overlays = [ (import rust-overlay) ];
|
||||
pkgs = import nixpkgs {
|
||||
inherit overlays system;
|
||||
};
|
||||
stdenv = pkgs.stdenvAdapters.useMoldLinker pkgs.stdenv;
|
||||
rustPlatform = pkgs.makeRustPlatform {
|
||||
cargo = pkgs.rust-bin.stable.latest.minimal;
|
||||
rustc = pkgs.rust-bin.stable.latest.minimal;
|
||||
inherit stdenv;
|
||||
};
|
||||
|
||||
craneLib = (crane.mkLib pkgs).overrideToolchain pkgs.rust-bin.stable.latest.minimal;
|
||||
buildInputs = with pkgs; [
|
||||
openssl
|
||||
sqlite
|
||||
zlib
|
||||
];
|
||||
|
||||
nativeBuildInputs = with pkgs; [
|
||||
protobuf
|
||||
pkg-config
|
||||
rustPlatform.bindgenHook
|
||||
];
|
||||
|
||||
src = pkgs.lib.cleanSourceWith {
|
||||
src = pkgs.lib.cleanSource ./.;
|
||||
filter = name: type:
|
||||
let baseName = baseNameOf (toString name);
|
||||
in !(baseName == "flake.lock" || pkgs.lib.hasSuffix ".nix" baseName);
|
||||
};
|
||||
|
||||
commonArgs = {
|
||||
inherit src stdenv buildInputs nativeBuildInputs;
|
||||
|
||||
strictDeps = true;
|
||||
|
||||
meta = {
|
||||
description = "ActivityPub-federated microblogging";
|
||||
homepage = "https://joinkitsune.org";
|
||||
outputs =
|
||||
{ self
|
||||
, devenv
|
||||
, flake-utils
|
||||
, nixpkgs
|
||||
, rust-overlay
|
||||
, crane
|
||||
, ...
|
||||
}@inputs:
|
||||
(
|
||||
flake-utils.lib.eachDefaultSystem
|
||||
(
|
||||
system:
|
||||
let
|
||||
features = "--all-features";
|
||||
overlays = [ (import rust-overlay) ];
|
||||
pkgs = import nixpkgs { inherit overlays system; };
|
||||
stdenv = pkgs.stdenvAdapters.useMoldLinker pkgs.stdenv;
|
||||
rustPlatform = pkgs.makeRustPlatform {
|
||||
cargo = pkgs.rust-bin.stable.latest.minimal;
|
||||
rustc = pkgs.rust-bin.stable.latest.minimal;
|
||||
inherit stdenv;
|
||||
};
|
||||
|
||||
OPENSSL_NO_VENDOR = 1;
|
||||
NIX_OUTPATH_USED_AS_RANDOM_SEED = "aaaaaaaaaa";
|
||||
cargoExtraArgs = "--locked ${features}";
|
||||
} // (pkgs.lib.optionalAttrs inputs.debugBuild.value {
|
||||
# do a debug build, as `dev` is the default debug profile
|
||||
CARGO_PROFILE = "dev";
|
||||
});
|
||||
craneLib = (crane.mkLib pkgs).overrideToolchain pkgs.rust-bin.stable.latest.minimal;
|
||||
buildInputs = with pkgs; [
|
||||
openssl
|
||||
sqlite
|
||||
zlib
|
||||
];
|
||||
|
||||
cargoToml = builtins.fromTOML (builtins.readFile ./Cargo.toml);
|
||||
version = cargoToml.workspace.package.version;
|
||||
nativeBuildInputs = with pkgs; [
|
||||
protobuf
|
||||
pkg-config
|
||||
rustPlatform.bindgenHook
|
||||
];
|
||||
|
||||
cargoArtifacts = craneLib.buildDepsOnly (commonArgs // {
|
||||
pname = "kitsune-workspace";
|
||||
src = craneLib.cleanCargoSource src;
|
||||
});
|
||||
in
|
||||
{
|
||||
formatter = pkgs.nixpkgs-fmt;
|
||||
packages = rec {
|
||||
default = main;
|
||||
|
||||
cli = craneLib.buildPackage (commonArgs // {
|
||||
pname = "kitsune-cli";
|
||||
cargoExtraArgs = commonArgs.cargoExtraArgs + " --bin kitsune-cli";
|
||||
inherit cargoArtifacts;
|
||||
doCheck = false;
|
||||
});
|
||||
|
||||
mrf-tool = craneLib.buildPackage (commonArgs // {
|
||||
pname = "mrf-tool";
|
||||
cargoExtraArgs = commonArgs.cargoExtraArgs + " --bin mrf-tool";
|
||||
inherit cargoArtifacts;
|
||||
doCheck = false;
|
||||
});
|
||||
|
||||
main = craneLib.buildPackage (commonArgs // rec {
|
||||
pname = "kitsune";
|
||||
cargoExtraArgs = commonArgs.cargoExtraArgs + " --bin kitsune --bin kitsune-job-runner";
|
||||
inherit cargoArtifacts;
|
||||
doCheck = false;
|
||||
});
|
||||
|
||||
frontend = pkgs.mkYarnPackage {
|
||||
inherit version;
|
||||
packageJSON = "${src}/kitsune-fe/package.json";
|
||||
yarnLock = "${src}/kitsune-fe/yarn.lock";
|
||||
src = "${src}/kitsune-fe";
|
||||
|
||||
buildPhase = ''
|
||||
export HOME=$(mktemp -d)
|
||||
yarn --offline build
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out
|
||||
cp -R deps/kitsune-fe/dist $out
|
||||
'';
|
||||
|
||||
distPhase = "true";
|
||||
};
|
||||
};
|
||||
|
||||
devShells = rec {
|
||||
default = backend;
|
||||
|
||||
backend = devenv.lib.mkShell {
|
||||
inherit pkgs inputs;
|
||||
|
||||
modules = [
|
||||
({ pkgs, ... }: {
|
||||
packages = with pkgs; [
|
||||
cargo-insta
|
||||
diesel-cli
|
||||
rust-bin.stable.latest.default
|
||||
]
|
||||
++
|
||||
buildInputs ++ nativeBuildInputs;
|
||||
|
||||
enterShell = ''
|
||||
export PG_HOST=127.0.0.1
|
||||
export PG_PORT=5432
|
||||
[ -z "$DATABASE_URL" ] && export DATABASE_URL=postgres://$USER@$PG_HOST:$PG_PORT/$USER
|
||||
|
||||
export REDIS_PORT=6379
|
||||
[ -z "$REDIS_URL" ] && export REDIS_URL="redis://127.0.0.1:$REDIS_PORT"
|
||||
'';
|
||||
|
||||
services = {
|
||||
postgres = {
|
||||
enable = true;
|
||||
listen_addresses = "127.0.0.1";
|
||||
};
|
||||
redis.enable = true;
|
||||
};
|
||||
})
|
||||
];
|
||||
src = pkgs.lib.cleanSourceWith {
|
||||
src = pkgs.lib.cleanSource ./.;
|
||||
filter =
|
||||
name: type:
|
||||
let
|
||||
baseName = baseNameOf (toString name);
|
||||
in
|
||||
!(baseName == "flake.lock" || pkgs.lib.hasSuffix ".nix" baseName);
|
||||
};
|
||||
|
||||
frontend = pkgs.mkShell {
|
||||
buildInputs = with pkgs; [
|
||||
nodejs
|
||||
yarn
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
) // {
|
||||
overlays = rec {
|
||||
default = kitsune;
|
||||
kitsune = (import ./overlay.nix self);
|
||||
};
|
||||
commonArgs =
|
||||
{
|
||||
inherit
|
||||
src
|
||||
stdenv
|
||||
buildInputs
|
||||
nativeBuildInputs
|
||||
;
|
||||
|
||||
nixosModules = rec {
|
||||
default = kitsune;
|
||||
kitsune = (import ./module.nix);
|
||||
};
|
||||
}) // {
|
||||
strictDeps = true;
|
||||
|
||||
meta = {
|
||||
description = "ActivityPub-federated microblogging";
|
||||
homepage = "https://joinkitsune.org";
|
||||
};
|
||||
|
||||
OPENSSL_NO_VENDOR = 1;
|
||||
NIX_OUTPATH_USED_AS_RANDOM_SEED = "aaaaaaaaaa";
|
||||
cargoExtraArgs = "--locked ${features}";
|
||||
}
|
||||
// (pkgs.lib.optionalAttrs inputs.debugBuild.value {
|
||||
# do a debug build, as `dev` is the default debug profile
|
||||
CARGO_PROFILE = "dev";
|
||||
});
|
||||
|
||||
cargoToml = builtins.fromTOML (builtins.readFile ./Cargo.toml);
|
||||
version = cargoToml.workspace.package.version;
|
||||
|
||||
cargoArtifacts = craneLib.buildDepsOnly (
|
||||
commonArgs
|
||||
// {
|
||||
pname = "kitsune-workspace";
|
||||
src = craneLib.cleanCargoSource src;
|
||||
}
|
||||
);
|
||||
in
|
||||
{
|
||||
formatter = pkgs.nixpkgs-fmt;
|
||||
packages = rec {
|
||||
default = main;
|
||||
|
||||
cli = craneLib.buildPackage (
|
||||
commonArgs
|
||||
// {
|
||||
pname = "kitsune-cli";
|
||||
cargoExtraArgs = commonArgs.cargoExtraArgs + " --bin kitsune-cli";
|
||||
inherit cargoArtifacts;
|
||||
doCheck = false;
|
||||
}
|
||||
);
|
||||
|
||||
mrf-tool = craneLib.buildPackage (
|
||||
commonArgs
|
||||
// {
|
||||
pname = "mrf-tool";
|
||||
cargoExtraArgs = commonArgs.cargoExtraArgs + " --bin mrf-tool";
|
||||
inherit cargoArtifacts;
|
||||
doCheck = false;
|
||||
}
|
||||
);
|
||||
|
||||
main = craneLib.buildPackage (
|
||||
commonArgs
|
||||
// {
|
||||
pname = "kitsune";
|
||||
cargoExtraArgs = commonArgs.cargoExtraArgs + " --bin kitsune --bin kitsune-job-runner";
|
||||
inherit cargoArtifacts;
|
||||
doCheck = false;
|
||||
}
|
||||
);
|
||||
|
||||
frontend = pkgs.mkYarnPackage {
|
||||
inherit version;
|
||||
packageJSON = "${src}/kitsune-fe/package.json";
|
||||
yarnLock = "${src}/kitsune-fe/yarn.lock";
|
||||
src = "${src}/kitsune-fe";
|
||||
|
||||
buildPhase = ''
|
||||
export HOME=$(mktemp -d)
|
||||
yarn --offline build
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out
|
||||
cp -R deps/kitsune-fe/dist $out
|
||||
'';
|
||||
|
||||
distPhase = "true";
|
||||
};
|
||||
};
|
||||
|
||||
devShells = rec {
|
||||
default = backend;
|
||||
|
||||
backend = devenv.lib.mkShell {
|
||||
inherit pkgs inputs;
|
||||
|
||||
modules = [
|
||||
(
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
packages =
|
||||
with pkgs;
|
||||
[
|
||||
cargo-insta
|
||||
diesel-cli
|
||||
rust-bin.stable.latest.default
|
||||
]
|
||||
++ buildInputs
|
||||
++ nativeBuildInputs;
|
||||
|
||||
enterShell = ''
|
||||
export PG_HOST=127.0.0.1
|
||||
export PG_PORT=5432
|
||||
[ -z "$DATABASE_URL" ] && export DATABASE_URL=postgres://$USER@$PG_HOST:$PG_PORT/$USER
|
||||
|
||||
export REDIS_PORT=6379
|
||||
[ -z "$REDIS_URL" ] && export REDIS_URL="redis://127.0.0.1:$REDIS_PORT"
|
||||
'';
|
||||
|
||||
services = {
|
||||
postgres = {
|
||||
enable = true;
|
||||
listen_addresses = "127.0.0.1";
|
||||
};
|
||||
redis.enable = true;
|
||||
};
|
||||
}
|
||||
)
|
||||
];
|
||||
};
|
||||
|
||||
frontend = pkgs.mkShell {
|
||||
buildInputs = with pkgs; [
|
||||
nodejs
|
||||
yarn
|
||||
nodePackages.svelte-language-server
|
||||
nodePackages.typescript-language-server
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
)
|
||||
// {
|
||||
overlays = rec {
|
||||
default = kitsune;
|
||||
kitsune = (import ./overlay.nix self);
|
||||
};
|
||||
|
||||
nixosModules = rec {
|
||||
default = kitsune;
|
||||
kitsune = (import ./module.nix);
|
||||
};
|
||||
}
|
||||
)
|
||||
// {
|
||||
nixci.default = {
|
||||
debug = {
|
||||
dir = ".";
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
|
@ -0,0 +1 @@
|
|||
dist/
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"endOfLine": "lf",
|
||||
"importOrder": ["^\\w", "^[./|~/]"],
|
||||
"importOrderSeparation": true,
|
||||
"importOrderParserPlugins": ["typescript"],
|
||||
"plugins": [
|
||||
"@trivago/prettier-plugin-sort-imports",
|
||||
"prettier-plugin-css-order"
|
||||
],
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"vueIndentScriptAndStyle": true
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
# Kitsune FE
|
||||
|
||||
Frontend for Kitsune using its GraphQL API
|
||||
|
||||
## Build
|
||||
|
||||
```
|
||||
yarn build
|
||||
```
|
||||
|
||||
## Development server
|
||||
|
||||
```
|
||||
yarn dev
|
||||
```
|
||||
|
||||
Set the backend the frontend uses inside `.env.development`
|
||||
|
||||
## Autogenerate GraphQL typings in the background
|
||||
|
||||
```
|
||||
yarn graphql-codegen --watch
|
||||
```
|
|
@ -0,0 +1,73 @@
|
|||
{
|
||||
"name": "kitsune-fe",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vue-tsc && vite build",
|
||||
"preview": "vite preview",
|
||||
"lint": "eslint src",
|
||||
"format": "prettier . --write"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fluent/bundle": "^0.18.0",
|
||||
"@formkit/core": "^1.6.2",
|
||||
"@formkit/validation": "^1.6.2",
|
||||
"@formkit/vue": "^1.6.2",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.5.2",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.5.2",
|
||||
"@fortawesome/vue-fontawesome": "^3.0.6",
|
||||
"@hcaptcha/vue3-hcaptcha": "^1.3.0",
|
||||
"@mcaptcha/vanilla-glue": "^0.1.0-alpha-3",
|
||||
"@tiptap/pm": "^2.3.0",
|
||||
"@tiptap/starter-kit": "^2.3.0",
|
||||
"@tiptap/vue-3": "^2.3.0",
|
||||
"@urql/exchange-graphcache": "^7.0.1",
|
||||
"@urql/vue": "^1.1.3",
|
||||
"@vueuse/core": "^10.9.0",
|
||||
"@zxcvbn-ts/core": "^3.0.4",
|
||||
"@zxcvbn-ts/language-common": "^3.0.4",
|
||||
"@zxcvbn-ts/language-en": "^3.0.2",
|
||||
"floating-vue": "^5.2.2",
|
||||
"fluent-vue": "^3.5.2",
|
||||
"graphql": "^16.8.1",
|
||||
"lodash": "^4.17.21",
|
||||
"pinia": "^2.1.7",
|
||||
"pinia-plugin-persistedstate": "^3.2.1",
|
||||
"rollup": "npm:@rollup/wasm-node",
|
||||
"tiptap-markdown": "^0.8.10",
|
||||
"unhead": "^1.9.7",
|
||||
"vue": "^3.4.23",
|
||||
"vue-powerglitch": "^1.0.0",
|
||||
"vue-router": "^4.3.2",
|
||||
"vue-virtual-scroller": "^2.0.0-beta.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@graphql-codegen/cli": "^5.0.2",
|
||||
"@graphql-codegen/client-preset": "^4.2.5",
|
||||
"@parcel/watcher": "^2.4.1",
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
|
||||
"@types/lodash": "^4.17.0",
|
||||
"@typescript-eslint/eslint-plugin": "^7.7.0",
|
||||
"@typescript-eslint/parser": "^7.7.0",
|
||||
"@vitejs/plugin-vue": "^5.0.4",
|
||||
"@vue/eslint-config-prettier": "^9.0.0",
|
||||
"@vue/eslint-config-typescript": "^13.0.0",
|
||||
"eslint": "^9.1.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"eslint-plugin-vue": "^9.25.0",
|
||||
"prettier": "^3.2.5",
|
||||
"prettier-plugin-css-order": "^2.1.2",
|
||||
"sass": "^1.75.0",
|
||||
"typescript": "^5.4.5",
|
||||
"unplugin-fluent-vue": "^1.3.0",
|
||||
"vite": "^5.2.10",
|
||||
"vue-tsc": "^2.0.13"
|
||||
},
|
||||
"resolutions": {
|
||||
"rollup": "npm:@rollup/wasm-node"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 6.9 KiB |
|
@ -0,0 +1,9 @@
|
|||
// Source: Tailwind <https://tailwindcss.com/docs/screens>
|
||||
|
||||
$breakpoints: (
|
||||
sm: 640px,
|
||||
md: 768px,
|
||||
lg: 1024px,
|
||||
xl: 1280px,
|
||||
xxl: 1536px,
|
||||
);
|
|
@ -0,0 +1,7 @@
|
|||
$dark1: #0f1026;
|
||||
$dark2: #051c30;
|
||||
$dark3: #042f40;
|
||||
$shade1dark: #53a0c4;
|
||||
$shade1light: #afd7fa;
|
||||
$shade2dark: #935d7e;
|
||||
$shade2light: #d68fbc;
|
|
@ -0,0 +1,8 @@
|
|||
@use './breakpoints' as *;
|
||||
@use 'sass:map';
|
||||
|
||||
@mixin only-on-mobile {
|
||||
@media only screen and (max-width: map.get($breakpoints, md)) {
|
||||
@content;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
@use 'colours' as *;
|
||||
@use 'fonts' as *;
|
||||
|
||||
* {
|
||||
// font-family: BlockZone;
|
||||
box-sizing: inherit;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
}
|
||||
|
||||
:root {
|
||||
background-color: $dark1;
|
||||
color: white;
|
||||
|
||||
color-scheme: light dark;
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
|
||||
font-synthesis: none;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
a {
|
||||
color: $shade2light;
|
||||
font-weight: 500;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
margin-top: 85px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 0.666em;
|
||||
height: 0.666em;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: $shade2light;
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"strict": true,
|
||||
"jsx": "preserve",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"esModuleInterop": true,
|
||||
"lib": ["ESNext", "DOM"],
|
||||
"skipLibCheck": true,
|
||||
"noEmit": true
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
import vue from '@vitejs/plugin-vue';
|
||||
|
||||
import path from 'node:path';
|
||||
import { ExternalFluentPlugin } from 'unplugin-fluent-vue/vite';
|
||||
import { defineConfig } from 'vite';
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
build: {
|
||||
rollupOptions: {
|
||||
output: {
|
||||
manualChunks: {
|
||||
zxcvbnCommon: ['@zxcvbn-ts/language-common'],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
vue(),
|
||||
ExternalFluentPlugin({
|
||||
locales: ['en', 'en-cyberpunk'],
|
||||
checkSyntax: true,
|
||||
|
||||
baseDir: path.resolve('src'),
|
||||
ftlDir: path.resolve('src/locales'),
|
||||
|
||||
getFtlPath(locale) {
|
||||
return path.join('src/locales', `${locale}.ftl`);
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
|
@ -0,0 +1,13 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
/build
|
||||
/.svelte-kit
|
||||
/package
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# Ignore files for PNPM, NPM and YARN
|
||||
pnpm-lock.yaml
|
||||
package-lock.json
|
||||
yarn.lock
|
|
@ -0,0 +1,31 @@
|
|||
/** @type { import("eslint").Linter.Config } */
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:svelte/recommended',
|
||||
'prettier'
|
||||
],
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: ['@typescript-eslint'],
|
||||
parserOptions: {
|
||||
sourceType: 'module',
|
||||
ecmaVersion: 2020,
|
||||
extraFileExtensions: ['.svelte']
|
||||
},
|
||||
env: {
|
||||
browser: true,
|
||||
es2017: true,
|
||||
node: true
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.svelte'],
|
||||
parser: 'svelte-eslint-parser',
|
||||
parserOptions: {
|
||||
parser: '@typescript-eslint/parser'
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
|
@ -1,24 +1,12 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
node_modules
|
||||
/build
|
||||
/.svelte-kit
|
||||
/package
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
vite.config.js.timestamp-*
|
||||
vite.config.ts.timestamp-*
|
||||
|
||||
$houdini
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
projects:
|
||||
default:
|
||||
schema:
|
||||
- ./schema.graphql
|
||||
- ./$houdini/graphql/schema.graphql
|
||||
documents:
|
||||
- '**/*.gql'
|
||||
- '**/*.svelte'
|
||||
- ./$houdini/graphql/documents.gql
|
|
@ -0,0 +1 @@
|
|||
engine-strict=true
|
|
@ -1 +1,4 @@
|
|||
dist/
|
||||
# Ignore files for PNPM, NPM and YARN
|
||||
pnpm-lock.yaml
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
{
|
||||
"endOfLine": "lf",
|
||||
"importOrder": ["^\\w", "^[./|~/]"],
|
||||
"importOrderSeparation": true,
|
||||
"importOrderParserPlugins": ["typescript"],
|
||||
"plugins": [
|
||||
"@trivago/prettier-plugin-sort-imports",
|
||||
"prettier-plugin-css-order"
|
||||
],
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"vueIndentScriptAndStyle": true
|
||||
"useTabs": true,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"printWidth": 100,
|
||||
"plugins": ["prettier-plugin-svelte"],
|
||||
"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
|
||||
}
|
||||
|
|
|
@ -1,23 +1,38 @@
|
|||
# Kitsune FE
|
||||
# create-svelte
|
||||
|
||||
Frontend for Kitsune using its GraphQL API
|
||||
Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/main/packages/create-svelte).
|
||||
|
||||
## Build
|
||||
## Creating a project
|
||||
|
||||
```
|
||||
yarn build
|
||||
If you're seeing this, you've probably already done this step. Congrats!
|
||||
|
||||
```bash
|
||||
# create a new project in the current directory
|
||||
npm create svelte@latest
|
||||
|
||||
# create a new project in my-app
|
||||
npm create svelte@latest my-app
|
||||
```
|
||||
|
||||
## Development server
|
||||
## Developing
|
||||
|
||||
```
|
||||
yarn dev
|
||||
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
|
||||
# or start the server and open the app in a new browser tab
|
||||
npm run dev -- --open
|
||||
```
|
||||
|
||||
Set the backend the frontend uses inside `.env.development`
|
||||
## Building
|
||||
|
||||
## Autogenerate GraphQL typings in the background
|
||||
To create a production version of your app:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
yarn graphql-codegen --watch
|
||||
```
|
||||
|
||||
You can preview the production build with `npm run preview`.
|
||||
|
||||
> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
/// <references types="houdini-svelte">
|
||||
|
||||
/** @type {import('houdini').ConfigFile} */
|
||||
const config = {
|
||||
watchSchema: {
|
||||
url: 'http://localhost:5000/graphql'
|
||||
},
|
||||
plugins: {
|
||||
'houdini-svelte': {}
|
||||
},
|
||||
scalars: {
|
||||
DateTime: {
|
||||
type: 'Date'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default config;
|
File diff suppressed because it is too large
Load Diff
|
@ -1,73 +1,39 @@
|
|||
{
|
||||
"name": "kitsune-fe",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vue-tsc && vite build",
|
||||
"preview": "vite preview",
|
||||
"lint": "eslint src",
|
||||
"format": "prettier . --write"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fluent/bundle": "^0.18.0",
|
||||
"@formkit/core": "^1.6.2",
|
||||
"@formkit/validation": "^1.6.2",
|
||||
"@formkit/vue": "^1.6.2",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.5.2",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.5.2",
|
||||
"@fortawesome/vue-fontawesome": "^3.0.6",
|
||||
"@hcaptcha/vue3-hcaptcha": "^1.3.0",
|
||||
"@mcaptcha/vanilla-glue": "^0.1.0-alpha-3",
|
||||
"@tiptap/pm": "^2.3.0",
|
||||
"@tiptap/starter-kit": "^2.3.0",
|
||||
"@tiptap/vue-3": "^2.3.0",
|
||||
"@urql/exchange-graphcache": "^7.0.1",
|
||||
"@urql/vue": "^1.1.3",
|
||||
"@vueuse/core": "^10.9.0",
|
||||
"@zxcvbn-ts/core": "^3.0.4",
|
||||
"@zxcvbn-ts/language-common": "^3.0.4",
|
||||
"@zxcvbn-ts/language-en": "^3.0.2",
|
||||
"floating-vue": "^5.2.2",
|
||||
"fluent-vue": "^3.5.2",
|
||||
"graphql": "^16.8.1",
|
||||
"lodash": "^4.17.21",
|
||||
"pinia": "^2.1.7",
|
||||
"pinia-plugin-persistedstate": "^3.2.1",
|
||||
"rollup": "npm:@rollup/wasm-node",
|
||||
"tiptap-markdown": "^0.8.10",
|
||||
"unhead": "^1.9.7",
|
||||
"vue": "^3.4.23",
|
||||
"vue-powerglitch": "^1.0.0",
|
||||
"vue-router": "^4.3.2",
|
||||
"vue-virtual-scroller": "^2.0.0-beta.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@graphql-codegen/cli": "^5.0.2",
|
||||
"@graphql-codegen/client-preset": "^4.2.5",
|
||||
"@parcel/watcher": "^2.4.1",
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
|
||||
"@types/lodash": "^4.17.0",
|
||||
"@typescript-eslint/eslint-plugin": "^7.7.0",
|
||||
"@typescript-eslint/parser": "^7.7.0",
|
||||
"@vitejs/plugin-vue": "^5.0.4",
|
||||
"@vue/eslint-config-prettier": "^9.0.0",
|
||||
"@vue/eslint-config-typescript": "^13.0.0",
|
||||
"eslint": "^9.1.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"eslint-plugin-vue": "^9.25.0",
|
||||
"prettier": "^3.2.5",
|
||||
"prettier-plugin-css-order": "^2.1.2",
|
||||
"sass": "^1.75.0",
|
||||
"typescript": "^5.4.5",
|
||||
"unplugin-fluent-vue": "^1.3.0",
|
||||
"vite": "^5.2.10",
|
||||
"vue-tsc": "^2.0.13"
|
||||
},
|
||||
"resolutions": {
|
||||
"rollup": "npm:@rollup/wasm-node"
|
||||
}
|
||||
"name": "kitsune-fe",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||
"test": "vitest",
|
||||
"lint": "prettier --check . && eslint .",
|
||||
"format": "prettier --write ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/adapter-static": "^3.0.1",
|
||||
"@sveltejs/kit": "^2.0.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^3.1.0",
|
||||
"@types/eslint": "^8.56.0",
|
||||
"@typescript-eslint/eslint-plugin": "^7.0.0",
|
||||
"@typescript-eslint/parser": "^7.0.0",
|
||||
"eslint": "^8.56.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-svelte": "^2.36.0-next.4",
|
||||
"houdini": "^0.0.0-20240429154814",
|
||||
"houdini-svelte": "^0.0.0-20240429154814",
|
||||
"prettier": "^3.1.1",
|
||||
"prettier-plugin-svelte": "^3.1.2",
|
||||
"sass": "^1.76.0",
|
||||
"svelte": "^5.0.0-next.1",
|
||||
"svelte-check": "^3.6.0",
|
||||
"tslib": "^2.4.1",
|
||||
"typescript": "^5.0.0",
|
||||
"unplugin-icons": "^0.19.0",
|
||||
"vite": "^5.0.3",
|
||||
"vitest": "^1.2.0"
|
||||
},
|
||||
"type": "module"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,198 @@
|
|||
schema {
|
||||
query: RootQuery
|
||||
mutation: RootMutation
|
||||
}
|
||||
|
||||
type Account {
|
||||
avatar: MediaAttachment
|
||||
createdAt: DateTime!
|
||||
displayName: String
|
||||
header: MediaAttachment
|
||||
id: UUID!
|
||||
locked: Boolean!
|
||||
note: String
|
||||
posts(after: String, before: String, first: Int, last: Int): PostConnection!
|
||||
updatedAt: DateTime!
|
||||
url: String!
|
||||
username: String!
|
||||
}
|
||||
|
||||
enum CaptchaBackend {
|
||||
H_CAPTCHA
|
||||
M_CAPTCHA
|
||||
}
|
||||
|
||||
type CaptchaInfo {
|
||||
backend: CaptchaBackend!
|
||||
key: String!
|
||||
}
|
||||
|
||||
"""
|
||||
A datetime with timezone offset.
|
||||
|
||||
The input is a string in RFC3339 format, e.g. "2022-01-12T04:00:19.12345Z"
|
||||
or "2022-01-12T04:00:19+03:00". The output is also a string in RFC3339
|
||||
format, but it is always normalized to the UTC (Z) offset, e.g.
|
||||
"2022-01-12T04:00:19.12345Z".
|
||||
"""
|
||||
scalar DateTime
|
||||
|
||||
type Instance {
|
||||
captcha: CaptchaInfo
|
||||
characterLimit: Int!
|
||||
description: String!
|
||||
domain: String!
|
||||
localPostCount: Int!
|
||||
name: String!
|
||||
registrationsOpen: Boolean!
|
||||
userCount: Int!
|
||||
version: String!
|
||||
}
|
||||
|
||||
type MediaAttachment {
|
||||
blurhash: String
|
||||
contentType: String!
|
||||
createdAt: DateTime!
|
||||
description: String
|
||||
id: UUID!
|
||||
uploader: Account!
|
||||
url: String!
|
||||
}
|
||||
|
||||
type OAuth2Application {
|
||||
createdAt: DateTime!
|
||||
id: UUID!
|
||||
name: String!
|
||||
redirectUri: String!
|
||||
secret: String!
|
||||
updatedAt: DateTime!
|
||||
}
|
||||
|
||||
"""
|
||||
Information about pagination in a connection
|
||||
"""
|
||||
type PageInfo {
|
||||
"""
|
||||
When paginating forwards, the cursor to continue.
|
||||
"""
|
||||
endCursor: String
|
||||
|
||||
"""
|
||||
When paginating forwards, are there more items?
|
||||
"""
|
||||
hasNextPage: Boolean!
|
||||
|
||||
"""
|
||||
When paginating backwards, are there more items?
|
||||
"""
|
||||
hasPreviousPage: Boolean!
|
||||
|
||||
"""
|
||||
When paginating backwards, the cursor to continue.
|
||||
"""
|
||||
startCursor: String
|
||||
}
|
||||
|
||||
type Post {
|
||||
account: Account!
|
||||
attachments: [MediaAttachment!]!
|
||||
content: String!
|
||||
createdAt: DateTime!
|
||||
id: UUID!
|
||||
isSensitive: Boolean!
|
||||
subject: String
|
||||
updatedAt: DateTime!
|
||||
url: String!
|
||||
visibility: Visibility!
|
||||
}
|
||||
|
||||
type PostConnection {
|
||||
"""
|
||||
A list of edges.
|
||||
"""
|
||||
edges: [PostEdge!]!
|
||||
|
||||
"""
|
||||
A list of nodes.
|
||||
"""
|
||||
nodes: [Post!]!
|
||||
|
||||
"""
|
||||
Information to aid in pagination.
|
||||
"""
|
||||
pageInfo: PageInfo!
|
||||
}
|
||||
|
||||
"""
|
||||
An edge in a connection.
|
||||
"""
|
||||
type PostEdge {
|
||||
"""
|
||||
A cursor for use in pagination
|
||||
"""
|
||||
cursor: String!
|
||||
|
||||
"""
|
||||
The item at the end of the edge
|
||||
"""
|
||||
node: Post!
|
||||
}
|
||||
|
||||
type RootMutation {
|
||||
createPost(content: String!, isSensitive: Boolean!, visibility: Visibility!): Post!
|
||||
deletePost(id: UUID!): UUID!
|
||||
registerOauthApplication(name: String!, redirectUri: String!): OAuth2Application!
|
||||
registerUser(captchaToken: String, email: String!, password: String!, username: String!): User!
|
||||
updateUser(
|
||||
avatar: Upload
|
||||
displayName: String
|
||||
header: Upload
|
||||
locked: Boolean
|
||||
note: String
|
||||
): Account!
|
||||
}
|
||||
|
||||
type RootQuery {
|
||||
getAccountById(id: UUID!): Account
|
||||
getPostById(id: UUID!): Post!
|
||||
homeTimeline(after: String, before: String, first: Int, last: Int): PostConnection!
|
||||
instance: Instance!
|
||||
myAccount: Account!
|
||||
publicTimeline(
|
||||
after: String
|
||||
before: String
|
||||
first: Int
|
||||
last: Int
|
||||
onlyLocal: Boolean! = true
|
||||
): PostConnection!
|
||||
}
|
||||
|
||||
"""
|
||||
A UUID is a unique 128-bit number, stored as 16 octets. UUIDs are parsed as
|
||||
Strings within GraphQL. UUIDs are used to assign unique identifiers to
|
||||
entities without requiring a central allocating authority.
|
||||
|
||||
# References
|
||||
|
||||
* [Wikipedia: Universally Unique Identifier](http://en.wikipedia.org/wiki/Universally_unique_identifier)
|
||||
* [RFC4122: A Universally Unique Identifier (UUID) URN Namespace](http://tools.ietf.org/html/rfc4122)
|
||||
"""
|
||||
scalar UUID
|
||||
|
||||
scalar Upload
|
||||
|
||||
type User {
|
||||
account: Account!
|
||||
createdAt: DateTime!
|
||||
email: String!
|
||||
id: UUID!
|
||||
updatedAt: DateTime!
|
||||
username: String!
|
||||
}
|
||||
|
||||
enum Visibility {
|
||||
FOLLOWER_ONLY
|
||||
MENTION_ONLY
|
||||
PUBLIC
|
||||
UNLISTED
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
// See https://kit.svelte.dev/docs/types#app
|
||||
// for information about these interfaces
|
||||
declare global {
|
||||
namespace App {
|
||||
// interface Error {}
|
||||
// interface Locals {}
|
||||
// interface PageData {}
|
||||
// interface PageState {}
|
||||
// interface Platform {}
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
|
@ -0,0 +1,12 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
<div style="display: contents">%sveltekit.body%</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,15 @@
|
|||
import { HoudiniClient } from '$houdini';
|
||||
|
||||
export default new HoudiniClient({
|
||||
url: `${import.meta.env.VITE_BACKEND_URL ?? ''}/graphql`
|
||||
|
||||
// uncomment this to configure the network call (for things like authentication)
|
||||
// for more information, please visit here: https://www.houdinigraphql.com/guides/authentication
|
||||
// fetchParams({ session }) {
|
||||
// return {
|
||||
// headers: {
|
||||
// Authentication: `Bearer ${session.token}`,
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
});
|
|
@ -0,0 +1,7 @@
|
|||
import { describe, it, expect } from 'vitest';
|
||||
|
||||
describe('sum test', () => {
|
||||
it('adds 1 + 2 to equal 3', () => {
|
||||
expect(1 + 2).toBe(3);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,39 @@
|
|||
<script lang="ts">
|
||||
import type { Snippet } from 'svelte';
|
||||
|
||||
let {
|
||||
children,
|
||||
...rest
|
||||
}:
|
||||
| {
|
||||
children: Snippet;
|
||||
}
|
||||
| any = $props();
|
||||
</script>
|
||||
|
||||
<button {...rest}>
|
||||
{@render children()}
|
||||
</button>
|
||||
|
||||
<style lang="scss">
|
||||
@use '../../styles/colours' as *;
|
||||
|
||||
button {
|
||||
transition: 0.5s;
|
||||
cursor: pointer;
|
||||
|
||||
border: 0;
|
||||
border-radius: 10px;
|
||||
|
||||
background-color: $shade1dark;
|
||||
|
||||
padding: 10px;
|
||||
width: 100px;
|
||||
height: 50px;
|
||||
font-size: 16px;
|
||||
|
||||
&:hover {
|
||||
background-color: $shade2dark;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1 @@
|
|||
// place files you want to import through the `$lib` alias in this folder.
|
|
@ -0,0 +1,11 @@
|
|||
<script lang="ts">
|
||||
import '../styles/root.scss';
|
||||
|
||||
const { children } = $props();
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Kitsune Ⓐ🏴</title>
|
||||
</svelte:head>
|
||||
|
||||
{@render children()}
|
|
@ -0,0 +1 @@
|
|||
export const ssr = false;
|
|
@ -0,0 +1,208 @@
|
|||
<script lang="ts">
|
||||
import { graphql } from '$houdini';
|
||||
import Button from '$lib/components/Button.svelte';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
let registerButtonDisabled = $state(false);
|
||||
|
||||
onMount(() => {
|
||||
// TODO: Authenticated check and redirect to home timeline
|
||||
});
|
||||
|
||||
async function handleRegister(
|
||||
event: SubmitEvent & { currentTarget: EventTarget & HTMLFormElement }
|
||||
) {
|
||||
event.preventDefault();
|
||||
|
||||
const data = new FormData(event.currentTarget);
|
||||
|
||||
const username = data.get('username');
|
||||
const email = data.get('email');
|
||||
const password = data.get('password');
|
||||
const passwordConfirmation = data.get('confirm-password');
|
||||
|
||||
if (!username) {
|
||||
alert('Missing username');
|
||||
return;
|
||||
} else if (!email) {
|
||||
alert('Missing email');
|
||||
return;
|
||||
} else if (!password) {
|
||||
alert('Missing password');
|
||||
return;
|
||||
} else if (!passwordConfirmation || passwordConfirmation !== password) {
|
||||
alert('Password mismatch');
|
||||
return;
|
||||
}
|
||||
|
||||
const register = graphql(`
|
||||
mutation Register($username: String!, $email: String!, $password: String!) {
|
||||
registerUser(username: $username, email: $email, password: $password) {
|
||||
username
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
try {
|
||||
const response = await register.mutate({
|
||||
username: username as string,
|
||||
email: email as string,
|
||||
password: password as string
|
||||
});
|
||||
|
||||
if (response.errors) {
|
||||
alert('Failed to register:\n' + response.errors.map((error) => error.message).concat('\n'));
|
||||
} else {
|
||||
alert('Registered!');
|
||||
}
|
||||
} catch (ex: unknown) {}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="landing-page">
|
||||
<div class="section-left">
|
||||
<div class="section-left-content">
|
||||
<img class="logo" src="/kitsune_full.svg" />
|
||||
|
||||
<h1>Federated microblogging</h1>
|
||||
|
||||
Statistics:
|
||||
|
||||
<ul>
|
||||
<li>1,000,000,000 registered users</li>
|
||||
<li>96,000,000,000 posts</li>
|
||||
<li>50,000,000 connected instances</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section-right">
|
||||
<div class="section-right-content">
|
||||
<form
|
||||
class="register-form"
|
||||
onsubmit={(e) => {
|
||||
registerButtonDisabled = true;
|
||||
handleRegister(e).finally(() => (registerButtonDisabled = false));
|
||||
}}
|
||||
>
|
||||
<input placeholder="Username" type="text" name="username" />
|
||||
<input placeholder="Email" type="email" name="email" />
|
||||
<input placeholder="Password" type="password" name="password" />
|
||||
<input placeholder="Confirm Password" type="password" name="confirm-password" />
|
||||
|
||||
<p>
|
||||
<Button
|
||||
class="register-button"
|
||||
onclick={() => console.log('register')}
|
||||
disabled={registerButtonDisabled}
|
||||
>
|
||||
Register
|
||||
</Button>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
@use '../styles/breakpoints' as *;
|
||||
@use '../styles/colours' as *;
|
||||
@use '../styles/mixins' as *;
|
||||
@use 'sass:map';
|
||||
|
||||
.landing-page {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
.section-right {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: $dark2;
|
||||
|
||||
&-content {
|
||||
border-radius: 0px 30px 30px 0px;
|
||||
background-color: $dark1;
|
||||
padding: 2em;
|
||||
max-width: 50ch;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.section-left {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 65%;
|
||||
}
|
||||
|
||||
.register-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
|
||||
& input {
|
||||
width: 100%;
|
||||
border: none;
|
||||
height: 50px;
|
||||
border-radius: 10px;
|
||||
background-color: $dark2;
|
||||
margin-bottom: 0.75em;
|
||||
margin-top: 0.75em;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
& :global(.register-button) {
|
||||
width: 100%;
|
||||
margin-top: 2em;
|
||||
}
|
||||
}
|
||||
|
||||
h1,
|
||||
ul {
|
||||
color: $text1;
|
||||
}
|
||||
|
||||
@include only-on-mobile {
|
||||
.bottom-section {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.section-left {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.landing-page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.section-right {
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
|
||||
&-content {
|
||||
max-width: 100%;
|
||||
border-radius: 0px;
|
||||
background-color: $dark2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.register-form input {
|
||||
background-color: $dark1;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,9 +1,9 @@
|
|||
// Source: Tailwind <https://tailwindcss.com/docs/screens>
|
||||
|
||||
$breakpoints: (
|
||||
sm: 640px,
|
||||
md: 768px,
|
||||
lg: 1024px,
|
||||
xl: 1280px,
|
||||
xxl: 1536px,
|
||||
sm: 640px,
|
||||
md: 768px,
|
||||
lg: 1024px,
|
||||
xl: 1280px,
|
||||
xxl: 1536px
|
||||
);
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
$dark1: #0f1026;
|
||||
$dark2: #051c30;
|
||||
$dark1: #1c1626;
|
||||
$dark2: #2b233a;
|
||||
$dark3: #042f40;
|
||||
$shade1dark: #53a0c4;
|
||||
$shade1dark: #ff9e55;
|
||||
$shade1light: #afd7fa;
|
||||
$shade2dark: #935d7e;
|
||||
$shade2light: #d68fbc;
|
||||
$text1: #e5d4b5;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
@use 'sass:map';
|
||||
|
||||
@mixin only-on-mobile {
|
||||
@media only screen and (max-width: map.get($breakpoints, md)) {
|
||||
@content;
|
||||
}
|
||||
@media only screen and (max-width: map.get($breakpoints, md)) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,49 +1,50 @@
|
|||
@use 'colours' as *;
|
||||
@use 'fonts' as *;
|
||||
|
||||
* {
|
||||
// font-family: BlockZone;
|
||||
box-sizing: inherit;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
box-sizing: inherit;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
}
|
||||
|
||||
:root {
|
||||
background-color: $dark1;
|
||||
color: white;
|
||||
background-color: $dark1;
|
||||
color: white;
|
||||
|
||||
color-scheme: light dark;
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
color-scheme: light dark;
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
line-height: 1.5em;
|
||||
|
||||
font-synthesis: none;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
font-synthesis: none;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
|
||||
box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
a {
|
||||
color: $shade2light;
|
||||
font-weight: 500;
|
||||
text-decoration: inherit;
|
||||
color: $shade2light;
|
||||
font-weight: 500;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
margin-top: 85px;
|
||||
margin: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 0.666em;
|
||||
height: 0.666em;
|
||||
width: 0.666em;
|
||||
height: 0.666em;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
|
||||
box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: $shade2light;
|
||||
background-color: $shade2light;
|
||||
}
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_2" data-name="Layer 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 434.62 158.92">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: #ff9e55;
|
||||
}
|
||||
|
||||
.cls-1, .cls-2 {
|
||||
stroke-width: 0px;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
fill: #e5d4b5;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="Layer_1-2" data-name="Layer 1">
|
||||
<g>
|
||||
<path class="cls-2" d="M193.84,16.05c.24.28-30.65-11.7-39.07,36.28,0,0-1.42,2.69-5.17,6.72-14.56,5.73-27.13,2.68-27.13,2.68-1.99-3.09-2.45-9.8-2.45-9.8l-11.02-1.22s-3.67-15.92.32-25.94c.01-.02.01-.04.01-.04,1.38-2.23,2.82-4.54,4.3-6.94,15.58-25.25,63.34-21.58,80.21-1.74Z"/>
|
||||
<path class="cls-1" d="M78.44,121.34c-7.75-9.75-12.09-19.69-14.09-25.12,34.98-3.38,57.64-12.63,71.92-21.65-1.73.14-3.47.22-5.22.22-3.92,0-7.05-.36-9.07-.69-14.15,6.81-34.36,12.94-62.86,15.2l-4.38.35,1.12,4.25c.17.65,4.36,16.22,16.66,31.79,11.22,14.21,31.51,30.98,64.72,30.98.61,0,1.3.05,1.92.04l-.21-7.41c-25.02.45-45.39-8.94-60.5-27.96Z"/>
|
||||
<path class="cls-1" d="M96.67,51.54c-.48-2.47-1.15-6.58-1.38-11.36-15.19,23.69-24.11,35.13-32.82,40.29V9.68h-7.35v73.79c-5.24,1.29-11.36,1.37-19.4,1.47-1.45.02-2.96.04-4.54.07C10.52,85.36-.3,104.93,0,123.17c.28,16.5,10,34.09,30.7,34.09.2,0,.4,0,.59,0,10.19-.16,18.11-3.41,23.57-9.64,8.86-10.14,7.81-24.57,7.61-26.68v-32.21c10.28-4.45,19.17-14.37,34.2-37.18ZM49.3,142.81c-4.03,4.58-10.12,6.97-18.12,7.1-16.1.22-23.6-13.3-23.83-26.86-.25-15.05,7.89-30.43,23.95-30.7,1.57-.03,3.07-.05,4.51-.06,7.71-.1,13.78-.18,19.31-1.29v30.13l.02.42c.01.13,1.39,13.03-5.84,21.26Z"/>
|
||||
<g>
|
||||
<path class="cls-1" d="M169.14,102.93c.04,2.69-.29,6.41-.98,11.14-.69,4.73-1.41,10.59-2.16,17.59-.56,5.31-1.18,13.86-1.85,25.64l-9.76.56c.86-5.91,2.02-14.64,3.48-26.2.79-7.48,1.18-14.38,1.18-20.7,0-2.66-.08-4.82-.22-6.51l10.32-1.51ZM173.18,86.38c0,2.17-.71,4.02-2.13,5.55-1.42,1.53-3.22,2.3-5.39,2.3-3.4,0-5.11-1.81-5.11-5.44,0-2.17.71-4,2.13-5.5,1.42-1.5,3.22-2.24,5.39-2.24,3.4,0,5.11,1.78,5.11,5.33Z"/>
|
||||
<path class="cls-1" d="M213.12,147.02l-1.4,7.46c-3.93,2.66-7.97,3.98-12.12,3.98-5.12,0-8.7-1.26-10.72-3.79-2.02-2.52-3.03-6.55-3.03-12.09,0-4.64,1.07-14.64,3.2-30.02-1.98,0-5.03.11-9.14.34l1.18-8.14c3.52.22,6.58.34,9.2.34.22-1.53,1.03-6.86,2.41-15.99l8.42-.9c-.67,3.82-1.55,9.44-2.64,16.89,3.48,0,8.45-.19,14.92-.56l-1.12,8.36c-6.17-.22-11.2-.34-15.09-.34-1.95,12.57-2.92,21.56-2.92,26.99,0,4.26.54,7.18,1.63,8.75,1.08,1.57,2.92,2.36,5.5,2.36,3.74,0,7.65-1.22,11.73-3.65Z"/>
|
||||
<path class="cls-1" d="M259.13,103.6l-2.52,8.13c-3.74-1.38-8.04-2.08-12.9-2.08-7.26,0-10.88,2.43-10.88,7.29,0,1.76.69,3.24,2.08,4.43,1.38,1.2,4.02,2.62,7.91,4.26,9.5,4.08,14.25,9.26,14.25,15.54,0,11.52-7.26,17.28-21.77,17.28-5.87,0-11.3-.5-16.27-1.51l2.58-8.25c4.41,1.65,9.24,2.47,14.47,2.47,8.42,0,12.62-2.41,12.62-7.24,0-3.37-3.37-6.53-10.1-9.48-9.58-4.19-14.36-9.37-14.36-15.54,0-5.35,1.96-9.44,5.89-12.29,3.93-2.84,8.73-4.26,14.42-4.26,6.13,0,11,.41,14.59,1.23Z"/>
|
||||
<path class="cls-1" d="M317.53,102.87c-2.62,20.8-3.93,34.6-3.93,41.4,0,3.93.3,8.15.9,12.68l-9.48,1.4c-.22-3.29-.34-7.65-.34-13.07h-.45c-4.86,9.09-11.56,13.63-20.08,13.63-9.76,0-14.64-5.55-14.64-16.66,0-2.95.42-8.96,1.26-18.01s1.26-15.8,1.26-20.25l9.71-1.12c0,1.61-.58,6.97-1.74,16.07-1.16,9.11-1.74,15.96-1.74,20.56s.79,7.42,2.38,9.12c1.59,1.7,4.09,2.55,7.49,2.55,4.08,0,7.99-2.67,11.75-8.02,3.76-5.35,5.96-11.22,6.59-17.62.9-9.13,1.35-16.31,1.35-21.54l9.71-1.12Z"/>
|
||||
<path class="cls-1" d="M376.33,118.92c0,2.96-.42,8.98-1.26,18.07-.84,9.09-1.26,15.86-1.26,20.31l-9.48.56c0-1.65.54-6.94,1.63-15.88,1.08-8.94,1.63-15.71,1.63-20.31s-.79-7.41-2.38-9.12c-1.59-1.7-4.09-2.55-7.49-2.55-4.08,0-7.99,2.66-11.75,7.99s-5.96,11.21-6.59,17.64c-.82,8.38-1.46,15.6-1.91,21.66l-9.15.56c2.62-19.37,3.93-32.46,3.93-39.27,0-3.93-.3-8.71-.9-14.36l9.48-1.4c.22,3.29.34,7.65.34,13.07h.45c4.86-9.09,11.56-13.63,20.09-13.63,9.76,0,14.64,5.55,14.64,16.66Z"/>
|
||||
<path class="cls-1" d="M434.62,114.6c0,5.05-2.34,8.88-7.01,11.5-5.95,3.37-16.08,5.18-30.41,5.44,0,6.73,1.17,11.62,3.51,14.67,2.34,3.05,6.27,4.57,11.81,4.57s11.33-1.91,17.73-5.72l-1.4,8.3c-5.05,3.63-11.3,5.44-18.74,5.44s-13.25-2.29-16.86-6.87c-3.61-4.58-5.41-10.39-5.41-17.42,0-10.36,3.02-18.45,9.06-24.26,6.04-5.82,13.01-8.72,20.9-8.72,4.79,0,8.79,1.16,12.01,3.48,3.21,2.32,4.82,5.52,4.82,9.59ZM425.7,114.82c0-1.98-.92-3.51-2.75-4.57-1.83-1.07-4.19-1.6-7.07-1.6-4.08,0-7.86,1.35-11.36,4.04-3.5,2.69-5.77,6.83-6.82,12.4,11.48-.22,19.36-1.44,23.62-3.65,2.92-1.5,4.38-3.7,4.38-6.62Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.4 KiB |
Binary file not shown.
After Width: | Height: | Size: 266 KiB |
|
@ -0,0 +1,32 @@
|
|||
import adapter from '@sveltejs/adapter-static';
|
||||
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
||||
|
||||
/** @type {import('@sveltejs/kit').Config} */
|
||||
const config = {
|
||||
compilerOptions: {
|
||||
runes: true
|
||||
},
|
||||
|
||||
// Consult https://kit.svelte.dev/docs/integrations#preprocessors
|
||||
// for more information about preprocessors
|
||||
preprocess: [vitePreprocess()],
|
||||
|
||||
kit: {
|
||||
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
|
||||
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
|
||||
// See https://kit.svelte.dev/docs/adapters for more information about adapters.
|
||||
adapter: adapter({
|
||||
pages: 'build',
|
||||
assets: 'build',
|
||||
fallback: 'index.html',
|
||||
precompress: false,
|
||||
strict: true
|
||||
}),
|
||||
|
||||
alias: {
|
||||
$houdini: './$houdini'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default config;
|
|
@ -1,18 +1,20 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"strict": true,
|
||||
"jsx": "preserve",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"esModuleInterop": true,
|
||||
"lib": ["ESNext", "DOM"],
|
||||
"skipLibCheck": true,
|
||||
"noEmit": true
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
"extends": "./.svelte-kit/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"skipLibCheck": true,
|
||||
"sourceMap": true,
|
||||
"strict": true,
|
||||
"moduleResolution": "bundler",
|
||||
"rootDirs": [".", "./.svelte-kit/types", "./$houdini/types"]
|
||||
}
|
||||
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
|
||||
// except $lib which is handled by https://kit.svelte.dev/docs/configuration#files
|
||||
//
|
||||
// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
|
||||
// from the referenced tsconfig.json - TypeScript does not merge them in
|
||||
}
|
||||
|
|
|
@ -1,32 +1,18 @@
|
|||
import vue from '@vitejs/plugin-vue';
|
||||
|
||||
import path from 'node:path';
|
||||
import { ExternalFluentPlugin } from 'unplugin-fluent-vue/vite';
|
||||
import { sveltekit } from '@sveltejs/kit/vite';
|
||||
import houdini from 'houdini/vite';
|
||||
import { defineConfig } from 'vite';
|
||||
import Icons from 'unplugin-icons/vite';
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
build: {
|
||||
rollupOptions: {
|
||||
output: {
|
||||
manualChunks: {
|
||||
zxcvbnCommon: ['@zxcvbn-ts/language-common'],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
vue(),
|
||||
ExternalFluentPlugin({
|
||||
locales: ['en', 'en-cyberpunk'],
|
||||
checkSyntax: true,
|
||||
|
||||
baseDir: path.resolve('src'),
|
||||
ftlDir: path.resolve('src/locales'),
|
||||
|
||||
getFtlPath(locale) {
|
||||
return path.join('src/locales', `${locale}.ftl`);
|
||||
},
|
||||
}),
|
||||
],
|
||||
plugins: [
|
||||
houdini(),
|
||||
sveltekit(),
|
||||
Icons({
|
||||
autoInstall: true,
|
||||
compiler: 'svelte'
|
||||
})
|
||||
],
|
||||
test: {
|
||||
include: ['src/**/*.{test,spec}.{js,ts}']
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue