diff --git a/go.mod b/go.mod
index eb658de..4b001f6 100644
--- a/go.mod
+++ b/go.mod
@@ -15,6 +15,7 @@ require (
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/charmbracelet/lipgloss v0.9.1 // indirect
github.com/go-logfmt/logfmt v0.6.0 // indirect
+ github.com/goccy/go-json v0.10.2 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
diff --git a/go.sum b/go.sum
index 755022d..8032581 100644
--- a/go.sum
+++ b/go.sum
@@ -16,6 +16,8 @@ github.com/galeone/tfgo v0.0.0-20230715013254-16113111dc99 h1:8Bt1P/zy1gb37L4n8C
github.com/galeone/tfgo v0.0.0-20230715013254-16113111dc99/go.mod h1:3YgYBeIX42t83uP27Bd4bSMxTnQhSbxl0pYSkCDB1tc=
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
+github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
+github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
diff --git a/logic/utils/handler.go b/logic/utils/handler.go
index 6e37a1a..decdef4 100644
--- a/logic/utils/handler.go
+++ b/logic/utils/handler.go
@@ -14,6 +14,7 @@ import (
dbtypes "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types"
"github.com/charmbracelet/log"
+ "github.com/goccy/go-json"
)
func Mul(n1 int, n2 int) int {
@@ -347,6 +348,43 @@ type Context struct {
Db *sql.DB
}
+func (c Context) ToJSON(r *http.Request, dat any) *Error {
+
+ decoder := json.NewDecoder(r.Body)
+
+ err := decoder.Decode(dat)
+ if err != nil {
+ return c.Error500(err)
+ }
+
+ return nil
+}
+
+func (c Context) SendJSON(w http.ResponseWriter, dat any) *Error {
+ w.Header().Add("content-type", "application/json")
+ text, err := json.Marshal(dat)
+ if err != nil {
+ return c.Error500(err)
+ }
+ if _, err = w.Write(text); err != nil {
+ return c.Error500(err)
+ }
+ return nil
+}
+
+func (c Context) SendJSONStatus(w http.ResponseWriter, status int, dat any) *Error {
+ w.Header().Add("content-type", "application/json")
+ w.WriteHeader(status)
+ text, err := json.Marshal(dat)
+ if err != nil {
+ return c.Error500(err)
+ }
+ if _, err = w.Write(text); err != nil {
+ return c.Error500(err)
+ }
+ return nil
+}
+
func (c Context) Error400(err error, message string, w http.ResponseWriter, path string, base string, data AnyMap) *Error {
c.SetReportCaller(true)
c.Logger.Error(message)
@@ -609,6 +647,10 @@ func NewHandler(db *sql.DB) *Handle {
if r.Header.Get("Request-Type") == "htmlfull" {
ans = HTMLFULL
}
+ if r.Header.Get("content-type") == "application/json" {
+ ans = JSON
+ }
+
//TODO JSON
//Login state
@@ -618,6 +660,9 @@ func NewHandler(db *sql.DB) *Handle {
return
}
+ w.Header().Add("Access-Control-Allow-Origin", "*")
+ w.Header().Add("Access-Control-Allow-Headers", "*")
+
if r.Method == "GET" {
x.handleGets(w, r, context)
return
@@ -630,6 +675,9 @@ func NewHandler(db *sql.DB) *Handle {
x.handleDeletes(w, r, context)
return
}
+ if r.Method == "OPTIONS" {
+ return
+ }
panic("TODO handle method: " + r.Method)
})
diff --git a/users.go b/users.go
index 94b38b0..9405b95 100644
--- a/users.go
+++ b/users.go
@@ -4,7 +4,6 @@ import (
"crypto/rand"
"database/sql"
"encoding/hex"
- "fmt"
"io"
"net/http"
"time"
@@ -79,8 +78,39 @@ func usersEndpints(db *sql.DB, handle *Handle) {
handle.GetHTML("/login", AnswerTemplate("login.html", nil, 0))
handle.Post("/login", func(w http.ResponseWriter, r *http.Request, c *Context) *Error {
if c.Mode == JSON {
- fmt.Println("Handle JSON")
- return &Error{Code: 404}
+
+ type UserLogin struct {
+ Email string `json:email`
+ Password string `json:password`
+ }
+
+ var dat UserLogin
+
+ if err := c.ToJSON(r, &dat); err != nil {
+ return err
+ }
+
+
+ /*if (dat["email"] == nil || dat["password"] == nil) {
+ // TODO improve this
+ c.Logger.Warn("Email or password are empty")
+ return c.Error500(nil)
+ }*/
+
+ // TODO Give this to the generateToken function
+ expiration := time.Now().Add(24 * time.Hour)
+ token, login := generateToken(db, dat.Email, dat.Password)
+ if !login {
+ return c.SendJSONStatus(w, http.StatusUnauthorized, "Email or password are incorrect")
+ }
+
+
+ cookie := &http.Cookie{Name: "auth", Value: token, HttpOnly: false, Expires: expiration}
+ http.SetCookie(w, cookie)
+
+ w.Header().Set("Location", "/")
+ w.WriteHeader(http.StatusSeeOther)
+ return nil
}
r.ParseForm()
diff --git a/webpage/.eslintignore b/webpage/.eslintignore
new file mode 100644
index 0000000..3897265
--- /dev/null
+++ b/webpage/.eslintignore
@@ -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
diff --git a/webpage/.eslintrc.cjs b/webpage/.eslintrc.cjs
new file mode 100644
index 0000000..0b75758
--- /dev/null
+++ b/webpage/.eslintrc.cjs
@@ -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'
+ }
+ }
+ ]
+};
diff --git a/webpage/.gitignore b/webpage/.gitignore
new file mode 100644
index 0000000..6635cf5
--- /dev/null
+++ b/webpage/.gitignore
@@ -0,0 +1,10 @@
+.DS_Store
+node_modules
+/build
+/.svelte-kit
+/package
+.env
+.env.*
+!.env.example
+vite.config.js.timestamp-*
+vite.config.ts.timestamp-*
diff --git a/webpage/.npmrc b/webpage/.npmrc
new file mode 100644
index 0000000..b6f27f1
--- /dev/null
+++ b/webpage/.npmrc
@@ -0,0 +1 @@
+engine-strict=true
diff --git a/webpage/.prettierignore b/webpage/.prettierignore
new file mode 100644
index 0000000..cc41cea
--- /dev/null
+++ b/webpage/.prettierignore
@@ -0,0 +1,4 @@
+# Ignore files for PNPM, NPM and YARN
+pnpm-lock.yaml
+package-lock.json
+yarn.lock
diff --git a/webpage/.prettierrc b/webpage/.prettierrc
new file mode 100644
index 0000000..9573023
--- /dev/null
+++ b/webpage/.prettierrc
@@ -0,0 +1,8 @@
+{
+ "useTabs": true,
+ "singleQuote": true,
+ "trailingComma": "none",
+ "printWidth": 100,
+ "plugins": ["prettier-plugin-svelte"],
+ "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
+}
diff --git a/webpage/README.md b/webpage/README.md
new file mode 100644
index 0000000..5ce6766
--- /dev/null
+++ b/webpage/README.md
@@ -0,0 +1,38 @@
+# create-svelte
+
+Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/main/packages/create-svelte).
+
+## Creating a project
+
+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
+```
+
+## Developing
+
+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
+```
+
+## Building
+
+To create a production version of your app:
+
+```bash
+npm run build
+```
+
+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.
diff --git a/webpage/bun.lockb b/webpage/bun.lockb
new file mode 100755
index 0000000..3db0581
Binary files /dev/null and b/webpage/bun.lockb differ
diff --git a/webpage/package.json b/webpage/package.json
new file mode 100644
index 0000000..39ec920
--- /dev/null
+++ b/webpage/package.json
@@ -0,0 +1,34 @@
+{
+ "name": "webpage",
+ "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",
+ "lint": "prettier --check . && eslint .",
+ "format": "prettier --write ."
+ },
+ "devDependencies": {
+ "@sveltejs/adapter-auto": "^3.0.0",
+ "@sveltejs/kit": "^2.0.0",
+ "@sveltejs/vite-plugin-svelte": "^3.0.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",
+ "prettier": "^3.1.1",
+ "prettier-plugin-svelte": "^3.1.2",
+ "sass": "^1.71.1",
+ "svelte": "^5.0.0-next.1",
+ "svelte-check": "^3.6.0",
+ "tslib": "^2.4.1",
+ "typescript": "^5.0.0",
+ "vite": "^5.0.3"
+ },
+ "type": "module"
+}
diff --git a/webpage/src/NavBar.svelte b/webpage/src/NavBar.svelte
new file mode 100644
index 0000000..6c87ba6
--- /dev/null
+++ b/webpage/src/NavBar.svelte
@@ -0,0 +1,60 @@
+
+
+
+
+
diff --git a/webpage/src/app.d.ts b/webpage/src/app.d.ts
new file mode 100644
index 0000000..743f07b
--- /dev/null
+++ b/webpage/src/app.d.ts
@@ -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 {};
diff --git a/webpage/src/app.html b/webpage/src/app.html
new file mode 100644
index 0000000..77a5ff5
--- /dev/null
+++ b/webpage/src/app.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ %sveltekit.head%
+
+
+ %sveltekit.body%
+
+
diff --git a/webpage/src/lib/index.ts b/webpage/src/lib/index.ts
new file mode 100644
index 0000000..856f2b6
--- /dev/null
+++ b/webpage/src/lib/index.ts
@@ -0,0 +1 @@
+// place files you want to import through the `$lib` alias in this folder.
diff --git a/webpage/src/lib/requests.svelte.ts b/webpage/src/lib/requests.svelte.ts
new file mode 100644
index 0000000..13738d4
--- /dev/null
+++ b/webpage/src/lib/requests.svelte.ts
@@ -0,0 +1,42 @@
+import { userStore } from 'routes/UserStore.svelte';
+
+const API = "http://localhost:8000";
+
+export async function get(url: string) {
+ const headers = new Headers();
+ //headers.append('content-type', 'application/json');
+ if (userStore.user) {
+ headers.append('token', userStore.user.token);
+ }
+
+ let r = await fetch(`${API}/${url}`, {
+ method: 'GET',
+ headers: headers,
+ });
+
+ if (r.status !== 200) {
+ throw r;
+ }
+
+ return r.json();
+}
+
+export async function post(url: string, body: any) {
+ const headers = new Headers();
+ headers.append('content-type', 'application/json');
+ if (userStore.user) {
+ headers.append('token', userStore.user.token);
+ }
+
+ let r = await fetch(`${API}/${url}`, {
+ method: 'POST',
+ headers: headers,
+ body: JSON.stringify(body),
+ });
+
+ if (r.status !== 200) {
+ throw r;
+ }
+
+ return r.json();
+}
diff --git a/webpage/src/routes/+error.svelte b/webpage/src/routes/+error.svelte
new file mode 100644
index 0000000..b08aa0e
--- /dev/null
+++ b/webpage/src/routes/+error.svelte
@@ -0,0 +1,17 @@
+
+
+{#if $page.error}
+ {#if $page.status == 404}
+
+ {:else}
+
+ {$page.status}
+
+
+ {$page.error.message}
+
+ {/if}
+{/if}
diff --git a/webpage/src/routes/+layout.svelte b/webpage/src/routes/+layout.svelte
new file mode 100644
index 0000000..9d2737a
--- /dev/null
+++ b/webpage/src/routes/+layout.svelte
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/webpage/src/routes/+layout.ts b/webpage/src/routes/+layout.ts
new file mode 100644
index 0000000..2dedff1
--- /dev/null
+++ b/webpage/src/routes/+layout.ts
@@ -0,0 +1,4 @@
+export const prerender = true;
+export const ssr = false;
+export const csr = true;
+//export const trailingSlash = '';
diff --git a/webpage/src/routes/+page.svelte b/webpage/src/routes/+page.svelte
new file mode 100644
index 0000000..9845c90
--- /dev/null
+++ b/webpage/src/routes/+page.svelte
@@ -0,0 +1 @@
+Main Web Page
diff --git a/webpage/src/routes/Page404.svelte b/webpage/src/routes/Page404.svelte
new file mode 100644
index 0000000..e45f516
--- /dev/null
+++ b/webpage/src/routes/Page404.svelte
@@ -0,0 +1,54 @@
+
+
+
+
+
+ 404
+
+ {#if message}
+
+ {message}
+
+ {#if goBackLink}
+
+ {/if}
+ {:else}
+
+ Page Not found
+
+
+ The page you were looking for does not exist
+
+ {/if}
+
+
+
+
diff --git a/webpage/src/routes/UserStore.svelte.ts b/webpage/src/routes/UserStore.svelte.ts
new file mode 100644
index 0000000..e882482
--- /dev/null
+++ b/webpage/src/routes/UserStore.svelte.ts
@@ -0,0 +1,55 @@
+import { goto } from "$app/navigation";
+
+type User = {
+ token: string,
+ id: string,
+ user_type: number,
+ username: string,
+ email: string,
+};
+
+export function createUserStore() {
+ let user = $state(undefined);
+
+ function getValue() {
+ if (user == undefined) {
+ let storage = localStorage.getItem('user');
+ if (storage) {
+ try {
+ user = JSON.parse(storage);
+ } catch {
+ user = undefined;
+ }
+ }
+ }
+ return user;
+ }
+
+ return {
+ get user() {
+ return getValue();
+ },
+ set user(value: User | undefined) {
+ if (value) {
+ localStorage.setItem('user', JSON.stringify(value));
+ } else {
+ localStorage.removeItem('user');
+ }
+ user = value;
+ },
+ checkUser(pathOnFail: string, level?: number) {
+ if (user && user.level > (level ?? 2) ) {
+ goto(pathOnFail);
+ return true;
+ }
+
+ return false;
+ },
+ isLogin() {
+ if (getValue()) return true;
+ return false;
+ }
+ }
+}
+
+export const userStore = createUserStore();
diff --git a/webpage/src/routes/login/+page.svelte b/webpage/src/routes/login/+page.svelte
new file mode 100644
index 0000000..41240a4
--- /dev/null
+++ b/webpage/src/routes/login/+page.svelte
@@ -0,0 +1,83 @@
+
+
+
+ Login
+
+
+
+
+
diff --git a/webpage/src/routes/logout/+page.svelte b/webpage/src/routes/logout/+page.svelte
new file mode 100644
index 0000000..35bb995
--- /dev/null
+++ b/webpage/src/routes/logout/+page.svelte
@@ -0,0 +1,10 @@
+
diff --git a/webpage/src/styles/app.css b/webpage/src/styles/app.css
new file mode 100644
index 0000000..50800a7
--- /dev/null
+++ b/webpage/src/styles/app.css
@@ -0,0 +1,88 @@
+*{box-sizing: border-box;font-family: 'Roboto', sans-serif;}
+
+:root {
+ --nav-bar-size: 54px;
+ --white: #ffffff;
+ --grey: #dbdcde;
+ --light-grey: #fafafa;
+ --main: #fca311;
+ --sec: #14213d;
+ --black: #000000;
+ --red: 212, 38, 38;
+ --green: 92, 199, 30;
+}
+
+body {
+ margin: 0px;
+}
+
+.button,
+button {
+ border-radius: 10px;
+ text-align: center;
+ padding: 3px 6px;
+ border: none;
+ box-shadow: 0 2px 8px 1px #66666655;
+ background: var(--main);
+ color: var(--black);
+
+ &.padded {
+ padding: 10px;
+ }
+
+ &.danger {
+ background: rgb(var(--red));
+ color: white;
+ font-weight: bold;
+ }
+}
+
+.flex {
+ display: flex;
+}
+
+.justify-center {
+ justify-content: center;
+}
+
+.justify-start {
+ justify-content: start;
+}
+
+.justify-end {
+ justify-content: end;
+}
+
+.align-center {
+ align-items: center;
+}
+
+.grow-1 {
+ flex-grow: 1;
+}
+
+.w100 {
+ width: 100%;
+ display: block;
+}
+
+.text-center {
+ text-align: center;
+}
+
+.simple-link {
+ color: var(--sec);
+ text-decoration: none;
+}
+
+.bold {
+ font-weight: bold;
+}
+
+.bigger {
+ font-size: 1.1rem;
+}
+
+.danger {
+ color: red;
+}
diff --git a/webpage/src/styles/fonts.css b/webpage/src/styles/fonts.css
new file mode 100644
index 0000000..57e7936
--- /dev/null
+++ b/webpage/src/styles/fonts.css
@@ -0,0 +1,8 @@
+@font-face {
+ font-family: MedievalSharp;
+ src: url(/MedievalSharp-Regular.ttf);
+}
+
+.font-medieval {
+ font-family: MedievalSharp, cursive;
+}
diff --git a/webpage/src/styles/forms.css b/webpage/src/styles/forms.css
new file mode 100644
index 0000000..b75209d
--- /dev/null
+++ b/webpage/src/styles/forms.css
@@ -0,0 +1,147 @@
+/* forms */
+
+a {
+ cursor: pointer;
+}
+
+.card form {
+ padding: 0;
+ border-radius: none;
+ box-shadow: none;
+}
+
+form {
+ padding: 30px;
+ margin: 20px 0;
+ border-radius: 10px;
+ box-shadow: 2px 5px 8px 2px #66666655;
+
+ label,
+ fieldset legend {
+ display: block;
+ padding-bottom: 5px;
+ font-size: 1.2rem;
+ }
+
+ input {
+ border: none;
+ box-shadow: 0 2px 5px 1px #66666655;
+ border-radius: 5px;
+ padding: 10px;
+ width: 100%;
+ }
+
+ input:invalid:focus,
+ &.submitted input:invalid {
+ box-shadow: 0 2px 5px 1px rgba(var(--red), 0.2);
+ }
+
+ &.submitted input:valid {
+ box-shadow: 0 2px 5px 1px rgba(var(--green), 0.2);
+ }
+
+ & .spacer {
+ padding-bottom: 10px;
+ }
+
+ fieldset {
+ padding-bottom: 15px;
+ border: none;
+
+ .form-msg {
+ font-size: 0.9rem;
+ }
+
+ .error {
+ color: rgb(var(--red))
+ }
+ }
+
+ button {
+ font-size: 1.2rem;
+ margin-left: 50%;
+ width: 50%;
+ transform: translateX(-50%);
+ padding: 10px;
+ }
+
+ .input-radial {
+ label {
+ display: inline;
+ font-size: 1rem;
+ }
+
+ input[type="radio"] {
+ width: auto;
+ box-shadow: none;
+ }
+ }
+
+ /* Upload files */
+ fieldset.file-upload {
+ input[type="file"] {
+ height: 1px;
+ width: 1px;
+ padding: 0;
+ box-shadow: none;
+ }
+
+ .icon-holder {
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ width: 100%;
+ font-size: 1rem;
+
+ .icon {
+ height: 150px;
+ width: 150px;
+ padding: 20px;
+ border-radius: 10px;
+ background: none;
+ transform: none;
+ margin: 0;
+ font-size: 1rem;
+ transition: all 1s;
+
+ &.adapt {
+ width: auto;
+ height: auto;
+ max-width: 80%;
+ max-height: 80%;
+ min-height: 150px;
+ min-width: 150px;
+ padding: 20px;
+ }
+
+ img {
+ display: block;
+ width: 100%;
+ height: 80%;
+ object-fit: contain;
+ text-align: center;
+ transition: all 1s;
+ }
+
+ span {
+ display: block;
+ width: 100%;
+ padding-top: 10px;
+ text-align: center;
+ }
+ }
+ }
+
+ }
+
+ fieldset.file-upload:has(input[type="file"]:invalid:focus) .icon,
+ &.submitted fieldset.file-upload:has(input[type="file"]:invalid:focus) .icon {
+ box-shadow: 0 2px 5px 1px rgba(var(--red), 0.2);
+ }
+
+ &.submitted fieldset.file-upload:has(input[type="file"]:valid:focus) .icon {
+ box-shadow: 0 2px 5px 1px rgba(var(--green), 0.2);
+ }
+
+}
diff --git a/webpage/static/favicon.png b/webpage/static/favicon.png
new file mode 100644
index 0000000..825b9e6
Binary files /dev/null and b/webpage/static/favicon.png differ
diff --git a/webpage/svelte.config.js b/webpage/svelte.config.js
new file mode 100644
index 0000000..d94ae00
--- /dev/null
+++ b/webpage/svelte.config.js
@@ -0,0 +1,22 @@
+import adapter from '@sveltejs/adapter-auto';
+import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
+
+/** @type {import('@sveltejs/kit').Config} */
+const config = {
+ // 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(),
+ alias: {
+ src: "src",
+ routes: "src/routes",
+ }
+ }
+};
+
+export default config;
diff --git a/webpage/tsconfig.json b/webpage/tsconfig.json
new file mode 100644
index 0000000..82081ab
--- /dev/null
+++ b/webpage/tsconfig.json
@@ -0,0 +1,18 @@
+{
+ "extends": "./.svelte-kit/tsconfig.json",
+ "compilerOptions": {
+ "allowJs": true,
+ "checkJs": true,
+ "esModuleInterop": true,
+ "forceConsistentCasingInFileNames": true,
+ "resolveJsonModule": true,
+ "skipLibCheck": true,
+ "sourceMap": true,
+ "strict": true,
+ "moduleResolution": "bundler"
+ }
+ // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
+ //
+ // 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
+}
diff --git a/webpage/vite.config.ts b/webpage/vite.config.ts
new file mode 100644
index 0000000..bbf8c7d
--- /dev/null
+++ b/webpage/vite.config.ts
@@ -0,0 +1,6 @@
+import { sveltekit } from '@sveltejs/kit/vite';
+import { defineConfig } from 'vite';
+
+export default defineConfig({
+ plugins: [sveltekit()]
+});