diff --git a/.eslintrc.json b/.eslintrc.json index 3722418..33f6e02 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -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" + } } diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index b895836..c3d7767 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -1,4 +1,4 @@ -name: Deploy Site +name: Deploy on: push: @@ -9,7 +9,7 @@ on: - docker-compose.yml jobs: - docker: + deploy: strategy: matrix: arch: [ "ubuntu-latest" ] @@ -28,5 +28,5 @@ jobs: - name: Deploy to Dokku uses: dokku/github-action@master 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 }} diff --git a/.gitignore b/.gitignore index fd3dbb5..acaf3a3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,36 +1,13 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.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 +node_modules +.idea/ +.vscode/ +.VSCodeCounter/ +.next/ .env*.local - -# vercel -.vercel - -# typescript -*.tsbuildinfo next-env.d.ts +.sentryclirc +.env +sw.* +workbox-* +swe-worker-* +dist/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index ac8aa26..50899a3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,8 +15,6 @@ COPY --from=depends /usr/src/app/node_modules ./node_modules COPY . . ENV NEXT_TELEMETRY_DISABLED 1 -RUN --mount=type=bind,target=/config,from=korben-splash cp /config/.env ./.env - 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/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/.env ./.env ENV NODE_ENV production diff --git a/README.md b/README.md index e69de29..6f8872e 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,3 @@ +# www + +The frontend for PulseApp. \ No newline at end of file diff --git a/bun.lockb b/bun.lockb index 3bae941..54e9519 100644 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/next.config.mjs b/next.config.mjs index 4678774..608f1be 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,4 +1,6 @@ /** @type {import('next').NextConfig} */ -const nextConfig = {}; +const nextConfig = { + output: "standalone", +}; export default nextConfig; diff --git a/package.json b/package.json index b24cdd0..f906e7a 100644 --- a/package.json +++ b/package.json @@ -9,9 +9,18 @@ "lint": "next lint" }, "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-dom": "^18", - "next": "14.2.8" + "sharp": "^0.33.5", + "tailwind-merge": "^2.5.2", + "tailwindcss-animate": "^1.0.7" }, "devDependencies": { "typescript": "^5", diff --git a/postcss.config.mjs b/postcss.config.mjs index 1a69fd2..6f94347 100644 --- a/postcss.config.mjs +++ b/postcss.config.mjs @@ -1,8 +1,8 @@ /** @type {import('postcss-load-config').Config} */ const config = { - plugins: { - tailwindcss: {}, - }, + plugins: { + tailwindcss: {}, + }, }; export default config; diff --git a/public/favicon.ico b/public/favicon.ico index 718d6fe..009fca4 100644 Binary files a/public/favicon.ico and b/public/favicon.ico differ diff --git a/src/app/(pages)/layout.tsx b/src/app/(pages)/layout.tsx index a36cde0..ea2c22b 100644 --- a/src/app/(pages)/layout.tsx +++ b/src/app/(pages)/layout.tsx @@ -1,35 +1,56 @@ -import type { Metadata } from "next"; -import localFont from "next/font/local"; -import "./globals.css"; +import type { Metadata, Viewport } from "next"; +import { Inter } from "next/font/google"; +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({ - 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", -}); +const inter: NextFont = Inter({ subsets: ["latin"] }); +/** + * The metadata for this app. + */ export const metadata: Metadata = { - title: "Create Next App", - description: "Generated by create next app", + title: "PulseApp", + 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({ - children, +/** + * The primary layout for this app. + */ +const RootLayout = ({ + children, }: Readonly<{ - children: React.ReactNode; -}>) { - return ( + children: ReactNode; +}>): ReactElement => ( - - {children} - + + + {children} + + - ); -} +); +export default RootLayout; diff --git a/src/app/(pages)/page.tsx b/src/app/(pages)/page.tsx index 6fe62d1..e32a542 100644 --- a/src/app/(pages)/page.tsx +++ b/src/app/(pages)/page.tsx @@ -1,101 +1,9 @@ -import Image from "next/image"; +import { ReactElement } from "react"; +import Greeting from "@/components/landing/greeting"; -export default function Home() { - return ( -
-
- Next.js logo -
    -
  1. - Get started by editing{" "} - - src/app/page.tsx - - . -
  2. -
  3. Save and see your changes instantly.
  4. -
- -
- - Vercel logomark - Deploy now - - - Read our docs - -
-
- -
- ); -} +const LandingPage = (): ReactElement => ( +
+ +
+); +export default LandingPage; diff --git a/src/app/style/globals.css b/src/app/style/globals.css index 13d40b8..f20e5ca 100644 --- a/src/app/style/globals.css +++ b/src/app/style/globals.css @@ -3,25 +3,92 @@ @tailwind utilities; :root { - --background: #ffffff; - --foreground: #171717; + --background: #ffffff; + --foreground: #171717; } @media (prefers-color-scheme: dark) { - :root { - --background: #0a0a0a; - --foreground: #ededed; - } + :root { + --background: #0a0a0a; + --foreground: #ededed; + } } body { - color: var(--foreground); - background: var(--background); - font-family: Arial, Helvetica, sans-serif; + color: var(--foreground); + background: var(--background); + font-family: Arial, Helvetica, sans-serif; } @layer utilities { - .text-balance { - text-wrap: balance; - } + .text-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; + } +} \ No newline at end of file diff --git a/src/components/landing/greeting.tsx b/src/components/landing/greeting.tsx index e69de29..49c4706 100644 --- a/src/components/landing/greeting.tsx +++ b/src/components/landing/greeting.tsx @@ -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 => ( +
+
+ {/* Logo */} + PulseApp Logo + + {/* Greeting */} +

Pulse App

+

+ A lightweight service monitoring solution for tracking the + availability of whatever service your heart desires! +

+

Coming Soon...

+
+ + {/* GitHub */} + + + +
+); +export default Greeting; diff --git a/src/components/theme-provider.tsx b/src/components/theme-provider.tsx index e69de29..a95c5bc 100644 --- a/src/components/theme-provider.tsx +++ b/src/components/theme-provider.tsx @@ -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) => ( + {children} +); diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx index 0270f64..d401551 100644 --- a/src/components/ui/button.tsx +++ b/src/components/ui/button.tsx @@ -1,57 +1,57 @@ -import * as React from "react" -import { Slot } from "@radix-ui/react-slot" -import { cva, type VariantProps } from "class-variance-authority" +import * as React from "react"; +import { Slot } from "@radix-ui/react-slot"; +import { cva, type VariantProps } from "class-variance-authority"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; 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", - { - variants: { - variant: { - default: - "bg-primary text-primary-foreground shadow hover:bg-primary/90", - destructive: - "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90", - outline: - "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground", - secondary: - "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80", - ghost: "hover:bg-accent hover:text-accent-foreground", - link: "text-primary underline-offset-4 hover:underline", - }, - size: { - default: "h-9 px-4 py-2", - sm: "h-8 rounded-md px-3 text-xs", - lg: "h-10 rounded-md px-8", - icon: "h-9 w-9", - }, - }, - defaultVariants: { - variant: "default", - size: "default", - }, - } -) + "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", + { + variants: { + variant: { + default: + "bg-primary text-primary-foreground shadow hover:bg-primary/90", + destructive: + "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90", + outline: + "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground", + secondary: + "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-9 px-4 py-2", + sm: "h-8 rounded-md px-3 text-xs", + lg: "h-10 rounded-md px-8", + icon: "h-9 w-9", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +); export interface ButtonProps - extends React.ButtonHTMLAttributes, - VariantProps { - asChild?: boolean + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean; } const Button = React.forwardRef( - ({ className, variant, size, asChild = false, ...props }, ref) => { - const Comp = asChild ? Slot : "button" - return ( - - ) - } -) -Button.displayName = "Button" + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : "button"; + return ( + + ); + } +); +Button.displayName = "Button"; -export { Button, buttonVariants } +export { Button, buttonVariants }; diff --git a/src/lib/utils.ts b/src/lib/utils.ts index bd0c391..e644794 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -1,6 +1,6 @@ -import { clsx, type ClassValue } from "clsx" -import { twMerge } from "tailwind-merge" +import { type ClassValue, clsx } from "clsx"; +import { twMerge } from "tailwind-merge"; export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)) + return twMerge(clsx(inputs)); } diff --git a/tailwind.config.ts b/tailwind.config.ts index 021c393..51403e2 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -1,19 +1,63 @@ import type { Config } from "tailwindcss"; const config: Config = { - content: [ - "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", - "./src/components/**/*.{js,ts,jsx,tsx,mdx}", - "./src/app/**/*.{js,ts,jsx,tsx,mdx}", - ], - theme: { - extend: { - colors: { - background: "var(--background)", - foreground: "var(--foreground)", - }, + darkMode: ["class"], + content: [ + "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", + "./src/components/**/*.{js,ts,jsx,tsx,mdx}", + "./src/app/**/*.{js,ts,jsx,tsx,mdx}", + ], + theme: { + extend: { + colors: { + background: "hsl(var(--background))", + 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; diff --git a/tsconfig.json b/tsconfig.json index 7b28589..af0efb2 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,10 @@ { "compilerOptions": { - "lib": ["dom", "dom.iterable", "esnext"], + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], "allowJs": true, "skipLibCheck": true, "strict": true, @@ -18,9 +22,18 @@ } ], "paths": { - "@/*": ["./src/*"] + "@/*": [ + "./src/*" + ] } }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], - "exclude": ["node_modules"] + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts" + ], + "exclude": [ + "node_modules" + ] }