Compare commits

..

No commits in common. "master" and "development" have entirely different histories.

21 changed files with 4954 additions and 9749 deletions

@ -14,14 +14,14 @@ on:
jobs:
docker:
runs-on: ubuntu-22.04
runs-on: ubuntu-20.04
steps:
- name: Get branch name
id: branch-name
uses: tj-actions/branch-names@v8
uses: tj-actions/branch-names@v7
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
- name: Restore Docker Cache
uses: actions/cache@v3
@ -39,10 +39,10 @@ jobs:
echo "Done"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v2
- name: Login to Repo
uses: docker/login-action@v3
uses: docker/login-action@v2
with:
username: ${{ secrets.REPO_USERNAME }}
password: ${{ secrets.REPO_TOKEN }}
@ -55,7 +55,7 @@ jobs:
key: ${{ runner.os }}-buildx
- name: Build and Push (Latest)
uses: docker/build-push-action@v5
uses: docker/build-push-action@v4
if: steps.branch-name.outputs.current_branch == 'master'
with:
push: true
@ -65,7 +65,7 @@ jobs:
cache-to: type=local,dest=/tmp/.buildx-cache
- name: Build and Push (Other Branches)
uses: docker/build-push-action@v5
uses: docker/build-push-action@v4
if: steps.branch-name.outputs.current_branch != 'master'
with:
push: true

2
.gitignore vendored

@ -145,4 +145,4 @@ dist
.pnp.*
# Config
config.yml
config.json

@ -1,12 +1,15 @@
FROM fascinated/docker-images:node-pnpm-latest
FROM node:lts-slim
ENV NODE_ENV=production
WORKDIR /usr/src/app
RUN apt update
RUN DEBIAN_FRONTEND=noninteractive apt install wget -y
# Copy package.json and package-lock.json separately to fully utilize Docker layer caching
COPY package.json ./
COPY pnpm-lock.yaml ./
RUN pnpm install --production --silent
COPY package-lock.json ./
RUN npm ci --production --silent && npm cache clean --force
# Opt out of Next.js telemetry
RUN npx next telemetry disable
@ -14,6 +17,9 @@ RUN npx next telemetry disable
# Copy the rest of the files
COPY . .
# Remove development dependencies
RUN npm prune --production
# Environment Variables
ENV NODE_ENV=production

104
README.md

@ -29,10 +29,6 @@ Simple Links is a lightweight alternative to Linktree and others.
3. Run `docker compose up -d`
4. The application is now updated
## Support
If you need any help, you can contact me on my Discord server [here](https://discord.gg/yjj2U3ctEG) or open a issue!
## What if I don't want buttons or icon only links?
Just simply remove it from the config and it will not show anymore
@ -40,3 +36,103 @@ Just simply remove it from the config and it will not show anymore
## Showing Discord status
You must be in the [lanyard server](https://discord.gg/UrXF2cfJ7F) for it to work.
## Help!!! I'm getting an error when launching it
### Config Issue
If your error looks similar to this you are most likely missing part of the config, as some new things may have been added.
```bash
simple-links | Type error: Property 'theme' does not exist on type '{ name: string; description: string; avatar: string; background: { showBackground: boolean; blur: boolean; darken: { enabled: boolean; amount: number; }; backgroundImage: string; }; infoCard: { transparency: number; }; metadata: { ...; }; options: { ...; }; analytics: { ...; }; links: { ...; }[]; }'.
```
## Config Example
```json
{
"name": "Your Name", // The name you want to display on the site
"description": "A description about yourself", // The description you want to use
"avatar": "https://cdn.fascinated.cc/KWprz2.jpg", // The avatar that is shown at the top of the site
// or use a local image
"avatar": "/avatar.webp",
// If you want to use a custom (not dark) background
"background": {
"showBackground": true, // Whether it is enabled or not
"blur": true, // Should we blur the background?
"darken": {
// Should we darken the background?
"enabled": true,
"amount": 0.7
},
"backgroundImage": "https://cdn.fascinated.cc/8twdW8.jpg", // The image to use in the background
// or use a local image
"backgroundImage": "/background.jpg"
},
"theme": "dark", // "dark" or "light" themes
// The card that displays your info and buttons
"infoCard": {
"transparency": 0.85 // How transparent should it be?
},
// Website options
"options": {
"showSourceLink": true // Should we show the "Source Code" link
},
// Show your discord status on the site (You MUST be in the Lanyard server)
// https://discord.gg/UrXF2cfJ7F
"discord": {
"id": "474221560031608833" // Your discord ID
},
// Search engine and embedding metadata (discord, twitter, etc embeds)
"metadata": {
"title": "Your Name", // The title of the embed
"description": "website description", // The description of the embed
"themeColor": "#6441a5", // The color of the embed
"authors": [
// SEO metadata
{
"name": "Fascinated",
"url": "https://fascinated.cc"
}
]
},
// The buttons to show links for
"links": [
{
"title": "Git", // The shown title of the button
"url": "https://git.fascinated.cc", // Where the button goes to when clicked
"icon": "fab fa-github", // The icon of the button (can be removed to show no icon)
// The color of the icon (tailwindcss colors)
"color": "bg-green-700"
},
{
"title": "Twitch",
"url": "https://twitch.tv/fascinated_",
"icon": "fab fa-twitch",
"color": "bg-[#6441a5]"
},
{
"title": "Documentation",
"url": "https://docs.fascinated.cc",
"color": "bg-neutral-700"
}
],
// Icon only links
"socialLinks": [
{
"icon": "fab fa-twitter", // The icon to use
"color": "#1DA1F2", // An optional color
"url": "https://twitter.com" // The link to go to
},
{
"icon": "fab fa-reddit",
"color": "#FF4300",
"url": "https://www.reddit.com/user/ImFascinatedMC"
},
{
"icon": "fab fa-git-alt",
"url": "https://git.fascinated.cc"
}
]
}
```

73
config-example.json Normal file

@ -0,0 +1,73 @@
{
"configVersion": "0.1.4",
"name": "Your Name",
"description": "A description about yourself",
"avatar": "/avatar.webp",
"background": {
"showBackground": true,
"blur": true,
"darken": {
"enabled": true,
"amount": 0.7
},
"backgroundImage": "/background.jpg"
},
"theme": "dark",
"infoCard": {
"transparency": 0.85
},
"discord": {
"id": "set me"
},
"options": {
"showSourceLink": true
},
"metadata": {
"title": "Your Name",
"description": "website description",
"themeColor": "#6441a5",
"authors": [
{
"name": "Fascinated",
"url": "https://fascinated.cc"
}
]
},
"links": [
{
"title": "Git",
"url": "https://git.fascinated.cc",
"icon": "fab fa-git-alt",
"color": {
"normal": "bg-green-700"
}
},
{
"title": "Twitch",
"url": "https://twitch.tv/fascinated_",
"icon": "fab fa-twitch",
"color": "bg-[#6441a5]"
},
{
"title": "Documentation",
"url": "https://docs.fascinated.cc",
"color": "bg-neutral-700"
}
],
"socialLinks": [
{
"icon": "fab fa-twitter",
"color": "#1DA1F2",
"url": "https://twitter.com"
},
{
"icon": "fab fa-reddit",
"color": "#FF4300",
"url": "https://www.reddit.com/user/ImFascinatedMC"
},
{
"icon": "fab fa-git-alt",
"url": "https://git.fascinated.cc"
}
]
}

@ -1,75 +0,0 @@
# The version of the config (DO NOT CHANGE)
configVersion: "0.2.0"
# Your name to show in the info card
name: "Your Name"
# The description shown in the info card
description: "A description about yourself"
# The avatar to show
avatar: "/avatar.webp"
# Background configuration
background:
# Should we use a custom background?
showBackground: true
# Should we blur that background?
blur: true
# Should we darken that background? and by how much
darken:
enabled: true
amount: 0.7
# The image to show when the background is enabled
backgroundImage: "/background.jpg"
# The theme to use (light or dark)
theme: "dark"
# The info card settings
infoCard:
# How transparent should it be?
transparency: 0.85
# Discord settings (Status indicator)
discord:
# Your discord id
id: "set me"
# Global settings for the site
options:
# Should we show the "Website Source" button?
showSourceLink: true
# Metadata for the website (controls embed settings and SEO info)
# see: https://nextjs.org/docs/app/api-reference/file-conventions/metadata/opengraph-image
metadata:
title: "Your Name"
description: "website description"
themeColor: "#6441a5"
authors:
- name: "Fascinated"
url: "https://fascinated.cc"
# The links to show (buttons)
links:
# The title of the button
- title: "Git"
# Where the button goes to
url: "https://git.fascinated.cc"
# The icon of the button
# see: https://fontawesome.com/search
icon: "fab fa-git-alt"
# The color of the button (TailwindCSS colors or hex color, see below for hex)
color: "bg-green-700"
- title: "Twitch"
url: "https://twitch.tv/fascinated_"
icon: "fab fa-twitch"
color: "bg-[#6441a5]"
- title: "Documentation"
url: "https://docs.fascinated.cc"
color: "bg-neutral-700"
# The links to show (icons only, below buttons)
socialLinks:
# The icon to use
# see: https://fontawesome.com/search
- icon: "fab fa-twitter"
# The color of the icon
color: "#1DA1F2"
# Where the icon goes to when clicked
url: "https://twitter.com"
- icon: "fab fa-reddit"
color: "#FF4300"
url: "https://www.reddit.com/user/ImFascinatedMC"
- icon: "fab fa-git-alt"
url: "https://git.fascinated.cc"

@ -13,5 +13,5 @@ services:
ports:
- 3000:3000
volumes:
- ./config.yml:/usr/src/app/config.yml:ro # The application config (Must be created before starting the service)
- ./config.json:/usr/src/app/config.json:ro # The application config (Must be created before starting the service)
- ./public:/usr/src/app/public:rw # Used for public facing images (eg: avatar and background)

@ -1,5 +1,3 @@
const withYaml = require("next-plugin-yaml");
/** @type {import('next').NextConfig} */
const nextConfig = {
images: {
@ -14,4 +12,4 @@ const nextConfig = {
},
};
module.exports = withYaml(nextConfig);
module.exports = nextConfig;

4697
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

@ -1,35 +1,32 @@
{
"name": "simple-links",
"version": "0.2.1",
"version": "0.1.9",
"private": false,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next build && next start",
"lint": "next lint",
"update-depends": "npm-check -u"
"lint": "next lint"
},
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^6.6.0",
"@fortawesome/free-brands-svg-icons": "^6.6.0",
"@fortawesome/free-regular-svg-icons": "^6.6.0",
"@fortawesome/free-solid-svg-icons": "^6.6.0",
"@fortawesome/react-fontawesome": "^0.2.2",
"@types/node": "^22.5.1",
"@types/react": "^18.3.4",
"@types/react-dom": "^18.3.0",
"autoprefixer": "^10.4.20",
"eslint": "^9.9.1",
"eslint-config-next": "^14.2.7",
"next": "^14.2.7",
"next-plugin-yaml": "^1.0.1",
"npm-check": "^6.0.1",
"postcss": "^8.4.41",
"react": "18.3.1",
"react-dom": "18.3.1",
"sharp": "^0.33.5",
"tailwindcss": "^3.4.10",
"typescript": "^5.5.4",
"use-lanyard": "^1.5.2"
"@fortawesome/fontawesome-svg-core": "^6.4.0",
"@fortawesome/free-brands-svg-icons": "^6.4.0",
"@fortawesome/free-regular-svg-icons": "^6.4.0",
"@fortawesome/free-solid-svg-icons": "^6.4.0",
"@fortawesome/react-fontawesome": "^0.2.0",
"@types/node": "20.4.1",
"@types/react": "18.2.14",
"@types/react-dom": "18.2.6",
"autoprefixer": "10.4.14",
"eslint": "8.44.0",
"eslint-config-next": "13.4.9",
"next": "13.4.9",
"postcss": "8.4.25",
"react": "18.2.0",
"react-dom": "18.2.0",
"sharp": "^0.32.2",
"tailwindcss": "3.3.2",
"typescript": "5.1.6",
"use-lanyard": "^1.4.4"
}
}

4676
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

@ -1,6 +0,0 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"local>Fascinated/renovate-config"
]
}

@ -1,11 +1,10 @@
"use client";
import { Config } from "@/src/types/config";
import Image from "next/image";
import { Fragment } from "react";
import { useLanyardWS } from "use-lanyard";
const config: Config = require("../../../config.yml") as any;
import Config from "../../../config.json";
function LanyardWrapper(props: { children: any }) {
return <Fragment>{props.children}</Fragment>;
@ -13,7 +12,7 @@ function LanyardWrapper(props: { children: any }) {
export default function Avatar(props: any) {
const { avatar } = props;
const { discord }: any = config;
const { discord }: any = Config;
return (
<div className="relative inline-block">
@ -40,10 +39,10 @@ function LanyardComponent(props: { discord: any }) {
const hasLanyard = lanyardData !== undefined;
const statusColor = {
online: "bg-[#43B581]",
offline: "bg-transparent",
dnd: "bg-[#F04747]",
idle: "bg-[#FAA61A]",
online: "bg-green-400",
offline: "bg-slate-400",
dnd: "bg-red-500",
idle: "bg-orange-400",
};
const currentStatus =
lanyardData !== undefined

@ -1,18 +1,20 @@
import { Config } from "@/src/types/config";
import { config as fontAwesomeConfig } from "@fortawesome/fontawesome-svg-core";
import { config } from "@fortawesome/fontawesome-svg-core";
import "@fortawesome/fontawesome-svg-core/styles.css";
import { Inter } from "next/font/google";
import "./globals.css";
import { ReactNode } from "react";
const config: Config = require("../../config.yml") as any;
fontAwesomeConfig.autoAddCss = false;
import Config from "../../config.json";
config.autoAddCss = false;
const inter = Inter({ subsets: ["latin"] });
export const metadata = config.metadata; // Site metadata from the config
export const metadata = Config.metadata; // Site metadata from the config
export default function RootLayout({ children }: { children: ReactNode }) {
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body className={inter.className}>{children}</body>

@ -1,15 +1,12 @@
import { Config } from "@/src/types/config";
import { library } from "@fortawesome/fontawesome-svg-core";
import { fab } from "@fortawesome/free-brands-svg-icons";
import { far } from "@fortawesome/free-regular-svg-icons";
import { fas } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import Image from "next/image";
import Link from "next/link";
import Config from "../../config.json";
import Avatar from "./components/Avatar";
const config: Config = require("../../config.yml") as any;
library.add(fab, far, fas); // Loading in the icons from FontAwesome
export default function Home() {
@ -23,7 +20,7 @@ export default function Home() {
options,
description,
theme,
} = config; // All the settings pulled from the config file
} = Config; // All of the settings pulled from the config file
// Theme colors to use when using the selected theme
// all used colors are from TailwindCSS
@ -54,26 +51,29 @@ export default function Home() {
const selectedTheme = themeColors[theme] || themeColors.dark; // The theme to use (fallback of dark)
return (
<div className={"relative"}>
{/* Background Image */}
{background.showBackground && background.backgroundImage && (
// eslint-disable-next-line @next/next/no-img-element
<img
alt="Background image"
src={background.backgroundImage}
className={`absolute z-0 object-cover w-full h-full ${background.blur && "blur-sm"} brightness-${background.darken.enabled && background.darken.amount / 2}`}
/>
)}
<>
<main
className={`flex flex-col items-center justify-center w-screen h-screen ${selectedTheme.backgroundColor} ${selectedTheme.textColor}`}
>
{/* Info Card */}
{/* Background Image */}
{background.showBackground && background.backgroundImage && (
<Image
alt="Background image"
src={background.backgroundImage}
fill={true}
style={{
zIndex: 0,
filter: `${background.blur && "blur(4px)"} brightness(${
background.darken.enabled && background.darken.amount / 2
})`,
}}
/>
)}
<div
className={`${infoCard.transparency != 0 && `${selectedTheme.infoCardColor} shadow-lg rounded-lg`} text-center`}
className={`${selectedTheme.infoCardColor} rounded-lg text-center shadow-lg`}
style={{
zIndex: 1,
opacity: infoCard.transparency != 0 ? infoCard.transparency : 1,
opacity: infoCard.transparency,
}}
>
<div className="m-5">
@ -106,13 +106,7 @@ export default function Home() {
target="_blank"
rel="noopener noreferrer"
className={`flex flex-row items-center justify-center mt-4 px-4 w-60 py-2 rounded
${selectedTheme.buttonTextColor} ${color} hover:brightness-75 transition gap-2 shadow-lg`}
style={{
opacity:
infoCard.transparency != 0
? infoCard.transparency
: 0.8,
}}
${selectedTheme.buttonTextColor} ${color} hover:brightness-75 transition gap-2`}
>
{link.icon && <FontAwesomeIcon icon={icons} />}
<p>{link.title}</p>
@ -133,13 +127,7 @@ export default function Home() {
href={link.url}
target="_blank"
rel="noopener noreferrer"
className="hover:brightness-75 transition shadow-lg"
style={{
opacity:
infoCard.transparency != 0
? infoCard.transparency
: 0.8,
}}
className="hover:brightness-75 transition"
>
{link.icon && (
<FontAwesomeIcon
@ -160,21 +148,16 @@ export default function Home() {
className={`absolute bottom-0 right-0 mb-5 mr-5 ${selectedTheme.footerTextColor}`}
>
{options.showSourceLink && (
<Link
<a
href="https://git.fascinated.cc/Fascinated/simple-links"
target="_blank"
className="mt-5"
>
<Image
src="https://cdn.fascinated.cc/assets/simple-links/icon.png"
alt="Simple Links Icon"
width={32}
height={32}
/>
</Link>
Website Source
</a>
)}
</div>
</main>
</div>
</>
);
}

55
src/types/config.d.ts vendored

@ -1,55 +0,0 @@
export interface Config {
configVersion: string;
name: string;
description: string;
avatar: string;
background: {
showBackground: boolean;
blur: boolean;
darken: {
enabled: boolean;
amount: number;
};
backgroundImage: string;
};
theme: string;
infoCard: {
transparency: number;
};
discord: {
id: string;
};
options: {
showSourceLink: boolean;
};
metadata: {
title: string;
description: string;
themeColor: string;
authors: {
name: string;
url: string;
}[];
};
links: {
title: string;
url: string;
icon: string;
color:
| {
normal: string;
}
| string;
}[];
socialLinks: {
icon: string;
color: string;
url: string;
}[];
}
// Parse the YAML content and convert it to the defined type
declare module "*.yml" {
const content: any;
export default content;
}

@ -1,7 +1,7 @@
workDir=/usr/src/app
baseUrl=https://git.fascinated.cc/Fascinated/simple-links/raw/branch/master/public/
toDownload=("avatar.webp" "background.jpg" "favicon.ico")
toDownload=("avatar.webp" "background.jpg")
echo "Checking if files need to be downloaded"
if [ -z "$(ls -A $workDir/public)" ]; then

@ -4,7 +4,7 @@ module.exports = {
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
"./config.yml",
"./config.json",
],
theme: {},
plugins: [],

@ -21,16 +21,8 @@
],
"paths": {
"@/*": ["./*"]
},
"typeRoots": ["./src/types", "./node_modules/@types"],
"types": ["node"]
}
},
"include": [
"next-env.d.ts",
"src/types/**/*.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts"
],
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}

4826
yarn.lock

File diff suppressed because it is too large Load Diff