initial commit
This commit is contained in:
commit
0f94d1300e
18 changed files with 947 additions and 0 deletions
44
.gitignore
vendored
Normal file
44
.gitignore
vendored
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnp
|
||||||
|
.pnp.*
|
||||||
|
.yarn/*
|
||||||
|
!.yarn/patches
|
||||||
|
!.yarn/plugins
|
||||||
|
!.yarn/releases
|
||||||
|
!.yarn/versions
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# next.js
|
||||||
|
/.next/
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
*.pem
|
||||||
|
|
||||||
|
# debug
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
.pnpm-debug.log*
|
||||||
|
|
||||||
|
# env files (can opt-in for committing if needed)
|
||||||
|
.env*
|
||||||
|
|
||||||
|
# vercel
|
||||||
|
.vercel
|
||||||
|
|
||||||
|
# typescript
|
||||||
|
*.tsbuildinfo
|
||||||
|
next-env.d.ts
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun.lock*
|
24
LICENSE
Normal file
24
LICENSE
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
This is free and unencumbered software released into the public domain.
|
||||||
|
|
||||||
|
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||||
|
distribute this software, either in source code form or as a compiled
|
||||||
|
binary, for any purpose, commercial or non-commercial, and by any
|
||||||
|
means.
|
||||||
|
|
||||||
|
In jurisdictions that recognize copyright laws, the author or authors
|
||||||
|
of this software dedicate any and all copyright interest in the
|
||||||
|
software to the public domain. We make this dedication for the benefit
|
||||||
|
of the public at large and to the detriment of our heirs and
|
||||||
|
successors. We intend this dedication to be an overt act of
|
||||||
|
relinquishment in perpetuity of all present and future rights to this
|
||||||
|
software under copyright law.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||||
|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
For more information, please refer to <https://unlicense.org/>
|
36
README.md
Normal file
36
README.md
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
First, run the development server:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
# or
|
||||||
|
yarn dev
|
||||||
|
# or
|
||||||
|
pnpm dev
|
||||||
|
# or
|
||||||
|
bun dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||||
|
|
||||||
|
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
|
||||||
|
|
||||||
|
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
|
||||||
|
|
||||||
|
## Learn More
|
||||||
|
|
||||||
|
To learn more about Next.js, take a look at the following resources:
|
||||||
|
|
||||||
|
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
||||||
|
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
||||||
|
|
||||||
|
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
|
||||||
|
|
||||||
|
## Deploy on Vercel
|
||||||
|
|
||||||
|
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
||||||
|
|
||||||
|
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
|
85
app/about/page.tsx
Normal file
85
app/about/page.tsx
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
import { Nav } from "@/components/core/nav";
|
||||||
|
import { GiStoneWheel } from "react-icons/gi";
|
||||||
|
import { TbUserSquareRounded } from "react-icons/tb";
|
||||||
|
import { RiTelegram2Line } from "react-icons/ri";
|
||||||
|
|
||||||
|
export default function About() {
|
||||||
|
return (
|
||||||
|
<main>
|
||||||
|
<Nav />
|
||||||
|
<div className="flex flex-col items-center justify-between gap-3 my-20">
|
||||||
|
<div className="flex flex-row items-center justify-between gap-2">
|
||||||
|
<TbUserSquareRounded size={36} />
|
||||||
|
<h1 className="text-4xl font-bold">
|
||||||
|
About
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col items-center justify-between gap-3">
|
||||||
|
<h2 className="text-2xl font-semibold text-center w-full flex flex-wrap items-center justify-center">
|
||||||
|
p0ntus is a small team of developers working towards
|
||||||
|
<span className="bg-red-400 text-white rounded-full italic ml-2 px-3 pr-4 py-1">one goal</span>.
|
||||||
|
</h2>
|
||||||
|
<h2 className="text-xl text-center w-full flex flex-wrap items-center justify-center">
|
||||||
|
we want to make the cloud accessible to <span className="ml-1 italic">everyone</span>.
|
||||||
|
</h2>
|
||||||
|
<h2 className="text-lg text-center w-full flex flex-wrap items-center justify-center">
|
||||||
|
no corporate sponsors, no closed source, no microtransactions.
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col items-center justify-between gap-3 my-20">
|
||||||
|
<div className="flex flex-col items-center justify-between gap-3">
|
||||||
|
<GiStoneWheel size={60} />
|
||||||
|
<h2 className="text-3xl font-semibold text-center w-full flex flex-wrap items-center justify-center">
|
||||||
|
we don't reinvent the wheel,
|
||||||
|
</h2>
|
||||||
|
<h2 className="text-2xl text-center w-full flex flex-wrap items-center justify-center">
|
||||||
|
but we get the job done.
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col items-center justify-between gap-3 my-2 max-w-3xl">
|
||||||
|
<p className="text-md text-center w-full flex flex-wrap items-center justify-center">
|
||||||
|
we put effort into finding, creating, and building on the best tools avaliable to bring the magic of the cloud to you.
|
||||||
|
</p>
|
||||||
|
<p className="text-md text-center w-full flex flex-wrap items-center justify-center">
|
||||||
|
we believe using cloud services is <span className="ml-1 italic">more than just a way to store your data.</span>
|
||||||
|
<span className="font-bold">your experience should be valued.</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col items-center justify-between gap-3 my-20">
|
||||||
|
<div className="flex flex-col items-center justify-between gap-3">
|
||||||
|
<RiTelegram2Line size={60} />
|
||||||
|
<h2 className="text-3xl font-semibold text-center w-full flex flex-wrap items-center justify-center">
|
||||||
|
let's talk.
|
||||||
|
</h2>
|
||||||
|
<div className="flex flex-col items-center justify-between gap-2">
|
||||||
|
<p className="text-md text-center w-full flex flex-wrap items-center justify-center">
|
||||||
|
we're always looking for new people to help out.
|
||||||
|
</p>
|
||||||
|
<p className="text-md text-center w-full flex flex-wrap items-center justify-center">
|
||||||
|
we're here for everything else, too! account support, deployment, service, and more.
|
||||||
|
</p>
|
||||||
|
<p className="text-md text-center w-full flex flex-wrap items-center justify-center">
|
||||||
|
join us on telegram for support, questions, chatting, and more.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-row items-center justify-center gap-4 my-3">
|
||||||
|
<button className="flex flex-row items-center justify-center gap-2 bg-blue-500 text-white px-4 py-2 rounded-md">
|
||||||
|
<RiTelegram2Line size={24} />
|
||||||
|
<span className="text-md">
|
||||||
|
contact
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
<button className="flex flex-row items-center justify-center gap-2 bg-blue-500 text-white px-4 py-2 rounded-md">
|
||||||
|
<RiTelegram2Line size={24} />
|
||||||
|
<span className="text-md">
|
||||||
|
join group
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
26
app/globals.css
Normal file
26
app/globals.css
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
@import "tailwindcss";
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--background: #ffffff;
|
||||||
|
--foreground: #171717;
|
||||||
|
}
|
||||||
|
|
||||||
|
@theme inline {
|
||||||
|
--color-background: var(--background);
|
||||||
|
--color-foreground: var(--foreground);
|
||||||
|
--font-sans: var(--font-geist-sans);
|
||||||
|
--font-mono: var(--font-geist-mono);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
:root {
|
||||||
|
--background: #0a0a0a;
|
||||||
|
--foreground: #ededed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background: var(--background);
|
||||||
|
color: var(--foreground);
|
||||||
|
font-family: var(--font-geist-sans);
|
||||||
|
}
|
34
app/layout.tsx
Normal file
34
app/layout.tsx
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
import { Geist, Geist_Mono } from "next/font/google";
|
||||||
|
import "./globals.css";
|
||||||
|
|
||||||
|
const geistSans = Geist({
|
||||||
|
variable: "--font-geist-sans",
|
||||||
|
subsets: ["latin"],
|
||||||
|
});
|
||||||
|
|
||||||
|
const geistMono = Geist_Mono({
|
||||||
|
variable: "--font-geist-mono",
|
||||||
|
subsets: ["latin"],
|
||||||
|
});
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: "p0ntus",
|
||||||
|
description: "p0ntus is a free and open set of services for the public",
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function RootLayout({
|
||||||
|
children,
|
||||||
|
}: Readonly<{
|
||||||
|
children: React.ReactNode;
|
||||||
|
}>) {
|
||||||
|
return (
|
||||||
|
<html lang="en">
|
||||||
|
<body
|
||||||
|
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
}
|
94
app/page.tsx
Normal file
94
app/page.tsx
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
import Link from "next/link";
|
||||||
|
import { SiForgejo, SiJellyfin, SiOllama } from "react-icons/si";
|
||||||
|
import { TbMail, TbKey, TbServer, TbArrowRight } from "react-icons/tb";
|
||||||
|
import { Nav } from "@/components/core/nav";
|
||||||
|
|
||||||
|
export default function Home() {
|
||||||
|
return (
|
||||||
|
<main>
|
||||||
|
<Nav />
|
||||||
|
<div className="flex flex-col items-center justify-between gap-3 my-20">
|
||||||
|
<h1 className="text-4xl font-bold">
|
||||||
|
p0ntus
|
||||||
|
</h1>
|
||||||
|
<h3 className="text-2xl">
|
||||||
|
open source at your fingertips
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<hr className="border-black mt-24 mb-24" />
|
||||||
|
<div className="max-w-6xl mx-auto w-full px-4 md:px-10">
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-x-38 gap-y-16">
|
||||||
|
<div className="flex flex-col items-center justify-start gap-6 h-full">
|
||||||
|
<h2 className="text-3xl font-bold text-center w-full whitespace-nowrap">Services</h2>
|
||||||
|
<h3 className="text-xl italic text-center w-full">what can we offer you?</h3>
|
||||||
|
<div className="grid grid-cols-3 gap-10 my-8">
|
||||||
|
<div className="flex flex-col items-center justify-center gap-3">
|
||||||
|
<Link href="/services/git" className="flex flex-col items-center gap-2">
|
||||||
|
<SiForgejo size={50} />
|
||||||
|
<h3 className="text-lg font-bold">git</h3>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col items-center justify-center gap-3">
|
||||||
|
<Link href="/services/mail" className="flex flex-col items-center gap-2">
|
||||||
|
<TbMail size={50} />
|
||||||
|
<h3 className="text-lg font-bold">mail</h3>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col items-center justify-center gap-3">
|
||||||
|
<Link href="/services/ai" className="flex flex-col items-center gap-2">
|
||||||
|
<SiOllama size={50} />
|
||||||
|
<h3 className="text-lg font-bold">ai</h3>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col items-center justify-center gap-3">
|
||||||
|
<Link href="/services/tv" className="flex flex-col items-center gap-2">
|
||||||
|
<SiJellyfin size={50} />
|
||||||
|
<h3 className="text-lg font-bold">tv</h3>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col items-center justify-center gap-3">
|
||||||
|
<Link href="/services/keybox" className="flex flex-col items-center gap-2">
|
||||||
|
<TbKey size={50} />
|
||||||
|
<h3 className="text-lg font-bold">keybox</h3>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col items-center justify-center gap-3">
|
||||||
|
<Link href="/services/keybox" className="flex flex-col items-center gap-2">
|
||||||
|
<TbServer size={50} />
|
||||||
|
<h3 className="text-lg font-bold">hosting</h3>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col items-center justify-start gap-6 h-full">
|
||||||
|
<h2 className="text-3xl font-bold text-center w-full whitespace-nowrap">Where we are</h2>
|
||||||
|
<h3 className="text-xl italic text-center w-full">how can you find us?</h3>
|
||||||
|
<div className="flex flex-col items-center gap-6 mt-6">
|
||||||
|
<p className="text-lg text-center">
|
||||||
|
p0ntus is fully on the public internet! our servers are mainly located in the united states.
|
||||||
|
</p>
|
||||||
|
<p className="text-lg text-center">
|
||||||
|
we also operate servers in the united states, canada and germany.
|
||||||
|
</p>
|
||||||
|
<Link href="/servers" className="flex flex-row items-center gap-2 text-lg text-center text-blue-500 hover:underline">
|
||||||
|
our servers <TbArrowRight size={20} />
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col items-center justify-start gap-6 h-full">
|
||||||
|
<h2 className="text-3xl font-bold text-center w-full whitespace-nowrap">Why is p0ntus free?</h2>
|
||||||
|
<h3 className="text-xl italic text-center w-full">what's the point?</h3>
|
||||||
|
<div className="flex flex-col items-center gap-6 mt-6">
|
||||||
|
<p className="text-lg text-center">
|
||||||
|
everything today includes microtransactions, and we were fed up with it.
|
||||||
|
</p>
|
||||||
|
<p className="text-lg text-center">
|
||||||
|
p0ntus exists to show that it is possible to have a free and open set of services that people have fun using.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
130
app/servers/page.tsx
Normal file
130
app/servers/page.tsx
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
import { Nav } from "@/components/core/nav";
|
||||||
|
import { TbServer } from "react-icons/tb";
|
||||||
|
import Flag from 'react-world-flags';
|
||||||
|
|
||||||
|
export default function Servers() {
|
||||||
|
return (
|
||||||
|
<main>
|
||||||
|
<Nav />
|
||||||
|
<div className="flex flex-col items-center justify-between gap-3 my-20">
|
||||||
|
<div className="flex flex-row items-center justify-between gap-2">
|
||||||
|
<TbServer size={36} />
|
||||||
|
<h1 className="text-4xl font-bold">
|
||||||
|
servers and infrastructure
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col items-center justify-between gap-3 my-20">
|
||||||
|
<h2 className="text-2xl font-semibold text-center w-full flex flex-wrap items-center justify-center">
|
||||||
|
where we host out of
|
||||||
|
</h2>
|
||||||
|
<div className="grid grid-cols-3 gap-4 my-4">
|
||||||
|
<p className="flex flex-row items-center justify-between gap-2 text-lg bg-blue-400 text-white px-4 py-2 rounded-full">
|
||||||
|
<Flag code="US" className="w-6 h-6" /> usa
|
||||||
|
</p>
|
||||||
|
<p className="flex flex-row items-center justify-between gap-2 text-lg bg-red-400 text-white px-4 py-2 rounded-full">
|
||||||
|
<Flag code="CA" className="w-6 h-6" /> canada
|
||||||
|
</p>
|
||||||
|
<p className="flex flex-row items-center justify-between gap-2 text-lg bg-orange-400 text-white px-4 py-2 rounded-full">
|
||||||
|
<Flag code="DE" className="mr-4 w-6 h-6" /> germany
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col items-center justify-between gap-3">
|
||||||
|
<h2 className="text-2xl font-semibold text-center w-full flex flex-wrap items-center justify-center">
|
||||||
|
hardware
|
||||||
|
</h2>
|
||||||
|
<div className="grid grid-cols-3 gap-4 my-4 w-5xl">
|
||||||
|
<div className="flex flex-col gap-2 text-lg bg-blue-400 text-white px-8 py-8 rounded-4xl">
|
||||||
|
<div className="flex flex-row items-center justify-between gap-2">
|
||||||
|
<TbServer size={36} />
|
||||||
|
<span className="text-2xl font-bold">
|
||||||
|
NY-1
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<p className="flex flex-col text-sm my-2 gap-4">
|
||||||
|
<span><span className="font-bold">CPU:</span> 2x Intel Xeon E5-2699 v4 @ 3.60 GHz</span>
|
||||||
|
<span><span className="font-bold">RAM:</span> 256GB (8x Samsung 32GB DDR4)</span>
|
||||||
|
<span><span className="font-bold">Boot Drive:</span> Samsung Evo 850 250GB</span>
|
||||||
|
<span><span className="font-bold">Storage:</span> HP FX900 Pro 4TB NVMe</span>
|
||||||
|
<span><span className="font-bold">Bandwidth:</span> 40TB</span>
|
||||||
|
<span><span className="font-bold">Location:</span> Buffalo, New York, USA</span>
|
||||||
|
<span><span className="font-bold">Provider:</span> ColoCrossing</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-2 text-lg bg-red-400 text-white px-8 py-8 rounded-4xl">
|
||||||
|
<div className="flex flex-row items-center justify-between gap-2">
|
||||||
|
<TbServer size={36} />
|
||||||
|
<span className="text-2xl font-bold">
|
||||||
|
CA-1
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<p className="flex flex-col text-sm my-2 gap-4">
|
||||||
|
<span><span className="font-bold">CPU:</span> 2 cores shared</span>
|
||||||
|
<span><span className="font-bold">RAM:</span> 2GB</span>
|
||||||
|
<span><span className="font-bold">Disk:</span> 3.5TB Raidz2</span>
|
||||||
|
<span><span className="font-bold">Storage:</span> HP FX900 Pro 4TB NVMe</span>
|
||||||
|
<span><span className="font-bold">Bandwidth:</span> Unlimited @ 250Mbps</span>
|
||||||
|
<span><span className="font-bold">Location:</span> Montreal, Canada</span>
|
||||||
|
<span><span className="font-bold">Provider:</span> Serverica</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-2 text-lg bg-orange-400 text-white px-8 py-8 rounded-4xl">
|
||||||
|
<div className="flex flex-row items-center justify-between gap-2">
|
||||||
|
<TbServer size={36} />
|
||||||
|
<span className="text-2xl font-bold">
|
||||||
|
DE-1
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<p className="flex flex-col text-sm my-2 gap-4">
|
||||||
|
<span><span className="font-bold">CPU:</span> 1vCPU AMD EPYC</span>
|
||||||
|
<span><span className="font-bold">RAM:</span> 1GB</span>
|
||||||
|
<span><span className="font-bold">Storage:</span> 153GB</span>
|
||||||
|
<span><span className="font-bold">Location:</span> Frankfurt, Germany</span>
|
||||||
|
<span><span className="font-bold">Bandwidth:</span> Unlimited</span>
|
||||||
|
<span><span className="font-bold">Provider:</span> Oracle Cloud</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-2 text-lg bg-orange-400 text-white px-8 py-8 rounded-4xl">
|
||||||
|
<div className="flex flex-row items-center justify-between gap-2">
|
||||||
|
<TbServer size={36} />
|
||||||
|
<span className="text-2xl font-bold">
|
||||||
|
DE-2
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<p className="flex flex-col text-sm my-2 gap-4">
|
||||||
|
<span><span className="font-bold">CPU:</span> 1vCPU AMD EPYC</span>
|
||||||
|
<span><span className="font-bold">RAM:</span> 1GB</span>
|
||||||
|
<span><span className="font-bold">Storage:</span> 47GB</span>
|
||||||
|
<span><span className="font-bold">Location:</span> Frankfurt, Germany</span>
|
||||||
|
<span><span className="font-bold">Bandwidth:</span> Unlimited</span>
|
||||||
|
<span><span className="font-bold">Provider:</span> Oracle Cloud</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col items-center justify-between gap-3 my-20">
|
||||||
|
<h2 className="text-2xl font-semibold text-center w-full flex flex-wrap items-center justify-center">
|
||||||
|
our ip addresses
|
||||||
|
</h2>
|
||||||
|
<p className="text-center text-md my-2">
|
||||||
|
if you own a mail server/service, please consider whitelisting our ip addresses.
|
||||||
|
</p>
|
||||||
|
<div className="grid grid-cols-3 gap-4 my-4">
|
||||||
|
<p className="flex flex-row items-center gap-2 text-lg bg-blue-400 text-white px-4 py-2 rounded-full">
|
||||||
|
<Flag code="US" className="w-6 h-6" /> <span className="font-bold">NY1:</span> 192.3.178.206
|
||||||
|
</p>
|
||||||
|
<p className="flex flex-row items-center gap-2 text-lg bg-red-400 text-white px-4 py-2 rounded-full">
|
||||||
|
<Flag code="CA" className="w-6 h-6" /> <span className="font-bold">CA1:</span> 209.209.9.109
|
||||||
|
</p>
|
||||||
|
<p className="flex flex-row items-center gap-2 text-lg bg-orange-400 text-white px-4 py-2 rounded-full">
|
||||||
|
<Flag code="DE" className="w-6 h-6" /> <span className="font-bold">DE1:</span> 138.2.154.209
|
||||||
|
</p>
|
||||||
|
<p className="flex flex-row items-center gap-2 text-lg bg-orange-400 text-white px-4 py-2 rounded-full">
|
||||||
|
<Flag code="DE" className="w-6 h-6" /> <span className="font-bold">DE2:</span> 158.180.60.92
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
12
app/services/[slug]/page.tsx
Normal file
12
app/services/[slug]/page.tsx
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
"use client"
|
||||||
|
|
||||||
|
import { ServicesShell } from "@/components/front/services"
|
||||||
|
import { useParams } from "next/navigation"
|
||||||
|
|
||||||
|
export default function Service() {
|
||||||
|
const slug = useParams().slug
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ServicesShell slug={slug as string} />
|
||||||
|
)
|
||||||
|
}
|
87
app/services/page.tsx
Normal file
87
app/services/page.tsx
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
import { Nav } from "@/components/core/nav"
|
||||||
|
import { SiForgejo, SiJellyfin, SiOllama } from "react-icons/si"
|
||||||
|
import { TbKey, TbMail, TbServer, TbTool } from "react-icons/tb"
|
||||||
|
import Link from "next/link"
|
||||||
|
|
||||||
|
export default function Services() {
|
||||||
|
return (
|
||||||
|
<main>
|
||||||
|
<Nav />
|
||||||
|
<div className="flex flex-col items-center justify-between gap-10 my-16">
|
||||||
|
<div className="flex flex-row items-center justify-between gap-2">
|
||||||
|
<TbTool size={36} />
|
||||||
|
<h1 className="text-4xl font-bold">
|
||||||
|
services
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col items-center justify-between gap-2">
|
||||||
|
<h2 className="text-3xl font-light text-center w-full flex flex-wrap items-center justify-center">
|
||||||
|
please select a service.
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="grid grid-cols-4 gap-4 my-4 w-3/4 mx-auto">
|
||||||
|
<Link href="/services/git">
|
||||||
|
<div className="flex flex-col gap-2 text-lg bg-blue-400 text-white px-8 py-8 rounded-4xl">
|
||||||
|
<div className="flex flex-row items-center justify-between gap-2">
|
||||||
|
<SiForgejo size={36} />
|
||||||
|
<span className="text-2xl font-bold">
|
||||||
|
git
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
<Link href="/services/mail">
|
||||||
|
<div className="flex flex-col gap-2 text-lg bg-blue-400 text-white px-8 py-8 rounded-4xl">
|
||||||
|
<div className="flex flex-row items-center justify-between gap-2">
|
||||||
|
<TbMail size={36} />
|
||||||
|
<span className="text-2xl font-bold">
|
||||||
|
email
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
<Link href="/services/ai">
|
||||||
|
<div className="flex flex-col gap-2 text-lg bg-blue-400 text-white px-8 py-8 rounded-4xl">
|
||||||
|
<div className="flex flex-row items-center justify-between gap-2">
|
||||||
|
<SiOllama size={36} />
|
||||||
|
<span className="text-2xl font-bold">
|
||||||
|
ai
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
<Link href="/services/tv">
|
||||||
|
<div className="flex flex-col gap-2 text-lg bg-blue-400 text-white px-8 py-8 rounded-4xl">
|
||||||
|
<div className="flex flex-row items-center justify-between gap-2">
|
||||||
|
<SiJellyfin size={36} />
|
||||||
|
<span className="text-2xl font-bold">
|
||||||
|
tv
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
<Link href="/services/keybox">
|
||||||
|
<div className="flex flex-col gap-2 text-lg bg-blue-400 text-white px-8 py-8 rounded-4xl">
|
||||||
|
<div className="flex flex-row items-center justify-between gap-2">
|
||||||
|
<TbKey size={36} />
|
||||||
|
<span className="text-2xl font-bold">
|
||||||
|
keybox
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
<Link href="/services/hosting">
|
||||||
|
<div className="flex flex-col gap-2 text-lg bg-blue-400 text-white px-8 py-8 rounded-4xl">
|
||||||
|
<div className="flex flex-row items-center justify-between gap-2">
|
||||||
|
<TbServer size={36} />
|
||||||
|
<span className="text-2xl font-bold">
|
||||||
|
hosting
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
)
|
||||||
|
}
|
19
components/core/nav.tsx
Normal file
19
components/core/nav.tsx
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
export function Nav() {
|
||||||
|
return (
|
||||||
|
<div className="flex flex-row items-center justify-between px-5 py-3">
|
||||||
|
<Link href="/">
|
||||||
|
<h1 className="text-3xl font-bold font-mono">
|
||||||
|
p0ntus
|
||||||
|
</h1>
|
||||||
|
</Link>
|
||||||
|
<div className="flex flex-row gap-4">
|
||||||
|
<Link href="/">Home</Link>
|
||||||
|
<Link href="/about">About</Link>
|
||||||
|
<Link href="/servers">Servers</Link>
|
||||||
|
<Link href="/services">Services</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
125
components/front/services.tsx
Normal file
125
components/front/services.tsx
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
import Link from "next/link";
|
||||||
|
import { Nav } from "../core/nav";
|
||||||
|
import { services } from "@/config/services";
|
||||||
|
import { TbArrowLeft, TbEye, TbShieldLock } from "react-icons/tb";
|
||||||
|
|
||||||
|
function HumanPriceStatus(priceStatus: "open" | "invite-only" | "by-request") {
|
||||||
|
switch (priceStatus) {
|
||||||
|
case "open":
|
||||||
|
return "Open";
|
||||||
|
case "invite-only":
|
||||||
|
return "Invite only";
|
||||||
|
case "by-request":
|
||||||
|
return "By request";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function HumanPriceStatusColor(priceStatus: "open" | "invite-only" | "by-request") {
|
||||||
|
switch (priceStatus) {
|
||||||
|
case "open":
|
||||||
|
return "bg-green-500";
|
||||||
|
case "invite-only":
|
||||||
|
return "bg-yellow-500";
|
||||||
|
case "by-request":
|
||||||
|
return "bg-red-500";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function PriceStatusDesc(priceStatus: "open" | "invite-only" | "by-request", serviceName: string) {
|
||||||
|
switch (priceStatus) {
|
||||||
|
case "open":
|
||||||
|
return `${serviceName} is open for public, self-service registration.`;
|
||||||
|
case "invite-only":
|
||||||
|
return `${serviceName} is invite-only. Please request an invite from an admin.`;
|
||||||
|
case "by-request":
|
||||||
|
return `${serviceName} is by-request. You may request access from an admin.`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ServicesShell({ slug }: { slug: string }) {
|
||||||
|
const service = services.find((service) => service.name === slug);
|
||||||
|
const Icon = service?.icon;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main>
|
||||||
|
<Nav />
|
||||||
|
<div className="flex flex-col items-center justify-between gap-4 my-20">
|
||||||
|
<div className="flex flex-row items-center justify-between gap-2">
|
||||||
|
{Icon && <Icon size={36} />}
|
||||||
|
<h1 className="text-4xl font-bold">
|
||||||
|
{service?.name}
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<p className="text-lg">
|
||||||
|
{service?.description}
|
||||||
|
</p>
|
||||||
|
<Link href={`/services`}>
|
||||||
|
<button className="flex flex-row items-center justify-between gap-2 text-blue-500 px-4 py-2 rounded-2xl hover:underline transition-all duration-300 cursor-pointer">
|
||||||
|
<TbArrowLeft size={16} />
|
||||||
|
Back to services
|
||||||
|
</button>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
<div className="grid grid-cols-4 gap-4 px-14">
|
||||||
|
<div className={`flex flex-col justify-between gap-4 rounded-2xl px-8 py-4 ${HumanPriceStatusColor(service?.priceStatus as "open" | "invite-only" | "by-request")}`}>
|
||||||
|
<div className="flex flex-row items-center justify-between gap-2 w-full my-2">
|
||||||
|
<h2 className="text-2xl font-semibold text-white">
|
||||||
|
{HumanPriceStatus(service?.priceStatus as "open" | "invite-only" | "by-request")}
|
||||||
|
</h2>
|
||||||
|
{service?.joinLink && (
|
||||||
|
<Link href={service.joinLink}>
|
||||||
|
<button className="flex flex-row items-center justify-between gap-2 text-white bg-green-600 px-4 py-2 rounded-full hover:underline transition-all duration-300 cursor-pointer">
|
||||||
|
Join!
|
||||||
|
</button>
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<p className="text-md text-white mb-3">
|
||||||
|
{PriceStatusDesc(service?.priceStatus as "open" | "invite-only" | "by-request", service?.name as string)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className={`flex flex-col justify-between gap-4 rounded-2xl px-8 py-4 bg-gray-200`}>
|
||||||
|
<div className="flex flex-row items-center gap-2 w-full my-2">
|
||||||
|
<h2 className="flex flex-row items-center gap-2 text-2xl font-semibold text-black">
|
||||||
|
<TbEye size={32} />
|
||||||
|
What admins can see
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
{Object.entries((service?.adminView ?? {}) as Record<string, {
|
||||||
|
icon: React.ElementType;
|
||||||
|
description: string;
|
||||||
|
}>)
|
||||||
|
.filter(([, value]) => value !== undefined)
|
||||||
|
.map(([key, value], index) => (
|
||||||
|
<div className="flex flex-col w-full mb-2" key={index}>
|
||||||
|
<p className="flex flex-row items-center gap-1 text-md font-semibold text-black">
|
||||||
|
<value.icon size={16} /> {key}
|
||||||
|
</p>
|
||||||
|
<p className="text-sm text-black">
|
||||||
|
{value.description}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<div className={`flex flex-col gap-4 rounded-2xl px-8 py-4 bg-gray-200`}>
|
||||||
|
<div className="flex flex-row items-center gap-2 w-full my-2">
|
||||||
|
<h2 className="flex flex-row items-center gap-2 text-2xl font-semibold text-black">
|
||||||
|
<TbShieldLock size={32} />
|
||||||
|
Our commitment to privacy
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<p className="text-md text-black">
|
||||||
|
Privacy is a big concern to us, too. That's why we:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc list-inside text-md text-black">
|
||||||
|
<li>Never share your data to third parties.</li>
|
||||||
|
<li>Never use your data for advertising.</li>
|
||||||
|
<li>Never use your data for any other purpose than to provide you with the service you have requested.</li>
|
||||||
|
<li>Always delete data upon request.</li>
|
||||||
|
<li>Provide additional options to manage your data.</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
)
|
||||||
|
}
|
146
config/services.ts
Normal file
146
config/services.ts
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
import { SiForgejo, SiJellyfin, SiOllama } from "react-icons/si"
|
||||||
|
import { TbBrowser, TbBubbleText, TbDeviceTv, TbGitBranch, TbKey, TbLink, TbLock, TbMail, TbServer, TbUser } from "react-icons/tb"
|
||||||
|
|
||||||
|
export interface Service {
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
icon: React.ElementType;
|
||||||
|
priceStatus: "open" | "invite-only" | "by-request"; /*
|
||||||
|
open -> open, public registration
|
||||||
|
invite-only -> manual registration/invites
|
||||||
|
by-request -> must be requested by user */
|
||||||
|
adminView: Record<string, {
|
||||||
|
icon: React.ElementType;
|
||||||
|
description: string;
|
||||||
|
}>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const services = [
|
||||||
|
{
|
||||||
|
name: "git",
|
||||||
|
description: "Easy-to-use git server w/ Actions support. Powered by Forgejo.",
|
||||||
|
icon: SiForgejo,
|
||||||
|
priceStatus: "open",
|
||||||
|
joinLink: "https://git.p0ntus.com",
|
||||||
|
adminView: {
|
||||||
|
"Your private repositories": {
|
||||||
|
icon: TbGitBranch,
|
||||||
|
description: "Your private repositories are visible to admins.",
|
||||||
|
},
|
||||||
|
"Your email address": {
|
||||||
|
icon: TbMail,
|
||||||
|
description: "Your email address is visible to admins.",
|
||||||
|
},
|
||||||
|
"Change your password": {
|
||||||
|
icon: TbLock,
|
||||||
|
description: "Your password can be changed by an admin. It is not visible.",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "tv",
|
||||||
|
description: "Private screening movies and tv shows. Powered by Jellyfin.",
|
||||||
|
icon: SiJellyfin,
|
||||||
|
priceStatus: "invite-only",
|
||||||
|
adminView: {
|
||||||
|
"Your devices": {
|
||||||
|
icon: TbDeviceTv,
|
||||||
|
description: "Your devices and their IP addresses.",
|
||||||
|
},
|
||||||
|
"Your email address": {
|
||||||
|
icon: TbMail,
|
||||||
|
description: "Your email address is visible to admins.",
|
||||||
|
},
|
||||||
|
"The content you watch": {
|
||||||
|
icon: TbUser,
|
||||||
|
description: "The content you watch is visible to admins.",
|
||||||
|
},
|
||||||
|
"Change settings and preferences": {
|
||||||
|
icon: TbKey,
|
||||||
|
description: "Admins can change settings and preferences.",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ai",
|
||||||
|
description: "Invite-only Open WebUI instance w/ Ollama and popular models.",
|
||||||
|
icon: SiOllama,
|
||||||
|
priceStatus: "invite-only",
|
||||||
|
adminView: {
|
||||||
|
"Your chats": {
|
||||||
|
icon: TbBubbleText,
|
||||||
|
description: "Your chats are visible to admins.",
|
||||||
|
},
|
||||||
|
"Your email address": {
|
||||||
|
icon: TbMail,
|
||||||
|
description: "Your email address is visible to admins.",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "keybox",
|
||||||
|
description: "Need integrity? We do our best to provide you STRONG",
|
||||||
|
icon: TbKey,
|
||||||
|
priceStatus: "open",
|
||||||
|
joinLink: "/keybox",
|
||||||
|
adminView: {
|
||||||
|
"Your email address": {
|
||||||
|
icon: TbMail,
|
||||||
|
description: "Your email address is visible to admins.",
|
||||||
|
},
|
||||||
|
"Your sessions": {
|
||||||
|
icon: TbBrowser,
|
||||||
|
description: "Your sessions are visible to admins.",
|
||||||
|
},
|
||||||
|
"Your connections": {
|
||||||
|
icon: TbLink,
|
||||||
|
description: "If you authenticate with SSO, your connections are visible to admins.",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "mail",
|
||||||
|
description: "A private mail server with full data control. Powered by Mailu.",
|
||||||
|
icon: TbMail,
|
||||||
|
priceStatus: "open",
|
||||||
|
joinLink: "https://pontusmail.org",
|
||||||
|
adminView: {
|
||||||
|
"Change user settings": {
|
||||||
|
icon: TbUser,
|
||||||
|
description: "Admins can change and view user settings.",
|
||||||
|
},
|
||||||
|
"Subject lines": {
|
||||||
|
icon: TbMail,
|
||||||
|
description: "Subject lines are visible to admins.",
|
||||||
|
},
|
||||||
|
"Your email address": {
|
||||||
|
icon: TbMail,
|
||||||
|
description: "Your email address is visible to admins.",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "hosting",
|
||||||
|
description: "By-request server and service hosting.",
|
||||||
|
icon: TbServer,
|
||||||
|
priceStatus: "by-request",
|
||||||
|
adminView: {
|
||||||
|
"Your data": {
|
||||||
|
icon: TbServer,
|
||||||
|
description: "Your instance data is visible to admins.",
|
||||||
|
},
|
||||||
|
"Your email address": {
|
||||||
|
icon: TbMail,
|
||||||
|
description: "Your email address is visible to admins.",
|
||||||
|
},
|
||||||
|
"Your connections": {
|
||||||
|
icon: TbLink,
|
||||||
|
description: "If you authenticate with SSO, your connections are visible to admins.",
|
||||||
|
},
|
||||||
|
"Your sessions": {
|
||||||
|
icon: TbBrowser,
|
||||||
|
description: "Your sessions are visible to admins.",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
16
eslint.config.mjs
Normal file
16
eslint.config.mjs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import { dirname } from "path";
|
||||||
|
import { fileURLToPath } from "url";
|
||||||
|
import { FlatCompat } from "@eslint/eslintrc";
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = dirname(__filename);
|
||||||
|
|
||||||
|
const compat = new FlatCompat({
|
||||||
|
baseDirectory: __dirname,
|
||||||
|
});
|
||||||
|
|
||||||
|
const eslintConfig = [
|
||||||
|
...compat.extends("next/core-web-vitals", "next/typescript"),
|
||||||
|
];
|
||||||
|
|
||||||
|
export default eslintConfig;
|
7
next.config.ts
Normal file
7
next.config.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import type { NextConfig } from "next";
|
||||||
|
|
||||||
|
const nextConfig: NextConfig = {
|
||||||
|
/* config options here */
|
||||||
|
};
|
||||||
|
|
||||||
|
export default nextConfig;
|
30
package.json
Normal file
30
package.json
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
{
|
||||||
|
"name": "pontus",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "next dev --turbopack",
|
||||||
|
"build": "next build",
|
||||||
|
"start": "next start",
|
||||||
|
"lint": "next lint"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@types/react-world-flags": "^1.6.0",
|
||||||
|
"next": "15.3.4",
|
||||||
|
"react": "^19.0.0",
|
||||||
|
"react-dom": "^19.0.0",
|
||||||
|
"react-icons": "^5.5.0",
|
||||||
|
"react-world-flags": "^1.6.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"typescript": "^5",
|
||||||
|
"@types/node": "^20",
|
||||||
|
"@types/react": "^19",
|
||||||
|
"@types/react-dom": "^19",
|
||||||
|
"@tailwindcss/postcss": "^4",
|
||||||
|
"tailwindcss": "^4",
|
||||||
|
"eslint": "^9",
|
||||||
|
"eslint-config-next": "15.3.4",
|
||||||
|
"@eslint/eslintrc": "^3"
|
||||||
|
}
|
||||||
|
}
|
5
postcss.config.mjs
Normal file
5
postcss.config.mjs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
const config = {
|
||||||
|
plugins: ["@tailwindcss/postcss"],
|
||||||
|
};
|
||||||
|
|
||||||
|
export default config;
|
27
tsconfig.json
Normal file
27
tsconfig.json
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2017",
|
||||||
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
|
"allowJs": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"incremental": true,
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"name": "next"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue