initial sveltekit setup
This commit is contained in:
parent
f7f008cc89
commit
195e4c7e02
@ -1,13 +0,0 @@
|
||||
# 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
|
98
.gitignore
vendored
98
.gitignore
vendored
@ -1,90 +1,10 @@
|
||||
# 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
|
||||
node_modules
|
||||
/build
|
||||
/.svelte-kit
|
||||
/package
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
vite.config.js.timestamp-*
|
||||
vite.config.ts.timestamp-*
|
||||
|
@ -1 +0,0 @@
|
||||
.nuxt
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"trailingComma": "none",
|
||||
"tabWidth": 2,
|
||||
"semi": false,
|
||||
"singleQuote": false
|
||||
}
|
49
README.md
49
README.md
@ -1,17 +1,38 @@
|
||||
# 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. As database,
|
||||
it uses mongodb. It's just a personal project that
|
||||
I am working on.
|
||||
# create-svelte
|
||||
|
||||
Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte).
|
||||
|
||||
## Creating a project
|
||||
|
||||
If you're seeing this, you've probably already done this step. Congrats!
|
||||
|
||||
## Setup
|
||||
For some reason if you want to setup my website localy
|
||||
install `nodejs` and `npm`, then run the following:
|
||||
```bash
|
||||
git clone https://github.com/ngn13/ngn13.fun.git && cd ngn13.fun &&
|
||||
npm i
|
||||
echo "PASS=password" > .env
|
||||
echo "DATABASE=mongodb://127.0.0.1" > .env
|
||||
npm run build
|
||||
npm run start
|
||||
# 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.
|
||||
|
46
api/index.js
46
api/index.js
@ -1,46 +0,0 @@
|
||||
const express = require("express")
|
||||
const { MongoClient } = require("mongodb")
|
||||
require("dotenv").config()
|
||||
|
||||
/*
|
||||
* error: 0 -> no error
|
||||
* error: 1 -> parameter error
|
||||
* error: 2 -> auth error
|
||||
* error: 3 -> not found error
|
||||
*/
|
||||
|
||||
const db = new MongoClient(process.env.DATABASE)
|
||||
const app = express()
|
||||
app.use(express.json())
|
||||
app.use(express.urlencoded({ extended: false }))
|
||||
app.use(async (req, res, next) => {
|
||||
await db.connect()
|
||||
req.db = db
|
||||
next()
|
||||
})
|
||||
|
||||
const { auth, authware } = require("./routes/auth.js")
|
||||
// anything starts with "add"
|
||||
// requires admin privs
|
||||
app.use("/*/a*", authware)
|
||||
const resources = require("./routes/resources.js")
|
||||
const projects = require("./routes/projects.js")
|
||||
const blog = require("./routes/blog.js")
|
||||
const routes = [resources, projects, blog, auth]
|
||||
|
||||
routes.forEach((route) => {
|
||||
app.use(route.path, route)
|
||||
})
|
||||
|
||||
async function pexit() {
|
||||
await db.close()
|
||||
process.exit()
|
||||
}
|
||||
|
||||
process.on("SIGTERM", pexit)
|
||||
process.on("SIGINT", pexit)
|
||||
|
||||
export default {
|
||||
path: "/api",
|
||||
handler: app
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
const express = require("express")
|
||||
const { gimmeToken } = require("../util.js")
|
||||
const auth = express.Router()
|
||||
auth.path = "/auth"
|
||||
|
||||
const PASS = process.env.PASS
|
||||
let TOKEN = gimmeToken()
|
||||
|
||||
function authware(req, res, next) {
|
||||
const token = req.query.token ? req.query.token : req.body.token
|
||||
|
||||
if (typeof token !== "string") return res.json({ error: 1 })
|
||||
|
||||
if (token !== TOKEN) return res.json({ error: 2 })
|
||||
|
||||
next()
|
||||
}
|
||||
auth.use("/logout", authware)
|
||||
|
||||
auth.get("/login", async (req, res) => {
|
||||
const pass = req.query.pass
|
||||
|
||||
if (typeof pass !== "string") return res.json({ error: 1 })
|
||||
|
||||
if (pass !== PASS) return res.json({ error: 2 })
|
||||
|
||||
res.json({ error: 0, token: TOKEN })
|
||||
})
|
||||
|
||||
auth.get("/logout", async (req, res) => {
|
||||
TOKEN = gimmeToken()
|
||||
res.json({ error: 0 })
|
||||
})
|
||||
|
||||
module.exports = { auth, authware }
|
@ -1,87 +0,0 @@
|
||||
const express = require("express")
|
||||
const { makeID } = require("../util.js")
|
||||
const blog = express.Router()
|
||||
blog.path = "/blog"
|
||||
|
||||
blog.get("/sum", async (req, res) => {
|
||||
const db = req.db.db("ngn13")
|
||||
const col = db.collection("posts")
|
||||
const results = await col.find({ priv: { $eq: false } }).toArray()
|
||||
|
||||
let posts = []
|
||||
for (let i = 0; i < results.length; i++) {
|
||||
posts.push({
|
||||
title: results[i]["title"],
|
||||
desc:
|
||||
results[i]["content"]
|
||||
.substring(0, 140) // a short desc
|
||||
.replaceAll("#", "") // remove all the markdown stuff
|
||||
.replaceAll("*", "")
|
||||
.replaceAll("`", "")
|
||||
.replaceAll("-", "") + "...", // add "..." to make it look like desc
|
||||
info: `${results[i]["author"]} | ${results[i]["date"]}`
|
||||
})
|
||||
}
|
||||
|
||||
// reversing so we can get
|
||||
// the latest posts on the top
|
||||
res.json({ error: 0, posts: posts.reverse() })
|
||||
})
|
||||
|
||||
blog.get("/get", async (req, res) => {
|
||||
const id = req.query.id
|
||||
|
||||
const db = req.db.db("ngn13")
|
||||
const col = db.collection("posts")
|
||||
const results = await col.find().toArray()
|
||||
|
||||
for (let i = 0; i < results.length; i++) {
|
||||
// id is basically the title of the post
|
||||
// but ve remove the whitespace
|
||||
// and make it lowerspace
|
||||
// for example:
|
||||
// Online Privacy Guide -> onlineprivacyguide
|
||||
if (makeID(results[i]["title"]) === id) {
|
||||
return res.json({
|
||||
error: 0,
|
||||
post: {
|
||||
title: results[i]["title"],
|
||||
// info is the subtitle, for example:
|
||||
// ngn | 01/06/2023
|
||||
info: `${results[i]["author"]} | ${results[i]["date"]}`,
|
||||
content: results[i]["content"]
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
res.json({ error: 3 })
|
||||
})
|
||||
|
||||
blog.post("/add", async (req, res) => {
|
||||
const title = req.body.title
|
||||
const author = req.body.author
|
||||
const content = req.body.content
|
||||
const priv = req.body.priv
|
||||
|
||||
if (
|
||||
typeof title !== "string" ||
|
||||
typeof author !== "string" ||
|
||||
typeof content !== "string" ||
|
||||
typeof priv !== "boolean"
|
||||
)
|
||||
return res.json({ error: 1 })
|
||||
|
||||
const db = req.db.db("ngn13")
|
||||
const col = db.collection("posts")
|
||||
await col.insertOne({
|
||||
title: title,
|
||||
author: author,
|
||||
date: new Date().toLocaleDateString(),
|
||||
content: content,
|
||||
priv: priv
|
||||
})
|
||||
res.json({ error: 0 })
|
||||
})
|
||||
|
||||
module.exports = blog
|
@ -1,35 +0,0 @@
|
||||
const express = require("express")
|
||||
const projects = express.Router()
|
||||
projects.path = "/projects"
|
||||
|
||||
projects.get("/get", async (req, res) => {
|
||||
const db = req.db.db("ngn13")
|
||||
const col = db.collection("projects")
|
||||
const results = await col.find().toArray()
|
||||
res.json({ error: 0, projects: results })
|
||||
})
|
||||
|
||||
projects.get("/add", async (req, res) => {
|
||||
let name = req.query.name
|
||||
let desc = req.query.desc
|
||||
let url = req.query.url
|
||||
|
||||
if (
|
||||
typeof name !== "string" ||
|
||||
typeof desc !== "string" ||
|
||||
typeof url !== "string"
|
||||
)
|
||||
return res.json({ error: 1 })
|
||||
|
||||
const db = req.db.db("ngn13")
|
||||
const col = db.collection("projects")
|
||||
await col.insertOne({
|
||||
name: name,
|
||||
desc: desc,
|
||||
url: url,
|
||||
click: 0
|
||||
})
|
||||
res.json({ error: 0 })
|
||||
})
|
||||
|
||||
module.exports = projects
|
@ -1,32 +0,0 @@
|
||||
const express = require("express")
|
||||
const resources = express.Router()
|
||||
resources.path = "/resources"
|
||||
|
||||
resources.get("/get", async (req, res) => {
|
||||
const db = req.db.db("ngn13")
|
||||
const col = db.collection("resources")
|
||||
let results = []
|
||||
if (req.query.sum) results = await col.find().limit(10).toArray()
|
||||
else results = await col.find().toArray()
|
||||
res.json({ error: 0, resources: results.reverse() })
|
||||
})
|
||||
|
||||
resources.get("/add", async (req, res) => {
|
||||
let name = req.query.name
|
||||
let tags = req.query.tags
|
||||
let url = req.query.url
|
||||
|
||||
if (
|
||||
typeof name !== "string" ||
|
||||
typeof tags !== "string" ||
|
||||
typeof url !== "string"
|
||||
)
|
||||
return res.json({ error: 1 })
|
||||
|
||||
const db = req.db.db("ngn13")
|
||||
const col = db.collection("resources")
|
||||
await col.insertOne({ name: name, tags: tags.split(","), url: url })
|
||||
res.json({ error: 0 })
|
||||
})
|
||||
|
||||
module.exports = resources
|
22
api/util.js
22
api/util.js
@ -1,22 +0,0 @@
|
||||
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
|
||||
}
|
||||
|
||||
function makeID(title) {
|
||||
// this is used in blog.js
|
||||
// id is basically the title of the post
|
||||
// but ve remove the whitespace
|
||||
// and make it lowerspace
|
||||
// for example:
|
||||
// Online Privacy Guide -> onlineprivacyguide
|
||||
return title.toLowerCase().replaceAll(" ", "")
|
||||
}
|
||||
|
||||
module.exports = { gimmeToken, makeID }
|
@ -1,29 +0,0 @@
|
||||
<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: 0.4s;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
box-shadow: var(--def-shadow);
|
||||
}
|
||||
</style>
|
@ -1,54 +0,0 @@
|
||||
<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>
|
@ -1,30 +0,0 @@
|
||||
<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>
|
@ -1,27 +0,0 @@
|
||||
<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: 10px;
|
||||
background: var(--dark-two);
|
||||
border: none;
|
||||
color: white;
|
||||
outline: none;
|
||||
transition: 0.4s;
|
||||
}
|
||||
|
||||
input:focus {
|
||||
box-shadow: var(--def-shadow);
|
||||
}
|
||||
</style>
|
@ -1,41 +0,0 @@
|
||||
<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/auth/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>
|
@ -1,55 +0,0 @@
|
||||
<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="/blog">Blog</NavbarLink>
|
||||
<NavbarLink :out="true" url="http://github.com/ngn13/ngn13.fun"
|
||||
>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>
|
@ -1,60 +0,0 @@
|
||||
<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>
|
@ -1,123 +0,0 @@
|
||||
<template>
|
||||
<main>
|
||||
<h1>Add New Post</h1>
|
||||
<div class="textareas">
|
||||
<Input
|
||||
:keyup="function () {}"
|
||||
id="title"
|
||||
placeholder="Post Title"
|
||||
type="text"
|
||||
/>
|
||||
<Input
|
||||
:keyup="function () {}"
|
||||
id="author"
|
||||
placeholder="Author"
|
||||
type="text"
|
||||
/>
|
||||
<h2>
|
||||
Make the post private
|
||||
<input id="private" type="checkbox" />
|
||||
</h2>
|
||||
</div>
|
||||
<textarea
|
||||
name="content"
|
||||
id="content"
|
||||
cols="30"
|
||||
rows="10"
|
||||
placeholder="Content"
|
||||
></textarea>
|
||||
<Button :click="click">Post</Button>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from "axios"
|
||||
import Input from "./Input.vue"
|
||||
import Button from "./Button.vue"
|
||||
|
||||
export default {
|
||||
methods: {
|
||||
async click(e) {
|
||||
const title = document.getElementById("title").value
|
||||
const author = document.getElementById("author").value
|
||||
const content = document.getElementById("content").value
|
||||
const priv = document.getElementById("private").value
|
||||
const token = localStorage.getItem("token")
|
||||
const res = await axios.post("/api/blog/add", {
|
||||
token: token,
|
||||
title: title,
|
||||
author: author,
|
||||
content: content,
|
||||
priv: priv === "on"
|
||||
})
|
||||
if (res.data["error"] !== 0) return alert("Error!")
|
||||
alert("Post added!")
|
||||
location.reload()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
h1 {
|
||||
color: var(--white);
|
||||
font-size: 50px;
|
||||
margin-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h2 {
|
||||
background: var(--dark-two);
|
||||
font-size: 25px;
|
||||
border-radius: 20px;
|
||||
border: none;
|
||||
padding: 20px;
|
||||
color: var(--white);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
input[type="checkbox"] {
|
||||
-ms-transform: scale(2);
|
||||
-moz-transform: scale(2);
|
||||
-webkit-transform: scale(2);
|
||||
-o-transform: scale(2);
|
||||
transform: scale(2);
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 500px;
|
||||
font-size: 20px;
|
||||
padding: 20px;
|
||||
border-radius: 20px;
|
||||
background: var(--dark-two);
|
||||
border: none;
|
||||
color: white;
|
||||
outline: none;
|
||||
resize: vertical;
|
||||
height: 200px;
|
||||
transition: 0.4s;
|
||||
}
|
||||
|
||||
.textareas {
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
textarea:focus {
|
||||
box-shadow: var(--def-shadow);
|
||||
}
|
||||
|
||||
main {
|
||||
background-color: var(--dark-three);
|
||||
padding: 50px;
|
||||
margin-top: 50px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
@ -1,67 +0,0 @@
|
||||
<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/projects/add?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>
|
@ -1,67 +0,0 @@
|
||||
<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/resources/add?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>
|
@ -1,42 +0,0 @@
|
||||
<template>
|
||||
<nuxt-link :to="url">
|
||||
<h1>{{ title }}</h1>
|
||||
<p>{{ info }}</p>
|
||||
<h2>{{ desc }}</h2>
|
||||
</nuxt-link>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ["title", "desc", "info", "url"]
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
a {
|
||||
padding: 30px;
|
||||
color: white;
|
||||
background: var(--dark-two);
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
transition: 0.4s;
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
box-shadow: var(--def-shadow);
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 40px;
|
||||
margin-bottom: 5px;
|
||||
animation-name: colorAnimation;
|
||||
animation-iteration-count: infinite;
|
||||
animation-duration: 10s;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 10px;
|
||||
}
|
||||
</style>
|
@ -1,62 +0,0 @@
|
||||
<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;
|
||||
gap: 20px;
|
||||
padding: 40px;
|
||||
cursor: pointer;
|
||||
height: 100px;
|
||||
width: 450px;
|
||||
transition: .4s;
|
||||
}
|
||||
|
||||
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: 1416px) {
|
||||
main {
|
||||
width: 80%;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,26 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
div {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 15px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 30px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1416px) {
|
||||
div {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,66 +0,0 @@
|
||||
<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;
|
||||
width: 80%;
|
||||
cursor: pointer;
|
||||
transition: .4s;
|
||||
}
|
||||
|
||||
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: 0.4s;
|
||||
}
|
||||
</style>
|
@ -1,20 +0,0 @@
|
||||
<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: 0.4s;
|
||||
}
|
||||
</style>
|
@ -1,12 +0,0 @@
|
||||
// https://v2.nuxt.com/deployments/pm2/
|
||||
module.exports = {
|
||||
apps: [
|
||||
{
|
||||
name: "ngn13.fun website",
|
||||
exec_mode: "cluster",
|
||||
instances: "max",
|
||||
script: "./node_modules/nuxt/bin/nuxt.js",
|
||||
args: "start"
|
||||
}
|
||||
]
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
<template>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ["error"],
|
||||
layout: "error",
|
||||
mounted() {
|
||||
this.$router.push({ path: "/" })
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,46 +0,0 @@
|
||||
const express = require("express")
|
||||
const { MongoClient } = require("mongodb")
|
||||
const { makeID } = require("../api/util.js")
|
||||
require("dotenv").config()
|
||||
|
||||
const app = express()
|
||||
app.use(express.json())
|
||||
app.use(express.urlencoded({ extended: false }))
|
||||
|
||||
const client = new MongoClient(process.env.DATABASE)
|
||||
|
||||
app.get("/:id", async (req, res) => {
|
||||
const id = req.params.id
|
||||
|
||||
if (typeof id !== "string") return res.redirect("/projects")
|
||||
|
||||
await client.connect()
|
||||
const db = client.db("ngn13")
|
||||
const col = db.collection("projects")
|
||||
const projects = await col.find().toArray()
|
||||
|
||||
for (let i = 0; i < projects.length; i++) {
|
||||
if (makeID(projects[i]["name"]) === id) {
|
||||
res.redirect(projects[i]["url"])
|
||||
await col.updateOne(
|
||||
{ name: projects[i]["name"] },
|
||||
{ $set: { click: projects[i]["click"] + 1 } }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return res.redirect("/projects")
|
||||
})
|
||||
|
||||
async function pexit() {
|
||||
await client.close()
|
||||
process.exit()
|
||||
}
|
||||
|
||||
process.on("SIGTERM", pexit)
|
||||
process.on("SIGINT", pexit)
|
||||
|
||||
export default {
|
||||
path: "/l",
|
||||
handler: app
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
export default {
|
||||
head: {
|
||||
title: "[ngn]",
|
||||
htmlAttrs: {
|
||||
lang: "en"
|
||||
},
|
||||
meta: [
|
||||
{ charset: "utf-8" },
|
||||
{ name: "viewport", content: "width=1200" },
|
||||
{ hid: "description", name: "description", content: "" },
|
||||
{ name: "format-detection", content: "telephone=no" },
|
||||
{ hid: "og:title", content: "[ngn]" },
|
||||
{
|
||||
hid: "og:description",
|
||||
content:
|
||||
"personal website of ngn | read my blogs, check out my projects, discover cool resources"
|
||||
},
|
||||
{ hid: "og:url", content: "https://ngn13.fun" },
|
||||
{ name: "theme-color", content: "#141414", "data-react-helmet": "true" }
|
||||
],
|
||||
link: [
|
||||
{
|
||||
rel: "stylesheet",
|
||||
href: "https://files.ngn13.fun/boxicons.min.css",
|
||||
},
|
||||
]
|
||||
},
|
||||
css: ["@/static/global.css"],
|
||||
plugins: [],
|
||||
components: true,
|
||||
buildModules: [],
|
||||
modules: ["@nuxtjs/axios"],
|
||||
axios: {
|
||||
baseURL: "/"
|
||||
},
|
||||
build: {},
|
||||
serverMiddleware: {
|
||||
"/api": "~/api",
|
||||
"/l": "~/links"
|
||||
}
|
||||
}
|
27892
package-lock.json
generated
27892
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
37
package.json
37
package.json
@ -1,24 +1,17 @@
|
||||
{
|
||||
"name": "my-website",
|
||||
"version": "2.5.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",
|
||||
"dompurify": "^3.0.3",
|
||||
"dotenv": "^16.0.3",
|
||||
"express": "^4.18.2",
|
||||
"marked": "^5.0.3",
|
||||
"mongodb": "^5.5.0",
|
||||
"nuxt": "^2.15.8",
|
||||
"vue": "^2.7.10",
|
||||
"vue-server-renderer": "^2.7.10",
|
||||
"vue-template-compiler": "^2.7.10"
|
||||
}
|
||||
"name": "website",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/adapter-auto": "^2.0.0",
|
||||
"@sveltejs/kit": "^1.20.4",
|
||||
"svelte": "^4.0.5",
|
||||
"vite": "^4.4.2"
|
||||
},
|
||||
"type": "module"
|
||||
}
|
||||
|
@ -1,111 +0,0 @@
|
||||
<template>
|
||||
<div class="all">
|
||||
<Navbar />
|
||||
<Header>
|
||||
<label class="glitch title">{{ post.title }}</label>
|
||||
<p>{{ post.info }}</p>
|
||||
</Header>
|
||||
<div class="postcontain">
|
||||
<main class="markdown-body" v-html="content"></main>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Navbar from "../../../components/Navbar.vue"
|
||||
import Header from "../../../components/Header.vue"
|
||||
import axios from "axios"
|
||||
import * as DOMPurify from "dompurify"
|
||||
import marked from "marked"
|
||||
|
||||
export default {
|
||||
head() {
|
||||
return {
|
||||
title: "[ngn] | blog",
|
||||
meta: [
|
||||
{
|
||||
hid: "description",
|
||||
name: "description",
|
||||
content: "read my blog posts"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
post: {},
|
||||
lang: "",
|
||||
content: ""
|
||||
}
|
||||
},
|
||||
|
||||
async created() {
|
||||
const res = await axios.get(`/api/blog/get?id=${this.$route.params.id}`)
|
||||
if (res.data["error"] === 3) return this.$router.push({ path: "/blog" })
|
||||
this.post = res.data["post"]
|
||||
this.post["content"] = this.post["content"].replaceAll(
|
||||
"\n<br>\n<br>\n",
|
||||
"\n\n"
|
||||
)
|
||||
this.content = DOMPurify.sanitize(
|
||||
marked.parse(this.post["content"], { breaks: true }),
|
||||
{
|
||||
ADD_TAGS: ["iframe"],
|
||||
ADD_ATTR: ["allow", "allowfullscreen", "frameborder", "scrolling"]
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
glitch {
|
||||
font-size: 80px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
.info {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.postcontain {
|
||||
padding: 50px;
|
||||
}
|
||||
|
||||
.markdown-body {
|
||||
font-size: 25px;
|
||||
padding: 50px;
|
||||
border-radius: 10px;
|
||||
background-color: var(--dark-two);
|
||||
box-shadow: var(--def-shadow);
|
||||
}
|
||||
</style>
|
||||
|
||||
<style>
|
||||
.markdown-body {
|
||||
font-family: "Ubuntu", sans-serif;
|
||||
}
|
||||
|
||||
.markdown-body h1 {
|
||||
border-bottom: 1px solid #505050;
|
||||
}
|
||||
|
||||
.markdown-body iframe {
|
||||
display: block;
|
||||
margin: 20px 0px;
|
||||
}
|
||||
|
||||
.markdown-body a {
|
||||
animation-name: colorAnimation;
|
||||
animation-iteration-count: infinite;
|
||||
animation-duration: 10s;
|
||||
text-shadow: none;
|
||||
}
|
||||
</style>
|
@ -1,92 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<Navbar />
|
||||
<Header> <label class="glitch">/dev/</label>blog </Header>
|
||||
<div class="blogs">
|
||||
<Input :keyup="keyup" placeholder="Search post" type="text" />
|
||||
<PostPreview
|
||||
v-for="post in posts"
|
||||
:key="post.title"
|
||||
:title="post.title"
|
||||
:desc="post.desc"
|
||||
:info="post.info"
|
||||
:url="post.url"
|
||||
>
|
||||
{{ post.desc }}
|
||||
</PostPreview>
|
||||
</div>
|
||||
<NewPost v-if="logged" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Navbar from "../../components/Navbar.vue"
|
||||
import Header from "../../components/Header.vue"
|
||||
import NewPost from "../../components/NewPost.vue"
|
||||
import PostPreview from "../../components/PostPreview.vue"
|
||||
import axios from "axios"
|
||||
|
||||
export default {
|
||||
head() {
|
||||
return {
|
||||
title: "[ngn] | blog",
|
||||
meta: [
|
||||
{
|
||||
hid: "description",
|
||||
name: "description",
|
||||
content: "read my blog posts"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
logged: false,
|
||||
posts: [],
|
||||
all: []
|
||||
}
|
||||
},
|
||||
mounted: async function () {
|
||||
if (localStorage.getItem("token")) this.logged = true
|
||||
const res = await axios.get("/api/blog/sum")
|
||||
let posts = []
|
||||
|
||||
res.data["posts"].forEach((post) => {
|
||||
posts.push({
|
||||
title: post.title,
|
||||
desc: post.desc,
|
||||
info: post.info,
|
||||
url: `/blog/${post.title.toLowerCase().replaceAll(" ", "")}`
|
||||
})
|
||||
})
|
||||
|
||||
this.posts = posts
|
||||
this.all = posts
|
||||
},
|
||||
methods: {
|
||||
keyup(e) {
|
||||
let val = e.target.value
|
||||
|
||||
// search looks at name and info
|
||||
this.posts = []
|
||||
for (let i = 0; i < this.all.length; i++) {
|
||||
if (this.all[i].title.toLowerCase().includes(val.toLowerCase()))
|
||||
this.posts.push(this.all[i])
|
||||
else if (this.all[i].info.toLowerCase().includes(val.toLowerCase()))
|
||||
this.posts.push(this.all[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.blogs {
|
||||
padding: 50px;
|
||||
gap: 35px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 30px;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
109
pages/index.vue
109
pages/index.vue
@ -1,109 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<Navbar />
|
||||
<Header> <label class="glitch">echo</label> 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 />
|
||||
• gaming
|
||||
<br />
|
||||
• simply: everything about computers!
|
||||
</h2>
|
||||
</Card>
|
||||
<Card>
|
||||
<h1>👉 Contact me</h1>
|
||||
<h2>You can contact me on the following platforms:</h2>
|
||||
|
||||
<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://mastodon.social/@ngn"
|
||||
><i class="bx bxl-mastodon"></i> Mastodon</a
|
||||
>
|
||||
<br />
|
||||
<a href="mailto:ngn13proton@proton.me"
|
||||
><i class="bx bxs-envelope"></i> Mail</a
|
||||
>
|
||||
<br />
|
||||
<h2>or private message me on matrix:</h2>
|
||||
<a><i>[matrix]</i> @ngn:matrix.ngn13.fun</a>
|
||||
</Card>
|
||||
</div>
|
||||
<Logout v-if="logged" />
|
||||
<div class="version">
|
||||
<p>v2.6</p>
|
||||
</div>
|
||||
</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: "homepage of my website"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
logged: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (localStorage.getItem("token")) this.logged = true
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.info {
|
||||
padding: 50px;
|
||||
gap: 30px;
|
||||
display: flex;
|
||||
}
|
||||
.version {
|
||||
color: var(--dark-fife);
|
||||
position: fixed;
|
||||
bottom: 10px;
|
||||
right: 10px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
i {
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1076px) {
|
||||
.info {
|
||||
flex-direction: column;
|
||||
}
|
||||
.info div {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,56 +0,0 @@
|
||||
<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/auth/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>
|
@ -1,105 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<Navbar />
|
||||
<Header> <label class="glitch">ls -la</label> projects </Header>
|
||||
<div class="projects">
|
||||
<ProjectList v-for="project in projects" :key="project.id">
|
||||
<Project
|
||||
v-if="logged"
|
||||
v-for="p in project.list"
|
||||
:key="p.name"
|
||||
:name="`${p.name} (${p.click})`"
|
||||
:desc="p.desc"
|
||||
:url="p.url"
|
||||
/>
|
||||
<Project
|
||||
v-if="!logged"
|
||||
v-for="p in project.list"
|
||||
:key="p.desc"
|
||||
: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] | projects",
|
||||
meta: [
|
||||
{
|
||||
hid: "description",
|
||||
name: "description",
|
||||
content: "check out my projects"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
logged: false,
|
||||
projects: []
|
||||
}
|
||||
},
|
||||
mounted: async function () {
|
||||
if (localStorage.getItem("token")) this.logged = true
|
||||
|
||||
const res = await axios.get("/api/projects/get")
|
||||
|
||||
let all = res.data["projects"]
|
||||
let pcounter = 0
|
||||
let projects = []
|
||||
let project = {
|
||||
id: pcounter,
|
||||
list: []
|
||||
}
|
||||
for (let i = 0; i < all.length; i++) {
|
||||
if (project["list"].length === 3) {
|
||||
projects.push(project)
|
||||
pcounter += 1
|
||||
project = {
|
||||
id: pcounter,
|
||||
list: []
|
||||
}
|
||||
}
|
||||
|
||||
project["list"].push({
|
||||
name: all[i]["name"],
|
||||
desc: all[i]["desc"],
|
||||
click: all[i]["click"],
|
||||
url: `/l/${all[i]["name"].toLowerCase().replaceAll(" ", "")}`
|
||||
})
|
||||
|
||||
if (i === all.length - 1) {
|
||||
projects.push(project)
|
||||
}
|
||||
}
|
||||
|
||||
this.projects = projects
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.projects {
|
||||
padding: 50px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1121px) {
|
||||
.projects {
|
||||
padding: 50px;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,108 +0,0 @@
|
||||
<template>
|
||||
<main>
|
||||
<Navbar />
|
||||
<Header> <label class="glitch">cat</label> {{ header }} </Header>
|
||||
<div class="resources">
|
||||
<Input :keyup="keyup" placeholder="Search resource" type="text" />
|
||||
<Resource
|
||||
v-for="res in show_resources"
|
||||
:key="res.name"
|
||||
:name="res.name"
|
||||
:tags="res.tags"
|
||||
:url="res.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 {
|
||||
head() {
|
||||
return {
|
||||
title: "[ngn] | resources",
|
||||
meta: [
|
||||
{
|
||||
hid: "description",
|
||||
name: "description",
|
||||
content: "discover new resources"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
header: "resources",
|
||||
logged: false,
|
||||
sum_resources: [],
|
||||
all_resources: [],
|
||||
show_resources: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
keyup(e) {
|
||||
let search = e.target.value
|
||||
if (e.key === "Backspace" && search === "") {
|
||||
this.header = "resources"
|
||||
this.show_resources = this.sum_resources
|
||||
return
|
||||
}
|
||||
if (e.key === "OS") return
|
||||
this.header = `resources | grep ${search}`
|
||||
|
||||
// dirty asf search alg
|
||||
this.show_resources = []
|
||||
for (let i = 0; i < this.all_resources.length; i++) {
|
||||
if (
|
||||
this.all_resources[i].name
|
||||
.toLowerCase()
|
||||
.includes(search.toLowerCase())
|
||||
) {
|
||||
this.show_resources.push(this.all_resources[i])
|
||||
continue
|
||||
}
|
||||
|
||||
for (let e = 0; e < this.all_resources[i].tags.length; e++) {
|
||||
if (
|
||||
this.all_resources[i].tags[e]
|
||||
.toLowerCase()
|
||||
.includes(search.toLowerCase())
|
||||
) {
|
||||
this.show_resources.push(this.all_resources[i])
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted: async function () {
|
||||
if (localStorage.getItem("token")) this.logged = true
|
||||
|
||||
// request top 10 resources so we can
|
||||
// render the DOM as fast as possible
|
||||
let res = await axios.get("/api/resources/get?sum=1")
|
||||
this.sum_resources = res.data["resources"]
|
||||
this.show_resources = this.sum_resources
|
||||
|
||||
// then we can load all the resources
|
||||
res = await axios.get("/api/resources/get")
|
||||
this.all_resources = res.data["resources"]
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.resources {
|
||||
padding: 50px;
|
||||
padding-bottom: 60px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 40px;
|
||||
}
|
||||
</style>
|
11
src/app.html
Normal file
11
src/app.html
Normal file
@ -0,0 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
<div style="display: contents">%sveltekit.body%</div>
|
||||
</body>
|
||||
</html>
|
52
src/lib/card.svelte
Normal file
52
src/lib/card.svelte
Normal file
@ -0,0 +1,52 @@
|
||||
<script>
|
||||
export let title
|
||||
|
||||
let current = ""
|
||||
let i = 0
|
||||
|
||||
while (title.length > i) {
|
||||
let c = title[i]
|
||||
setTimeout(()=>{
|
||||
current += c
|
||||
}, 100*(i+1))
|
||||
i += 1
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="main">
|
||||
<div class="title">
|
||||
root@ngn13.fun:~# {current}
|
||||
</div>
|
||||
<div class="content">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
background: var(--dark-three);
|
||||
box-shadow: var(--box-shadow);
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
.title {
|
||||
background: var(--dark-two);
|
||||
padding: 30px;
|
||||
border-radius: 7px 7px 0px 0px;
|
||||
font-size: 20px;
|
||||
font-family: Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New, monospace;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.content {
|
||||
background: var(--dark-three);
|
||||
padding: 40px;
|
||||
padding-top: 30px;
|
||||
color: white;
|
||||
border-radius: 5px;
|
||||
font-size: 25px;
|
||||
}
|
||||
</style>
|
29
src/lib/header.svelte
Normal file
29
src/lib/header.svelte
Normal file
@ -0,0 +1,29 @@
|
||||
<script></script>
|
||||
|
||||
<header>
|
||||
<h1>
|
||||
<slot></slot>
|
||||
</h1>
|
||||
</header>
|
||||
|
||||
<style>
|
||||
header {
|
||||
background:
|
||||
linear-gradient(rgba(1, 1, 1, 0.96),
|
||||
rgba(11, 11, 11, 0.808)),
|
||||
url("https://files.ngn13.fun/banner.png");
|
||||
background-size: 50%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-weight: 900;
|
||||
font-size: 5.5vw;
|
||||
padding: 120px;
|
||||
text-align: center;
|
||||
color: white;
|
||||
text-shadow: var(--text-shadow);
|
||||
text-size-adjust: 80%;
|
||||
}
|
||||
</style>
|
51
src/lib/navbar.svelte
Normal file
51
src/lib/navbar.svelte
Normal file
@ -0,0 +1,51 @@
|
||||
<script>
|
||||
import NavbarLink from "./navbar_link.svelte";
|
||||
</script>
|
||||
|
||||
<nav>
|
||||
<div>
|
||||
<h3>[ngn]</h3>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<NavbarLink link="/">home</NavbarLink>
|
||||
<NavbarLink link="/projects">projects</NavbarLink>
|
||||
<NavbarLink link="/resources">resources</NavbarLink>
|
||||
<NavbarLink link="/blog">blog</NavbarLink>
|
||||
<NavbarLink link="https://github.com/ngn13/ngn13.fun">source</NavbarLink>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<style>
|
||||
nav {
|
||||
background: var(--dark-one);
|
||||
padding: 25px 30px 27px 25px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-bottom: solid 1.5px 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: 1px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-weight: 900;
|
||||
font-size: 25px;
|
||||
color: red;
|
||||
animation-name: colorAnimation;
|
||||
animation-iteration-count: infinite;
|
||||
animation-duration: 10s;
|
||||
}
|
||||
</style>
|
||||
|
27
src/lib/navbar_link.svelte
Normal file
27
src/lib/navbar_link.svelte
Normal file
@ -0,0 +1,27 @@
|
||||
<script>
|
||||
import { page } from "$app/stores"
|
||||
export let link
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<a href="{link}"><slot></slot></a>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
a {
|
||||
margin-left: 20px;
|
||||
font-weight: 700;
|
||||
font-size: 22px;
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
a: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);
|
||||
}
|
||||
</style>
|
12
src/routes/+layout.svelte
Normal file
12
src/routes/+layout.svelte
Normal file
@ -0,0 +1,12 @@
|
||||
<script>
|
||||
import Navbar from "../lib/navbar.svelte";
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<Navbar />
|
||||
<slot></slot>
|
||||
</main>
|
||||
|
||||
<style>
|
||||
@import "../../static/global.css";
|
||||
</style>
|
63
src/routes/+page.svelte
Normal file
63
src/routes/+page.svelte
Normal file
@ -0,0 +1,63 @@
|
||||
<script>
|
||||
import Header from "../lib/header.svelte";
|
||||
import Card from "../lib/card.svelte";
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>[ngn] | homepage</title>
|
||||
<meta content="[ngn] | Homepage" property="og:title" />
|
||||
<meta content="Homepage of my personal website" property="og:description" />
|
||||
<meta content="https://ngn13.fun" property="og:url" />
|
||||
<meta content="#141414" data-react-helmet="true" name="theme-color" />
|
||||
</svelte:head>
|
||||
|
||||
<Header>
|
||||
<c>echo</c>
|
||||
hello world!
|
||||
</Header>
|
||||
|
||||
<div class="flexbox">
|
||||
<Card title="whoami">
|
||||
👋 Hello! I'm ngn!
|
||||
<ul>
|
||||
<li>🇹🇷 I'm a high school student from Turkey</li>
|
||||
<li>🖥️ I'm interested in cyber security, programming and electronics</li>
|
||||
<li>❤️ I love and support Free/Libre and Open Source Software (FLOSS)</li>
|
||||
<li>🐧 My GNU/Linux distribution of choice is Artix</li>
|
||||
<li>😋 In my free time, I like playing Minecraft</li>
|
||||
</ul>
|
||||
</Card>
|
||||
|
||||
<Card title="pwd">
|
||||
You are currently on my personal website, for all you nerds, here is some
|
||||
techinal details you may want to know:
|
||||
<ul>
|
||||
<li><c> </c> I built the frontend app using SvelteKit
|
||||
<li><c> </c> I deploy my app to vecel using Github actions</li>
|
||||
<li><c> </c> Backend server is written in Go and it's hosted on my server</li>
|
||||
<li><c> </c> And yup, I also have other services hosted on it</li>
|
||||
</ul>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.flexbox {
|
||||
padding: 50px;
|
||||
gap: 30px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
li {
|
||||
padding-top: 15px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1076px) {
|
||||
.flexbox {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
</style>
|
17
src/routes/projects/+page.svelte
Normal file
17
src/routes/projects/+page.svelte
Normal file
@ -0,0 +1,17 @@
|
||||
<script>
|
||||
import Header from "../../lib/header.svelte";
|
||||
</script>
|
||||
|
||||
|
||||
<svelte:head>
|
||||
<title>[ngn] | projects</title>
|
||||
<meta content="[ngn] | Projects" property="og:title" />
|
||||
<meta content="Projects that I work on" property="og:description" />
|
||||
<meta content="https://ngn13.fun" property="og:url" />
|
||||
<meta content="#141414" data-react-helmet="true" name="theme-color" />
|
||||
</svelte:head>
|
||||
<Header><glitch>ls -l</glitch> projects</Header>
|
||||
|
||||
|
||||
|
||||
<style></style>
|
@ -1,64 +1,13 @@
|
||||
/*
|
||||
* this what you would get from google fonts, i downloaded all the fonts and
|
||||
* placed them in static/fonts because google fonts made my website load
|
||||
* slower lol
|
||||
*
|
||||
* you can get the original css at:
|
||||
* https://fonts.googleapis.com/css2?family=Ubuntu:wght@300&display=swap
|
||||
* fonts are located under /static/fonts, they are from nerdfonts
|
||||
* see nerdfonts.com
|
||||
*
|
||||
*/
|
||||
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'Ubuntu';
|
||||
font-family: "Ubuntu";
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
font-display: swap;
|
||||
src: url(./fonts/cyrillic-ext.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
src: url("/fonts/UbuntuNerdFont-Regular.ttf");
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'Ubuntu';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
font-display: swap;
|
||||
src: url(./fonts/cyrillic.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* greek-ext */
|
||||
@font-face {
|
||||
font-family: 'Ubuntu';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
font-display: swap;
|
||||
src: url(./fonts/greek-ext.woff2) format('woff2');
|
||||
unicode-range: U+1F00-1FFF;
|
||||
}
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'Ubuntu';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
font-display: swap;
|
||||
src: url(./fonts/greek.woff2) format('woff2');
|
||||
unicode-range: U+0370-03FF;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Ubuntu';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
font-display: swap;
|
||||
src: url(./fonts/latin-ext.woff2) format('woff2');
|
||||
unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Ubuntu';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
font-display: swap;
|
||||
src: url(./fonts/latin.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
|
BIN
static/fonts/UbuntuNerdFont-Bold.ttf
Normal file
BIN
static/fonts/UbuntuNerdFont-Bold.ttf
Normal file
Binary file not shown.
BIN
static/fonts/UbuntuNerdFont-BoldItalic.ttf
Normal file
BIN
static/fonts/UbuntuNerdFont-BoldItalic.ttf
Normal file
Binary file not shown.
BIN
static/fonts/UbuntuNerdFont-Condensed.ttf
Normal file
BIN
static/fonts/UbuntuNerdFont-Condensed.ttf
Normal file
Binary file not shown.
BIN
static/fonts/UbuntuNerdFont-Italic.ttf
Normal file
BIN
static/fonts/UbuntuNerdFont-Italic.ttf
Normal file
Binary file not shown.
BIN
static/fonts/UbuntuNerdFont-Light.ttf
Normal file
BIN
static/fonts/UbuntuNerdFont-Light.ttf
Normal file
Binary file not shown.
BIN
static/fonts/UbuntuNerdFont-LightItalic.ttf
Normal file
BIN
static/fonts/UbuntuNerdFont-LightItalic.ttf
Normal file
Binary file not shown.
BIN
static/fonts/UbuntuNerdFont-Medium.ttf
Normal file
BIN
static/fonts/UbuntuNerdFont-Medium.ttf
Normal file
Binary file not shown.
BIN
static/fonts/UbuntuNerdFont-MediumItalic.ttf
Normal file
BIN
static/fonts/UbuntuNerdFont-MediumItalic.ttf
Normal file
Binary file not shown.
BIN
static/fonts/UbuntuNerdFont-Regular.ttf
Normal file
BIN
static/fonts/UbuntuNerdFont-Regular.ttf
Normal file
Binary file not shown.
BIN
static/fonts/UbuntuNerdFontPropo-Bold.ttf
Normal file
BIN
static/fonts/UbuntuNerdFontPropo-Bold.ttf
Normal file
Binary file not shown.
BIN
static/fonts/UbuntuNerdFontPropo-BoldItalic.ttf
Normal file
BIN
static/fonts/UbuntuNerdFontPropo-BoldItalic.ttf
Normal file
Binary file not shown.
BIN
static/fonts/UbuntuNerdFontPropo-Condensed.ttf
Normal file
BIN
static/fonts/UbuntuNerdFontPropo-Condensed.ttf
Normal file
Binary file not shown.
BIN
static/fonts/UbuntuNerdFontPropo-Italic.ttf
Normal file
BIN
static/fonts/UbuntuNerdFontPropo-Italic.ttf
Normal file
Binary file not shown.
BIN
static/fonts/UbuntuNerdFontPropo-Light.ttf
Normal file
BIN
static/fonts/UbuntuNerdFontPropo-Light.ttf
Normal file
Binary file not shown.
BIN
static/fonts/UbuntuNerdFontPropo-LightItalic.ttf
Normal file
BIN
static/fonts/UbuntuNerdFontPropo-LightItalic.ttf
Normal file
Binary file not shown.
BIN
static/fonts/UbuntuNerdFontPropo-Medium.ttf
Normal file
BIN
static/fonts/UbuntuNerdFontPropo-Medium.ttf
Normal file
Binary file not shown.
BIN
static/fonts/UbuntuNerdFontPropo-MediumItalic.ttf
Normal file
BIN
static/fonts/UbuntuNerdFontPropo-MediumItalic.ttf
Normal file
Binary file not shown.
BIN
static/fonts/UbuntuNerdFontPropo-Regular.ttf
Normal file
BIN
static/fonts/UbuntuNerdFontPropo-Regular.ttf
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -666,7 +666,7 @@
|
||||
.markdown-body span.float-left span {
|
||||
margin: 13px 0 0;
|
||||
}
|
||||
|
||||
https://github.com/ngn13/ngn13.fun/raw/main/static/fonts/latin.woff2
|
||||
.markdown-body span.float-right {
|
||||
display: block;
|
||||
float: right;
|
||||
|
@ -1,12 +1,12 @@
|
||||
@import url("./font.css");
|
||||
@import url("./github.css");
|
||||
@import "./font.css";
|
||||
@import "./github.css";
|
||||
|
||||
:root {
|
||||
--white: white;
|
||||
--dark-one: #141414;
|
||||
--dark-two: #18191a;
|
||||
--dark-three: #282828;
|
||||
--dark-four: #242526;
|
||||
--dark-one: black;
|
||||
--dark-two: #050505;
|
||||
--dark-three: #121212;
|
||||
--dark-four: #101010;
|
||||
--dark-fife: #3a3b3c;
|
||||
--border-rad: 30px;
|
||||
/*
|
||||
@ -15,7 +15,8 @@
|
||||
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;
|
||||
*/
|
||||
--def-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
|
||||
--text-shadow: 0px 10px 20px rgba(90, 90, 90, 0.8);
|
||||
--box-shadow: rgba(20, 20, 20, 0.19) 0px 10px 20px, rgba(30, 30, 30, 0.23) 0px 6px 6px;
|
||||
}
|
||||
|
||||
* {
|
||||
@ -30,7 +31,7 @@ body {
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
background: #141414;
|
||||
background: var(--dark-one);
|
||||
font-family: "Ubuntu", sans-serif;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
@ -295,9 +296,8 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
.glitch {
|
||||
c {
|
||||
animation-name: colorAnimation;
|
||||
animation-iteration-count: infinite;
|
||||
animation-duration: 10s;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
13
svelte.config.js
Normal file
13
svelte.config.js
Normal file
@ -0,0 +1,13 @@
|
||||
import adapter from '@sveltejs/adapter-auto';
|
||||
|
||||
/** @type {import('@sveltejs/kit').Config} */
|
||||
const config = {
|
||||
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()
|
||||
}
|
||||
};
|
||||
|
||||
export default config;
|
6
vite.config.js
Normal file
6
vite.config.js
Normal file
@ -0,0 +1,6 @@
|
||||
import { sveltekit } from '@sveltejs/kit/vite';
|
||||
import { defineConfig } from 'vite';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [sveltekit()]
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user