first commit

This commit is contained in:
ngn 2023-04-16 20:12:24 +03:00
commit 15d5df3227
27 changed files with 27478 additions and 0 deletions

13
.editorconfig Normal file
View File

@ -0,0 +1,13 @@
# editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false

94
.gitignore vendored Normal file
View File

@ -0,0 +1,94 @@
# Created by .ignore support plugin (hsz.mobi)
### Node template
# Logs
/logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# parcel-bundler cache (https://parceljs.org/)
.cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# Nuxt generate
dist
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless
# IDE / Editor
.idea
# Service worker
sw.*
# macOS
.DS_Store
# Vim swap files
*.swp
# db file
db.json
pass

12
README.md Normal file
View File

@ -0,0 +1,12 @@
# My Website - [ngn13.fun](https://ngn13.fun)
This repo contains the source code of my personal website.
It's written NuxtJS and supports full SSR.
## Setup
```
git clone https://github.com/ngn13/my-website.git
cd my-website && npm i
echo "password" > pass
npm run build
npm run start
```

78
api/db.js Normal file
View File

@ -0,0 +1,78 @@
const fs = require("fs");
class Database {
constructor() {
this.path = "db.json";
this.json = {};
this.read();
}
write() {
fs.writeFileSync(this.path, JSON.stringify(this.json));
}
read() {
try {
const data = fs.readFileSync(this.path, "utf8");
this.json = JSON.parse(data);
} catch (error) {
return;
}
}
find_all(key, check, ...args) {
try {
const ret = [];
for (const d of this.json[key]) {
if (check(d, ...args)) {
ret.push(d);
}
}
return ret;
} catch (error) {
return false;
}
}
find(key, check, ...args) {
try {
for (const d of this.json[key]) {
if (check(d, ...args)) {
return d;
}
}
return false;
} catch (error) {
return false;
}
}
get(key) {
const res = this.json[key]
if(res===undefined)
return []
return res
}
push(key, data) {
try {
this.json[key].push(data);
} catch (error) {
this.json[key] = [];
this.json[key].push(data);
}
this.write();
}
pop(key, data) {
try {
const indx = this.json[key].indexOf(data);
this.json[key].splice(indx, 1);
} catch (error) {
return;
}
this.write();
}
}
module.exports = Database;

136
api/index.js Normal file
View File

@ -0,0 +1,136 @@
const express = require("express");
const fs = require("fs");
const Database = require("./db");
const app = express();
const db = new Database();
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
function gimmeToken() {
var result = ""
var characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
var charactersLength = characters.length
for ( var i = 0; i < 32; i++ ) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
let TOKEN = gimmeToken();
const PASS = fs.readFileSync("pass", "utf-8")
/*
* error: 0 -> no error
* error: 1 -> parameter error
* error: 2 -> auth error
*
*/
// PATH: /api/login
// METHOD: GET
// PARAMETERS: pass
app.get("/login", (req,res)=>{
let pass = req.query.pass;
if (pass === undefined)
return res.json({error: 1})
if (pass !== PASS)
return res.json({error: 2})
res.json({error: 0, token:TOKEN})
})
// PATH: /api/logout
// METHOD: GET
// PARAMETERS: token
app.get("/logout", (req,res)=>{
let token = req.query.token;
if (token === undefined)
return res.json({error: 1})
if (token !== TOKEN)
return res.json({error: 2})
TOKEN = gimmeToken()
res.json({error: 0})
})
// PATH: /api/add_project
// METHOD: GET
// PARAMETERS: token, name, desc, url
app.get("/add_project", (req, res) => {
let token = req.query.token;
let name = req.query.name;
let desc = req.query.desc;
let url = req.query.url;
if (
token === undefined ||
name === undefined ||
desc === undefined ||
url === undefined
)
return res.json({error: 1})
if (token !== TOKEN)
return res.json({error: 2})
db.push("projects", {"name":name, "desc":desc, "url":url})
res.json({error: 0})
});
// PATH: /api/add_resource
// METHOD: GET
// PARAMETERS: token, name, tags, url
app.get("/add_resource", (req, res) => {
let token = req.query.token;
let name = req.query.name;
let tags = req.query.tags;
let url = req.query.url;
if (
token === undefined ||
name === undefined ||
tags === undefined ||
url === undefined
)
return res.json({error: 1})
if (token !== TOKEN)
return res.json({error: 2})
db.push("resources", {"name":name, "tags":tags.split(","), "url":url})
res.json({error: 0})
});
// PATH: /api/get_projects
// METHOD: GET
// PARAMETERS: NONE
app.get("/get_projects", (req, res) => {
let projects = db.get("projects")
res.json({error: 0, projects:projects})
});
// PATH: /api/get_resources
// METHOD: GET
// PARAMETERS: NONE
app.get("/get_resources", (req, res) => {
let resources = db.get("resources")
res.json({error: 0, resources:resources})
});
// PATH: /api/ping
// METHOD: GET
// PARAMETERS: NONE
app.get("/ping", (req, res) => {
res.send({ error: 0 });
});
export default {
path: "/api",
handler: app,
};

29
components/Button.vue Normal file
View File

@ -0,0 +1,29 @@
<template>
<button @click="click"><slot></slot></button>
</template>
<script>
export default {
props: ["click"]
}
</script>
<style scoped>
button {
text-align: center;
width: 540px;
font-size: 25px;
padding: 20px;
border-radius: 20px;
background: var(--dark-two);
border: none;
color: white;
outline: none;
cursor: pointer;
transition: .4s;
}
button:hover {
box-shadow: var(--def-shadow);
}
</style>

56
components/Card.vue Normal file
View File

@ -0,0 +1,56 @@
<template>
<div>
<slot></slot>
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
div {
box-shadow: var(--def-shadow);
background: var(--dark-two);
width: 100%;
height: auto;
padding: 50px;
color: white;
}
h1 {
text-shadow: 3px 4px 7px rgba(81, 67, 21, 0.8);
font-size: 50px;
margin-bottom: 30px;
text-decoration: underline;
}
i {
animation-name: colorAnimation;
animation-duration: 10s;
animation-iteration-count: infinite;
}
a:hover {
font-weight: 900;
}
i {
font-size: 30px;
margin-top: 3px;
}
h2 {
font-size: 40px;
line-height: 60px;
}
a {
font-size: 40px;
color: white;
line-height: 60px;
text-decoration: none;
}
</style>

31
components/Header.vue Normal file
View File

@ -0,0 +1,31 @@
<template>
<div class="header">
<h1>
<slot></slot>
</h1>
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
div {
background: linear-gradient(rgba(3, 3, 3, 0.706), rgba(22, 22, 22, 0.808)), url("https://www.sketchappsources.com/resources/source-image/tv-glitch-sureshmurali29.png");
width: 100%;
height: 100%;
}
h1 {
font-weight: 900;
font-size: 7.5vw;
padding: 150px;
text-align: center;
color: white;
text-shadow: 3px 4px 7px rgba(81, 67, 21, 0.8);
text-size-adjust: 80%;
}
</style>

27
components/Input.vue Normal file
View File

@ -0,0 +1,27 @@
<template>
<input v-on:keyup="keyup" :placeholder="placeholder" :type="type">
</template>
<script>
export default {
props:["keyup", "placeholder", "type"]
}
</script>
<style scoped>
input {
width: 500px;
font-size: 25px;
padding: 20px;
border-radius: 20px;
background: var(--dark-two);
border: none;
color: white;
outline: none;
transition: .4s;
}
input:focus {
box-shadow: var(--def-shadow);
}
</style>

41
components/Logout.vue Normal file
View File

@ -0,0 +1,41 @@
<template>
<div>
<h1>Currently logged in</h1>
<Button :click="click">Logout</Button>
</div>
</template>
<script>
import axios from 'axios';
import Button from './Button.vue';
export default {
methods: {
async click(e) {
await axios.get(`/api/logout?token=${localStorage.getItem("token")}`)
localStorage.clear()
location.reload()
}
},
}
</script>
<style scoped>
h1{
color: var(--white);
font-size: 50px;
margin-bottom: 20px;
text-align: center;
}
div{
background-color: var(--dark-three);
padding: 50px;
margin-top: 50px;
display: flex;
flex-direction: column;
gap: 20px;
align-items: center;
justify-content: center;
}
</style>

53
components/Navbar.vue Normal file
View File

@ -0,0 +1,53 @@
<template>
<nav>
<div>
<h3>[ngn]</h3>
</div>
<div>
<NavbarLink :out="false" url="/">Home</NavbarLink>
<NavbarLink :out="false" url="/projects">Projects</NavbarLink>
<NavbarLink :out="false" url="/resources">Resources</NavbarLink>
<!--<NavbarLink :out="false" url="/stats">Stats</NavbarLink>-->
<NavbarLink :out="true" url="http://github.com/ngn13/my-website">Source</NavbarLink>
</div>
</nav>
</template>
<script>
import NavbarLink from "./NavbarLink.vue";
export default {}
</script>
<style scoped>
nav {
background: var(--dark-two);
padding: 25px 35px 30px 35px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
border-bottom: solid 3px black;
animation-name: borderAnimation;
animation-duration: 10s;
animation-iteration-count: infinite;
box-shadow: var(--def-shadow);
}
div {
display: flex;
overflow: hidden;
align-items: center;
justify-content: center;
gap: 5px;
}
h3 {
font-weight: 900;
font-size: 30px;
color: red;
animation-name: colorAnimation;
animation-iteration-count: infinite;
animation-duration: 10s;
}
</style>

60
components/NavbarLink.vue Normal file
View File

@ -0,0 +1,60 @@
<template>
<div>
<nuxt-link v-if="!out" :class="cname" id="link" :to="url">
<slot></slot>
</nuxt-link>
<a v-if="out" :class="cname" id="link" :href="url">
<slot></slot>
</a>
</div>
</template>
<script>
export default {
props: ["url", "out"],
data() {
return {
cname: "notcurrent"
}
},
mounted(){
let url = window.location.pathname
if(url===this.url){
this.cname = "current"
}
}
}
</script>
<style scoped>
.notcurrent {
margin-left: 20px;
font-weight: 700;
font-size: 25px;
text-decoration: none;
color: white;
cursor: pointer;
}
.notcurrent:hover {
text-decoration: underline;
animation-name: underlineAnimation;
animation-duration: 5s;
animation-iteration-count: infinite;
text-shadow: 3px 4px 7px rgba(81, 67, 21, 0.8);
}
.current{
margin-left: 20px;
font-weight: 700;
font-size: 25px;
text-decoration: none;
color: white;
cursor: pointer;
text-decoration: underline;
animation-name: underlineAnimation;
animation-duration: 10s;
animation-iteration-count: infinite;
text-shadow: 3px 4px 7px rgba(81, 67, 21, 0.8);
}
</style>

51
components/NewProject.vue Normal file
View File

@ -0,0 +1,51 @@
<template>
<div>
<h1>Add Project</h1>
<Input :keyup="function() { }" id="name" placeholder="Project Name" type="text"/>
<Input :keyup="function() { }" id="desc" placeholder="Project Desc" type="text"/>
<Input :keyup="function() { }" id="url" placeholder="Project URL" type="text"/>
<Button :click="click">Post</Button>
</div>
</template>
<script>
import axios from 'axios';
import Input from './Input.vue';
import Button from './Button.vue';
export default {
methods: {
async click(e) {
const name = document.getElementById("name").value
const desc = document.getElementById("desc").value
const url = document.getElementById("url").value
const token = localStorage.getItem("token")
const res = await axios.get(`/api/add_project?token=${token}&name=${name}&desc=${desc}&url=${url}`)
if(res.data["error"]!==0)
return alert("Error!")
alert("Project added!")
location.reload()
}
},
}
</script>
<style scoped>
h1{
color: var(--white);
font-size: 50px;
margin-bottom: 20px;
text-align: center;
}
div{
background-color: var(--dark-three);
padding: 50px;
margin-top: 50px;
display: flex;
flex-direction: column;
gap: 20px;
align-items: center;
justify-content: center;
}
</style>

View File

@ -0,0 +1,51 @@
<template>
<div>
<h1>Add Resource</h1>
<Input :keyup="function(){}" id="name" placeholder="Resource Name" type="text"/>
<Input :keyup="function(){}" id="tags" placeholder="Resource Tags (comma seperated)" type="text"/>
<Input :keyup="function(){}" id="url" placeholder="Resource URL" type="text"/>
<Button :click="click">Post</Button>
</div>
</template>
<script>
import Input from './Input.vue';
import Button from './Button.vue';
import axios from 'axios';
export default {
methods: {
async click(e) {
const name = document.getElementById("name").value
const tags = document.getElementById("tags").value
const url = document.getElementById("url").value
const token = localStorage.getItem("token")
const res = await axios.get(`/api/add_resource?token=${token}&name=${name}&tags=${tags}&url=${url}`)
if(res.data["error"]!==0)
return alert("Error!")
alert("Resource added!")
location.reload()
}
},
}
</script>
<style scoped>
h1{
color: var(--white);
font-size: 50px;
margin-bottom: 20px;
text-align: center;
}
div{
background-color: var(--dark-three);
padding: 50px;
margin-top: 50px;
display: flex;
flex-direction: column;
gap: 20px;
align-items: center;
justify-content: center;
}
</style>

63
components/Project.vue Normal file
View File

@ -0,0 +1,63 @@
<template>
<main @click="redirect()">
<i class='bx bx-code-alt'></i>
<div>
<h1>{{ name }}</h1>
<h2>{{ desc }}</h2>
</div>
</main>
</template>
<script>
export default {
props: ["name", "desc", "url"],
methods: {
redirect(e) {
location.href = this.url
}
},
}
</script>
<style scoped>
main {
color: var(--white);
background: var(--dark-two);
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
gap: 20px;
padding: 40px;
cursor: pointer;
transition: .4s;
height: 13%;
width: 27%;
}
main:hover{
box-shadow: var(--def-shadow);
}
i{
font-size: 65px;
animation-name: colorAnimation;
animation-duration: 10s;
animation-iteration-count: infinite;
}
h1{
font-size: 35px;
margin-bottom: 10px;
}
h2{
font-size: 25px;
}
@media only screen and (max-width: 1121px) {
main{
width: auto;
}
}
</style>

View File

@ -0,0 +1,28 @@
<template>
<div>
<slot></slot>
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
div{
display: flex;
flex-direction: row;
padding: 20px;
align-items: center;
justify-content: center;
gap: 30px;
}
@media only screen and (max-width: 1121px) {
div {
flex-direction: column;
}
}
</style>

66
components/Resource.vue Normal file
View File

@ -0,0 +1,66 @@
<template>
<main @click="redirect()" class="mn">
<div class="resource">
<h1>{{ name }}</h1>
<div class="tags">
<Tag v-for="tag in tags" :key="tag">{{ tag }}</Tag>
</div>
</div>
<i class='bx bx-right-arrow-alt' ></i>
</main>
</template>
<script>
import Tag from './Tag.vue';
export default {
props: ["tags", "name", "url"],
methods: {
redirect(e){
location.href = this.url
}
}
}
</script>
<style scoped>
main{
background: var(--dark-two);
padding: 30px 40px 30px 40px;
display: flex;
flex-direction: row;
color: var(--white);
justify-content: space-between;
align-items: center;
transition: .4s;
width: 80%;
cursor: pointer;
}
main:hover{
box-shadow: var(--def-shadow);
}
.mn:hover i{
color: white;
}
.resource{
display: flex;
flex-direction: column;
gap: 10px;
}
.tags{
display: flex;
flex-direction: row;
gap: 10px;
}
i{
font-size: 70px;
cursor: pointer;
color: var(--dark-two);
transition: .4s;
}
</style>

24
components/Tag.vue Normal file
View File

@ -0,0 +1,24 @@
<template>
<p>
#<slot></slot>
</p>
</template>
<script>
export default {
}
</script>
<style scoped>
p{
background: var(--dark-three);
color: white;
text-shadow: 1px 1px 2px white;
padding: 5px 10px 5px 10px;
font-size: 25px;
border-radius: 7px;
margin-top: 10px;
transition: .4s;
}
</style>

31
nuxt.config.js Normal file
View File

@ -0,0 +1,31 @@
export default {
head: {
title: "[ngn]",
htmlAttrs: {
lang: "en",
},
meta: [
{ charset: "utf-8" },
{ name: "viewport", content: "width=device-width, initial-scale=1" },
{ hid: "description", name: "description", content: "" },
{ name: "format-detection", content: "telephone=no" },
{ hid: "og:title", content: "[ngn]" },
{ hid: "og:description", content: "ngn's (very cool) personal website" },
{ hid: "og:url", content: "https://ngn13.fun" },
{ name: "theme-color", content: "#0c16d1", "data-react-helmet":"true"},
],
link: [{ rel: "stylesheet", href: "https://unpkg.com/boxicons@2.1.4/css/boxicons.min.css" }]
},
css: ["@/static/global.css"],
plugins: [],
components: true,
buildModules: [],
modules: ["@nuxtjs/axios"],
axios: {
baseURL: "/",
},
build: {},
serverMiddleware: {
"/api": "~/api",
},
};

25913
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

20
package.json Normal file
View File

@ -0,0 +1,20 @@
{
"name": "my-website",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"generate": "nuxt generate"
},
"dependencies": {
"@nuxtjs/axios": "^5.13.6",
"core-js": "^3.25.3",
"express": "^4.18.2",
"nuxt": "^2.15.8",
"vue": "^2.7.10",
"vue-server-renderer": "^2.7.10",
"vue-template-compiler": "^2.7.10"
}
}

86
pages/index.vue Normal file
View File

@ -0,0 +1,86 @@
<template>
<div>
<Navbar />
<Header>
<glitch>echo</glitch> hello world!
</Header>
<div class="info">
<Card>
<h1>👋 Welcome to my website!</h1>
<h2>
I am a high school student who is interested in
<br>
cyber security
<br>
coding
<br>
electronics
<br>
simply: everything about computers!
</h2>
</Card>
<Card>
<h1>👉 Checkout my socials</h1>
<h2>Here you can find my socials for following platforms:</h2>
<br>
<a href="https://discord.com/users/568131907368386565"><i class='bx bxl-discord-alt'></i> Discord</a>
<br>
<a href="https://github.com/ngn13"><i class='bx bxl-github'></i> Github</a>
<br>
<a href="https://www.reddit.com/user/_ngn"><i class='bx bxl-reddit'></i> Reddit</a>
<br>
<a href="https://fosstodon.org/@ngn"><i class='bx bxl-mastodon'></i> Fosstodon</a>
</Card>
</div>
<Logout v-if="logged"/>
</div>
</template>
<script>
import Navbar from "../components/Navbar.vue";
import Header from "../components/Header.vue";
import Card from "../components/Card.vue"
import Logout from "../components/Logout.vue";
export default {
head() {
return {
title: "[ngn]",
meta: [
{
hid: "description",
name: "description",
content: "ngn's Personal Website | Home Page"
}
]
}
},
data() {
return {
logged: false
}
},
mounted(){
if(localStorage.getItem("token"))
this.logged = true
}
}
</script>
<style scoped>
.info {
padding: 50px;
gap: 30px;
display: flex;
}
@media only screen and (max-width: 1076px) {
.info {
flex-direction: column;
}
.info div {
width: auto;
}
}
</style>

51
pages/login.vue Normal file
View File

@ -0,0 +1,51 @@
<template>
<div>
<h1>Login Page</h1>
<Input :keyup="function() { }" placeholder="Password" type="password" id="pass"/>
<Button :click="click">Login</Button>
</div>
</template>
<script>
import Input from '../components/Input.vue';
import Button from '../components/Button.vue';
import axios from "axios";
export default {
methods: {
async click(e) {
const pass = document.getElementById("pass").value
const res = await axios.get(`/api/login?pass=${pass}`)
if(res.data["error"]===0){
localStorage.setItem("token", res.data["token"])
return location.href="/"
}
alert("Incorrect password!")
}
}
}
</script>
<style scoped>
div {
padding: 50px;
background: var(--dark-three);
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
display: flex;
flex-direction: column;
gap: 20px;
color: var(--white);
align-items: center;
justify-content: center;
}
h1{
font-size: 70px;
margin-bottom: 20px;
}
</style>

73
pages/projects.vue Normal file
View File

@ -0,0 +1,73 @@
<template>
<div>
<Navbar />
<Header>
<glitch>ls -la</glitch> projects
</Header>
<div class="projects">
<ProjectList v-for="project in projects" :key="project">
<Project v-for="p in project" :key="p" :name="p.name" :desc="p.desc" :url="p.url"/>
</ProjectList>
</div>
<NewProject v-if="logged"/>
</div>
</template>
<script>
import ProjectList from "../components/ProjectList.vue";
import Project from "../components/Project.vue";
import NewProject from "../components/NewProject.vue";
import axios from "axios";
export default {
head() {
return {
title: "[ngn]",
meta: [
{
hid: "description",
name: "description",
content: "ngn's Personal Website | Projects Page"
}
]
}
},
data() {
return {
logged: false,
projects: []
}
},
mounted: async function(){
if(localStorage.getItem("token"))
this.logged = true
const res = await axios.get("/api/get_projects")
let all = res.data["projects"]
let projects = []
let project = []
for(let i = 0; i<all.length; i++){
if(project.length!==3)
project.push(all[i])
else{
projects.push(project)
project = []
}
if(i===all.length-1){
projects.push(project)
}
}
this.projects = projects
}
}
</script>
<style>
.projects{
margin-top: 20px;
display: flex;
flex-direction: column;
}
</style>

76
pages/resources.vue Normal file
View File

@ -0,0 +1,76 @@
<template>
<main>
<Navbar />
<Header>
<glitch>cat</glitch> {{ header }}
</Header>
<div class="resources">
<Input :keyup="keyup" placeholder="Search resource" type="text"/>
<Resource v-for="resource in resources" :key="resource" :name="resource.name" :tags="resource.tags" :url="resource.url" />
</div>
<NewResource v-if="logged"/>
</main>
</template>
<script>
import axios from 'axios';
import Resource from '../components/Resource.vue';
import Input from '../components/Input.vue';
import NewResource from '../components/NewResource.vue';
export default {
data() {
return {
header: "resources",
logged: false,
resources: [],
all: []
}
},
methods: {
keyup(e) {
let val = e.target.value
if(e.key==="Backspace" && val===""){
this.header = "resources"
this.resources = this.all
return
}
if(e.key==="OS")
return
this.header = `resources | grep ${val}`
// dirty asf search alg
this.resources = []
for(let i = 0; i < this.all.length; i++){
if(this.all[i].name.toLowerCase().includes(val.toLowerCase()))
this.resources.push(this.all[i])
for(let e = 0; e < this.all[i].tags.length; e++){
if(this.all[i].tags[e].toLowerCase().includes(val.toLowerCase())){
if(this.resources.indexOf(this.all[i])===-1)
this.resources.push(this.all[i])
}
}
}
}
},
mounted: async function(){
if(localStorage.getItem("token"))
this.logged = true
const res = await axios.get("/api/get_resources")
this.resources = res.data["resources"]
this.all = res.data["resources"]
}
}
</script>
<style scoped>
.resources {
padding: 50px;
display: flex;
flex-direction: column;
align-items: center;
gap: 40px
}
</style>

BIN
static/Minecraft.ttf Normal file

Binary file not shown.

315
static/global.css Normal file
View File

@ -0,0 +1,315 @@
@import url("https://fonts.googleapis.com/css2?family=Ubuntu:wght@300&display=swap");
:root {
--white: white;
--dark-one: #141414;
--dark-two: #18191a;
--dark-three: #282828;
--dark-four: #242526;
--dark-fife: #3a3b3c;
--border-rad: 30px;
--def-shadow: rgba(0, 0, 0, 0.25) 0px 54px 55px,
rgba(0, 0, 0, 0.12) 0px -12px 30px, rgba(0, 0, 0, 0.12) 0px 4px 6px,
rgba(0, 0, 0, 0.17) 0px 12px 13px, rgba(0, 0, 0, 0.09) 0px -3px 5px;
}
* {
padding: 0;
margin: 0;
}
body {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background: #141414;
font-family: "Ubuntu", sans-serif;
overflow-x: hidden;
}
::-webkit-scrollbar {
border-radius: 10px;
width: 10px;
}
::-webkit-scrollbar-track {
border-radius: 10px;
background: #181818;
}
::-webkit-scrollbar-thumb {
border-radius: 10px;
background: #282828;
}
@keyframes colorAnimation {
100%,
0% {
color: rgb(255, 0, 0);
}
8% {
color: rgb(255, 127, 0);
}
16% {
color: rgb(255, 255, 0);
}
25% {
color: rgb(127, 255, 0);
}
33% {
color: rgb(0, 255, 0);
}
41% {
color: rgb(0, 255, 127);
}
50% {
color: rgb(0, 255, 255);
}
58% {
color: rgb(0, 127, 255);
}
66% {
color: rgb(0, 0, 255);
}
75% {
color: rgb(127, 0, 255);
}
83% {
color: rgb(255, 0, 255);
}
91% {
color: rgb(255, 0, 127);
}
}
@keyframes borderAnimation {
100%,
0% {
border-bottom-color: rgb(255, 0, 0);
}
8% {
border-bottom-color: rgb(255, 127, 0);
}
16% {
border-bottom-color: rgb(255, 255, 0);
}
25% {
border-bottom-color: rgb(127, 255, 0);
}
33% {
border-bottom-color: rgb(0, 255, 0);
}
41% {
border-bottom-color: rgb(0, 255, 127);
}
50% {
border-bottom-color: rgb(0, 255, 255);
}
58% {
border-bottom-color: rgb(0, 127, 255);
}
66% {
border-bottom-color: rgb(0, 0, 255);
}
75% {
border-bottom-color: rgb(127, 0, 255);
}
83% {
border-bottom-color: rgb(255, 0, 255);
}
91% {
border-bottom-color: rgb(255, 0, 127);
}
}
@keyframes fullBorderAnimation {
100%,
0% {
border-color: rgb(255, 0, 0);
}
8% {
border-color: rgb(255, 127, 0);
}
16% {
border-color: rgb(255, 255, 0);
}
25% {
border-color: rgb(127, 255, 0);
}
33% {
border-color: rgb(0, 255, 0);
}
41% {
border-color: rgb(0, 255, 127);
}
50% {
border-color: rgb(0, 255, 255);
}
58% {
border-color: rgb(0, 127, 255);
}
66% {
border-color: rgb(0, 0, 255);
}
75% {
border-color: rgb(127, 0, 255);
}
83% {
border-color: rgb(255, 0, 255);
}
91% {
border-color: rgb(255, 0, 127);
}
}
@keyframes gayShadowAnimation {
100%,
0% {
box-shadow: rgba(255, 0, 0, 0.07) 0px 1px 2px,
rgba(255, 0, 0, 0.07) 0px 2px 4px, rgba(255, 0, 0, 0.07) 0px 4px 8px,
rgba(255, 0, 0, 0.07) 0px 8px 16px, rgba(255, 0, 0, 0.07) 0px 16px 32px,
rgba(255, 0, 0, 0.07) 0px 32px 64px;
}
8% {
box-shadow: rgba(255, 127, 0, 0.07) 0px 1px 2px,
rgba(255, 127, 0, 0.07) 0px 2px 4px, rgba(255, 127, 0, 0.07) 0px 4px 8px,
rgba(255, 127, 0, 0.07) 0px 8px 16px,
rgba(255, 127, 0, 0.07) 0px 16px 32px,
rgba(255, 127, 0, 0.07) 0px 32px 64px;
}
16% {
box-shadow: rgba(255, 255, 0, 0.07) 0px 1px 2px,
rgba(255, 255, 0, 0.07) 0px 2px 4px, rgba(255, 255, 0, 0.07) 0px 4px 8px,
rgba(255, 255, 0, 0.07) 0px 8px 16px,
rgba(255, 255, 0, 0.07) 0px 16px 32px,
rgba(255, 255, 0, 0.07) 0px 32px 64px;
}
25% {
box-shadow: rgba(127, 255, 0, 0.07) 0px 1px 2px,
rgba(127, 255, 0, 0.07) 0px 2px 4px, rgba(127, 255, 0, 0.07) 0px 4px 8px,
rgba(127, 255, 0, 0.07) 0px 8px 16px,
rgba(127, 255, 0, 0.07) 0px 16px 32px,
rgba(127, 255, 0, 0.07) 0px 32px 64px;
}
33% {
box-shadow: rgba(0, 255, 0, 0.07) 0px 1px 2px,
rgba(0, 255, 0, 0.07) 0px 2px 4px, rgba(0, 255, 0, 0.07) 0px 4px 8px,
rgba(0, 255, 0, 0.07) 0px 8px 16px, rgba(0, 255, 0, 0.07) 0px 16px 32px,
rgba(0, 255, 0, 0.07) 0px 32px 64px;
}
41% {
box-shadow: rgba(0, 255, 127, 0.07) 0px 1px 2px,
rgba(0, 255, 127, 0.07) 0px 2px 4px, rgba(0, 255, 127, 0.07) 0px 4px 8px,
rgba(0, 255, 127, 0.07) 0px 8px 16px,
rgba(0, 255, 127, 0.07) 0px 16px 32px,
rgba(0, 255, 127, 0.07) 0px 32px 64px;
}
50% {
box-shadow: rgba(0, 255, 255, 0.07) 0px 1px 2px,
rgba(0, 255, 255, 0.07) 0px 2px 4px, rgba(0, 255, 255, 0.07) 0px 4px 8px,
rgba(0, 255, 255, 0.07) 0px 8px 16px,
rgba(0, 255, 255, 0.07) 0px 16px 32px,
rgba(0, 255, 255, 0.07) 0px 32px 64px;
}
58% {
box-shadow: rgba(0, 127, 255, 0.07) 0px 1px 2px,
rgba(0, 127, 255, 0.07) 0px 2px 4px, rgba(0, 127, 255, 0.07) 0px 4px 8px,
rgba(0, 127, 255, 0.07) 0px 8px 16px,
rgba(0, 127, 255, 0.07) 0px 16px 32px,
rgba(0, 127, 255, 0.07) 0px 32px 64px;
}
66% {
box-shadow: rgba(0, 0, 255, 0.07) 0px 1px 2px,
rgba(0, 0, 255, 0.07) 0px 2px 4px, rgba(0, 0, 255, 0.07) 0px 4px 8px,
rgba(0, 0, 255, 0.07) 0px 8px 16px, rgba(0, 0, 255, 0.07) 0px 16px 32px,
rgba(0, 0, 255, 0.07) 0px 32px 64px;
}
75% {
box-shadow: rgba(127, 0, 255, 0.07) 0px 1px 2px,
rgba(127, 0, 255, 0.07) 0px 2px 4px, rgba(127, 0, 255, 0.07) 0px 4px 8px,
rgba(127, 0, 255, 0.07) 0px 8px 16px,
rgba(127, 0, 255, 0.07) 0px 16px 32px,
rgba(127, 0, 255, 0.07) 0px 32px 64px;
}
83% {
box-shadow: rgba(255, 0, 255, 0.07) 0px 1px 2px,
rgba(255, 0, 255, 0.07) 0px 2px 4px, rgba(255, 0, 255, 0.07) 0px 4px 8px,
rgba(255, 0, 255, 0.07) 0px 8px 16px,
rgba(255, 0, 255, 0.07) 0px 16px 32px,
rgba(255, 0, 255, 0.07) 0px 32px 64px;
}
91% {
box-shadow: rgba(255, 0, 127, 0.07) 0px 1px 2px,
rgba(255, 0, 127, 0.07) 0px 2px 4px, rgba(255, 0, 127, 0.07) 0px 4px 8px,
rgba(255, 0, 127, 0.07) 0px 8px 16px,
rgba(255, 0, 127, 0.07) 0px 16px 32px,
rgba(255, 0, 127, 0.07) 0px 32px 64px;
}
}
@keyframes underlineAnimation {
100%,
0% {
text-decoration-color: rgb(255, 0, 0);
}
8% {
text-decoration-color: rgb(255, 127, 0);
}
16% {
text-decoration-color: rgb(255, 255, 0);
}
25% {
text-decoration-color: rgb(127, 255, 0);
}
33% {
text-decoration-color: rgb(0, 255, 0);
}
41% {
text-decoration-color: rgb(0, 255, 127);
}
50% {
text-decoration-color: rgb(0, 255, 255);
}
58% {
text-decoration-color: rgb(0, 127, 255);
}
66% {
text-decoration-color: rgb(0, 0, 255);
}
75% {
text-decoration-color: rgb(127, 0, 255);
}
83% {
text-decoration-color: rgb(255, 0, 255);
}
91% {
text-decoration-color: rgb(255, 0, 127);
}
}
@keyframes minecraftAnimation {
0%{
font-size: 15px;
}
50%{
font-size: 17px;
}
100%{
font-size: 15px;
}
}
@font-face {
font-family: "Minecraft";
src: url("/Minecraft.ttf") format("opentype");
}
glitch {
animation-name: colorAnimation;
animation-iteration-count: infinite;
animation-duration: 10s;
text-shadow: none;
}