This commit is contained in:
Fernando Araoz 2025-01-26 15:00:34 -05:00
commit c78e96994d
17 changed files with 331 additions and 0 deletions

1
.env Normal file
View File

@ -0,0 +1 @@
VITE_BACKEND_URL=http://localhost:8000/api

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
node_modules
dist

13
README.md Normal file
View File

@ -0,0 +1,13 @@
# Reezer
Yet another rewrite of deemix, this time with:
- Rust in the backend
- Rocket.rs as server
- Swagger API docs
- Solidjs in the frontend
- SPA mode
- Bun
- UnoCSS
- Docker

BIN
bun.lockb Executable file

Binary file not shown.

70
eslint.config.js Normal file
View File

@ -0,0 +1,70 @@
import globals from "globals"
import pluginJs from "@eslint/js"
import tseslint from "typescript-eslint"
import solid from "eslint-plugin-solid/configs/typescript"
/** @type {import('eslint').Linter.Config[]} */
export default [
{ files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"] },
{ languageOptions: { globals: globals.browser } },
pluginJs.configs.recommended,
...tseslint.configs.recommended,
solid,
{
rules: {
"indent": ["error", "tab"],
"brace-style": ["error", "allman"],
"no-tabs": "off",
"quotes": ["error", "double"],
"semi": ["error", "never"],
"semi-spacing": ["error", { "before": false, "after": true }],
"no-multiple-empty-lines": ["error", { "max": 1, "maxEOF": 1 }],
// migrated
"prefer-const": "error",
"no-const-assign": "error",
"no-var": "error",
"array-callback-return": "error",
"prefer-template": "error",
"template-curly-spacing": "error",
"no-useless-escape": "error",
"wrap-iife": "error",
"no-loop-func": "error",
"default-param-last": "error",
"space-before-function-paren": ["error", "never"],
"space-before-blocks": "error",
"no-param-reassign": "error",
"function-paren-newline": "error",
"comma-dangle": ["error", "always-multiline"],
"arrow-spacing": "error",
"arrow-parens": "error",
"arrow-body-style": "error",
"no-confusing-arrow": "error",
"implicit-arrow-linebreak": "error",
"no-duplicate-imports": "error",
"object-curly-newline": "error",
"dot-notation": "error",
"one-var": ["error", "never"],
"no-multi-assign": "error",
"no-plusplus": "error",
"operator-linebreak": "error",
"eqeqeq": "error",
"no-case-declarations": "error",
"no-nested-ternary": "error",
"no-unneeded-ternary": "error",
"no-mixed-operators": "error",
"nonblock-statement-body-position": "error",
"keyword-spacing": "error",
"space-infix-ops": "error",
"eol-last": "error",
"newline-per-chained-call": "error",
"no-whitespace-before-property": "error",
"space-in-parens": "error",
"array-bracket-spacing": "error",
"key-spacing": "error",
"no-trailing-spaces": "error",
"comma-style": "error",
"radix": "error",
"no-new-wrappers": "error",
},
},
]

39
index.html Normal file
View File

@ -0,0 +1,39 @@
<!DOCTYPE html>
<html lang="en">
<head>
<style>
:root {
--bg: #181115;
--on-bg: #eddfe4;
--root-color: #F9A8D4;
--primary: #fbb1d8;
--on-primary: #511d3e;
--outline: #9c8d93;
--on-surface-variant: #d3c2c9;
}
html {
font-family: "Atkinson Hyperlegible", sans-serif;
}
body {
background-color: var(--bg);
color: var(--on-bg);
}
</style>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<link rel="shortcut icon" type="image/ico" href="/src/assets/favicon.ico" />
<title>Solid App</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Atkinson+Hyperlegible:ital,wght@0,400;0,700;1,400;1,700&display=swap" rel="stylesheet">
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script src="/src/index.tsx" type="module"></script>
</body>
</html>

36
package.json Normal file
View File

@ -0,0 +1,36 @@
{
"name": "vite-template-solid",
"version": "0.0.0",
"description": "",
"type": "module",
"scripts": {
"start": "vite",
"dev": "vite",
"lint": "eslint . --fix",
"build": "vite build",
"serve": "vite preview"
},
"license": "MIT",
"devDependencies": {
"@eslint/js": "^9.17.0",
"@types/bun": "latest",
"@typescript-eslint/eslint-plugin": "^8.19.0",
"@unocss/preset-wind": "^0.65.3",
"eslint": "^9.17.0",
"eslint-plugin-solid": "^0.14.5",
"globals": "^15.14.0",
"typescript": "^5.7.2",
"typescript-eslint": "^8.19.0",
"unocss": "^0.65.3",
"vite": "^6.0.0",
"vite-plugin-solid": "^2.11.0"
},
"dependencies": {
"@solidjs/router": "^0.15.2",
"@tanstack/solid-query": "^5.62.10",
"@unocss/reset": "^0.65.3",
"add": "^2.0.6",
"solid-js": "^1.9.3"
},
"module": "index.ts"
}

BIN
src/assets/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

18
src/components/input.tsx Normal file
View File

@ -0,0 +1,18 @@
export function Input(props: {
id?: string,
name?: string,
type?: string,
placeholder: string,
})
{
return (
<input
class="bg-c-bg text-c-on-bg border-2 border-c-outline rounded focus:border-c-primary p-2 inline-block w-full"
style={{ "outline": "none" }}
placeholder={props.placeholder}
id={props.id}
name={props.name}
type={props.type}
/>
)
}

27
src/index.tsx Normal file
View File

@ -0,0 +1,27 @@
/* @refresh reload */
import { render } from "solid-js/web"
import { Route, HashRouter } from "@solidjs/router"
import { QueryClientProvider } from "@tanstack/solid-query"
import { query_client } from "./utils/query"
import "virtual:uno.css"
import "@unocss/reset/tailwind.css"
import { IndexPage } from "./pages"
import { LoginPage } from "./pages/login"
const root = document.getElementById("root")
if (import.meta.env.DEV && !(root instanceof HTMLElement))
{
throw new Error("Root element not found. Did you forget to add it to your index.html? Or maybe the id attribute got misspelled?")
}
render(() => (
<QueryClientProvider client={query_client}>
<HashRouter>
<Route path="/" component={IndexPage} />
<Route path="/login" component={LoginPage} />
</HashRouter>
</QueryClientProvider>
), root!)

8
src/pages/index.tsx Normal file
View File

@ -0,0 +1,8 @@
export function IndexPage()
{
return (
<div>
:D (happy)
</div>
)
}

44
src/pages/login.tsx Normal file
View File

@ -0,0 +1,44 @@
import { Input } from "../components/input"
import { fetch_api } from "../utils/query"
export function LoginPage()
{
async function onSubmit(ev: SubmitEvent)
{
fetch_api("/login", {
method: "post",
})
ev.preventDefault()
console.log("loggin :D (submit)")
}
return (
<div>
<h1 class="font-bold">
Login to Reezer
</h1>
<form class="text-white" onSubmit={onSubmit}>
<div class="px-4">
<label for="login-username">Username:</label>
<br />
<Input id="login-username" name="username" type="text"
placeholder="Username"
/>
</div>
<div class="px-4">
<label for="login-password">Password:</label>
<br />
<Input id="login-password"
name="username"
type="password"
placeholder="Password"
/>
</div>
<button type="submit">
Log in
</button>
</form>
</div>
)
}

21
src/utils/query.ts Normal file
View File

@ -0,0 +1,21 @@
import { QueryClient } from "@tanstack/solid-query"
const backend_url = import.meta.env.VITE_BACKEND_URL
export async function fetch_api(url: string, options?: RequestInit)
{
const response = await fetch(`${backend_url}${url}`, {
credentials: "include",
...options,
})
if (!response.ok) throw new Error("API error")
return response.json()
}
export const query_client = new QueryClient({
defaultOptions: {
queries: {
queryFn: ({ queryKey }) => fetch_api(queryKey[0]),
},
},
})

1
src/utils/types.ts Normal file
View File

@ -0,0 +1 @@
export type Result<Result, Error> = [Result | null, Error | null];

15
tsconfig.json Normal file
View File

@ -0,0 +1,15 @@
{
"compilerOptions": {
"strict": true,
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"jsx": "preserve",
"jsxImportSource": "solid-js",
"types": ["vite/client"],
"noEmit": true,
"isolatedModules": true
}
}

20
uno.config.ts Normal file
View File

@ -0,0 +1,20 @@
import presetWind from "@unocss/preset-wind"
import { defineConfig } from "unocss"
export default defineConfig({
// ...UnoCSS options
presets: [
presetWind(),
],
theme: {
colors: {
"c-bg": "var(--bg)",
"c-on-bg": "var(--on-bg)",
"c-root-color": "var(--root-color)",
"c-primary": "var(--primary)",
"c-on-primary": "var(--on-primary)",
"c-outline": "var(--outline)",
"c-on-surface-variant": "var(--on-surface-variant)",
},
},
})

16
vite.config.ts Normal file
View File

@ -0,0 +1,16 @@
import UnoCSS from "unocss/vite"
import { defineConfig } from "vite"
import solidPlugin from "vite-plugin-solid"
export default defineConfig({
plugins: [
UnoCSS(),
solidPlugin(),
],
server: {
port: 3000,
},
build: {
target: "esnext",
},
})