Initial Commit
Some checks failed
Deploy / deploy (ubuntu-latest, 2.44.0) (push) Has been cancelled

This commit is contained in:
Braydon 2024-09-13 21:27:40 -04:00
parent 1d7bc5c311
commit ac765d0250
19 changed files with 354 additions and 253 deletions

@ -1,3 +1,10 @@
{ {
"extends": ["next/core-web-vitals", "next/typescript"] "extends": [
"next/core-web-vitals",
"next/typescript"
],
"rules": {
"@typescript-eslint/no-unused-vars": "off",
"@typescript-eslint/no-explicit-any": "off"
}
} }

@ -1,4 +1,4 @@
name: Deploy Site name: Deploy
on: on:
push: push:
@ -9,7 +9,7 @@ on:
- docker-compose.yml - docker-compose.yml
jobs: jobs:
docker: deploy:
strategy: strategy:
matrix: matrix:
arch: [ "ubuntu-latest" ] arch: [ "ubuntu-latest" ]
@ -28,5 +28,5 @@ jobs:
- name: Deploy to Dokku - name: Deploy to Dokku
uses: dokku/github-action@master uses: dokku/github-action@master
with: with:
git_remote_url: "ssh://dokku@10.10.3.28:22/rainnny-club" git_remote_url: "ssh://dokku@10.10.3.28:22/pulseapp-www"
ssh_private_key: ${{ secrets.SSH_PRIVATE_KEY }} ssh_private_key: ${{ secrets.SSH_PRIVATE_KEY }}

45
.gitignore vendored

@ -1,36 +1,13 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. node_modules
.idea/
# dependencies .vscode/
/node_modules .VSCodeCounter/
/.pnp .next/
.pnp.js
.yarn/install-state.gz
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env*.local .env*.local
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts next-env.d.ts
.sentryclirc
.env
sw.*
workbox-*
swe-worker-*
dist/

@ -15,8 +15,6 @@ COPY --from=depends /usr/src/app/node_modules ./node_modules
COPY . . COPY . .
ENV NEXT_TELEMETRY_DISABLED 1 ENV NEXT_TELEMETRY_DISABLED 1
RUN --mount=type=bind,target=/config,from=korben-splash cp /config/.env ./.env
RUN bun run build RUN bun run build
@ -35,7 +33,6 @@ COPY --from=builder --chown=nextjs:nextjs /usr/src/app/.next ./.next
COPY --from=builder --chown=nextjs:nextjs /usr/src/app/public ./public COPY --from=builder --chown=nextjs:nextjs /usr/src/app/public ./public
COPY --from=builder --chown=nextjs:nextjs /usr/src/app/next.config.mjs ./next.config.mjs COPY --from=builder --chown=nextjs:nextjs /usr/src/app/next.config.mjs ./next.config.mjs
COPY --from=builder --chown=nextjs:nextjs /usr/src/app/package.json ./package.json COPY --from=builder --chown=nextjs:nextjs /usr/src/app/package.json ./package.json
COPY --from=builder --chown=nextjs:nextjs /usr/src/app/.env ./.env
ENV NODE_ENV production ENV NODE_ENV production

@ -0,0 +1,3 @@
# www
The frontend for PulseApp.

BIN
bun.lockb

Binary file not shown.

@ -1,4 +1,6 @@
/** @type {import('next').NextConfig} */ /** @type {import('next').NextConfig} */
const nextConfig = {}; const nextConfig = {
output: "standalone",
};
export default nextConfig; export default nextConfig;

@ -9,9 +9,18 @@
"lint": "next lint" "lint": "next lint"
}, },
"dependencies": { "dependencies": {
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-slot": "^1.1.0",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"lucide-react": "^0.441.0",
"next": "14.2.8",
"next-themes": "^0.3.0",
"react": "^18", "react": "^18",
"react-dom": "^18", "react-dom": "^18",
"next": "14.2.8" "sharp": "^0.33.5",
"tailwind-merge": "^2.5.2",
"tailwindcss-animate": "^1.0.7"
}, },
"devDependencies": { "devDependencies": {
"typescript": "^5", "typescript": "^5",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 124 KiB

@ -1,35 +1,56 @@
import type { Metadata } from "next"; import type { Metadata, Viewport } from "next";
import localFont from "next/font/local"; import { Inter } from "next/font/google";
import "./globals.css"; import "../style/globals.css";
import { ReactElement, ReactNode } from "react";
import { cn } from "@/lib/utils";
import { NextFont } from "next/dist/compiled/@next/font";
import { ThemeProvider } from "@/components/theme-provider";
const geistSans = localFont({ const inter: NextFont = Inter({ subsets: ["latin"] });
src: "./fonts/GeistVF.woff",
variable: "--font-geist-sans",
weight: "100 900",
});
const geistMono = localFont({
src: "./fonts/GeistMonoVF.woff",
variable: "--font-geist-mono",
weight: "100 900",
});
/**
* The metadata for this app.
*/
export const metadata: Metadata = { export const metadata: Metadata = {
title: "Create Next App", title: "PulseApp",
description: "Generated by create next app", description:
"A lightweight service monitoring solution for tracking the availability of whatever service your heart desires!",
openGraph: {
images: [
{
url: "https://pulseapp.cc/logo.png",
width: 128,
height: 128,
},
],
},
twitter: {
card: "summary",
},
};
export const viewport: Viewport = {
themeColor: "#DC2626",
}; };
export default function RootLayout({ /**
* The primary layout for this app.
*/
const RootLayout = ({
children, children,
}: Readonly<{ }: Readonly<{
children: React.ReactNode; children: ReactNode;
}>) { }>): ReactElement => (
return (
<html lang="en"> <html lang="en">
<body <body className={cn(inter.className, "antialiased")}>
className={`${geistSans.variable} ${geistMono.variable} antialiased`} <ThemeProvider
attribute="class"
defaultTheme="dark"
enableSystem
disableTransitionOnChange
> >
{children} {children}
</ThemeProvider>
</body> </body>
</html> </html>
); );
} export default RootLayout;

@ -1,101 +1,9 @@
import Image from "next/image"; import { ReactElement } from "react";
import Greeting from "@/components/landing/greeting";
export default function Home() { const LandingPage = (): ReactElement => (
return ( <main className="min-h-[100vh]">
<div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]"> <Greeting />
<main className="flex flex-col gap-8 row-start-2 items-center sm:items-start">
<Image
className="dark:invert"
src="https://nextjs.org/icons/next.svg"
alt="Next.js logo"
width={180}
height={38}
priority
/>
<ol className="list-inside list-decimal text-sm text-center sm:text-left font-[family-name:var(--font-geist-mono)]">
<li className="mb-2">
Get started by editing{" "}
<code className="bg-black/[.05] dark:bg-white/[.06] px-1 py-0.5 rounded font-semibold">
src/app/page.tsx
</code>
.
</li>
<li>Save and see your changes instantly.</li>
</ol>
<div className="flex gap-4 items-center flex-col sm:flex-row">
<a
className="rounded-full border border-solid border-transparent transition-colors flex items-center justify-center bg-foreground text-background gap-2 hover:bg-[#383838] dark:hover:bg-[#ccc] text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5"
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
className="dark:invert"
src="https://nextjs.org/icons/vercel.svg"
alt="Vercel logomark"
width={20}
height={20}
/>
Deploy now
</a>
<a
className="rounded-full border border-solid border-black/[.08] dark:border-white/[.145] transition-colors flex items-center justify-center hover:bg-[#f2f2f2] dark:hover:bg-[#1a1a1a] hover:border-transparent text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 sm:min-w-44"
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
Read our docs
</a>
</div>
</main> </main>
<footer className="row-start-3 flex gap-6 flex-wrap items-center justify-center">
<a
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
aria-hidden
src="https://nextjs.org/icons/file.svg"
alt="File icon"
width={16}
height={16}
/>
Learn
</a>
<a
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
aria-hidden
src="https://nextjs.org/icons/window.svg"
alt="Window icon"
width={16}
height={16}
/>
Examples
</a>
<a
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
href="https://nextjs.org?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
aria-hidden
src="https://nextjs.org/icons/globe.svg"
alt="Globe icon"
width={16}
height={16}
/>
Go to nextjs.org
</a>
</footer>
</div>
); );
} export default LandingPage;

@ -25,3 +25,70 @@ body {
text-wrap: balance; text-wrap: balance;
} }
} }
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 240 10% 3.9%;
--card: 0 0% 100%;
--card-foreground: 240 10% 3.9%;
--popover: 0 0% 100%;
--popover-foreground: 240 10% 3.9%;
--primary: 240 5.9% 10%;
--primary-foreground: 0 0% 98%;
--secondary: 240 4.8% 95.9%;
--secondary-foreground: 240 5.9% 10%;
--muted: 240 4.8% 95.9%;
--muted-foreground: 240 3.8% 46.1%;
--accent: 240 4.8% 95.9%;
--accent-foreground: 240 5.9% 10%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 240 5.9% 90%;
--input: 240 5.9% 90%;
--ring: 240 10% 3.9%;
--chart-1: 12 76% 61%;
--chart-2: 173 58% 39%;
--chart-3: 197 37% 24%;
--chart-4: 43 74% 66%;
--chart-5: 27 87% 67%;
--radius: 0.5rem;
}
.dark {
--background: 240 10% 3.9%;
--foreground: 0 0% 98%;
--card: 240 10% 3.9%;
--card-foreground: 0 0% 98%;
--popover: 240 10% 3.9%;
--popover-foreground: 0 0% 98%;
--primary: 0 0% 98%;
--primary-foreground: 240 5.9% 10%;
--secondary: 240 3.7% 15.9%;
--secondary-foreground: 0 0% 98%;
--muted: 240 3.7% 15.9%;
--muted-foreground: 240 5% 64.9%;
--accent: 240 3.7% 15.9%;
--accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%;
--border: 240 3.7% 15.9%;
--input: 240 3.7% 15.9%;
--ring: 240 4.9% 83.9%;
--chart-1: 220 70% 50%;
--chart-2: 160 60% 45%;
--chart-3: 30 80% 55%;
--chart-4: 280 65% 60%;
--chart-5: 340 75% 55%;
}
}
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}

@ -0,0 +1,44 @@
import { ReactElement } from "react";
import Image from "next/image";
import Link from "next/link";
import { Button } from "@/components/ui/button";
const Greeting = (): ReactElement => (
<div className="h-screen flex flex-col gap-4 justify-center items-center">
<div className="flex flex-col gap-2 items-center select-none pointer-events-none">
{/* Logo */}
<Image
className="animate-pulse"
src="/media/logo.png"
alt="PulseApp Logo"
width={128}
height={128}
/>
{/* Greeting */}
<h1 className="text-3xl text-red-500 font-bold">Pulse App</h1>
<p className="max-w-[30rem] text-center opacity-75">
A lightweight service monitoring solution for tracking the
availability of whatever service your heart desires!
</p>
<p className="mt-3 text-center opacity-90">Coming Soon...</p>
</div>
{/* GitHub */}
<Link href="https://github.com/PulseAppCC" target="_blank">
<Button
className="hover:bg-transparent"
size="icon"
variant="ghost"
>
<Image
src="/media/github.png"
alt="GitHub Logo"
width={32}
height={32}
/>
</Button>
</Link>
</div>
);
export default Greeting;

@ -0,0 +1,9 @@
"use client";
import * as React from "react";
import { ThemeProvider as NextThemesProvider } from "next-themes";
import { type ThemeProviderProps } from "next-themes/dist/types";
export const ThemeProvider = ({ children, ...props }: ThemeProviderProps) => (
<NextThemesProvider {...props}>{children}</NextThemesProvider>
);

@ -1,8 +1,8 @@
import * as React from "react" import * as React from "react";
import { Slot } from "@radix-ui/react-slot" import { Slot } from "@radix-ui/react-slot";
import { cva, type VariantProps } from "class-variance-authority" import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils";
const buttonVariants = cva( const buttonVariants = cva(
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50", "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
@ -32,26 +32,26 @@ const buttonVariants = cva(
size: "default", size: "default",
}, },
} }
) );
export interface ButtonProps export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>, extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> { VariantProps<typeof buttonVariants> {
asChild?: boolean asChild?: boolean;
} }
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>( const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, ...props }, ref) => { ({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : "button" const Comp = asChild ? Slot : "button";
return ( return (
<Comp <Comp
className={cn(buttonVariants({ variant, size, className }))} className={cn(buttonVariants({ variant, size, className }))}
ref={ref} ref={ref}
{...props} {...props}
/> />
) );
} }
) );
Button.displayName = "Button" Button.displayName = "Button";
export { Button, buttonVariants } export { Button, buttonVariants };

@ -1,6 +1,6 @@
import { clsx, type ClassValue } from "clsx" import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge" import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) { export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs)) return twMerge(clsx(inputs));
} }

@ -1,6 +1,7 @@
import type { Config } from "tailwindcss"; import type { Config } from "tailwindcss";
const config: Config = { const config: Config = {
darkMode: ["class"],
content: [ content: [
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}", "./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
"./src/components/**/*.{js,ts,jsx,tsx,mdx}", "./src/components/**/*.{js,ts,jsx,tsx,mdx}",
@ -9,11 +10,54 @@ const config: Config = {
theme: { theme: {
extend: { extend: {
colors: { colors: {
background: "var(--background)", background: "hsl(var(--background))",
foreground: "var(--foreground)", foreground: "hsl(var(--foreground))",
card: {
DEFAULT: "hsl(var(--card))",
foreground: "hsl(var(--card-foreground))",
},
popover: {
DEFAULT: "hsl(var(--popover))",
foreground: "hsl(var(--popover-foreground))",
},
primary: {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
},
secondary: {
DEFAULT: "hsl(var(--secondary))",
foreground: "hsl(var(--secondary-foreground))",
},
muted: {
DEFAULT: "hsl(var(--muted))",
foreground: "hsl(var(--muted-foreground))",
},
accent: {
DEFAULT: "hsl(var(--accent))",
foreground: "hsl(var(--accent-foreground))",
},
destructive: {
DEFAULT: "hsl(var(--destructive))",
foreground: "hsl(var(--destructive-foreground))",
},
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
chart: {
"1": "hsl(var(--chart-1))",
"2": "hsl(var(--chart-2))",
"3": "hsl(var(--chart-3))",
"4": "hsl(var(--chart-4))",
"5": "hsl(var(--chart-5))",
},
},
borderRadius: {
lg: "var(--radius)",
md: "calc(var(--radius) - 2px)",
sm: "calc(var(--radius) - 4px)",
}, },
}, },
}, },
plugins: [], plugins: [require("tailwindcss-animate")],
}; };
export default config; export default config;

@ -1,6 +1,10 @@
{ {
"compilerOptions": { "compilerOptions": {
"lib": ["dom", "dom.iterable", "esnext"], "lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true, "allowJs": true,
"skipLibCheck": true, "skipLibCheck": true,
"strict": true, "strict": true,
@ -18,9 +22,18 @@
} }
], ],
"paths": { "paths": {
"@/*": ["./src/*"] "@/*": [
"./src/*"
]
} }
}, },
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], "include": [
"exclude": ["node_modules"] "next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts"
],
"exclude": [
"node_modules"
]
} }