added a hero page, background video, route lists. also installed pg and created the sql directory.

This commit is contained in:
HP
2026-01-14 14:23:26 -05:00
parent c2d6c93a73
commit dc4ae92839
8 changed files with 305 additions and 214 deletions

147
package-lock.json generated
View File

@@ -13,6 +13,7 @@
"@fontsource/roboto": "^5.2.9", "@fontsource/roboto": "^5.2.9",
"@mui/material": "^7.3.7", "@mui/material": "^7.3.7",
"next": "16.1.1", "next": "16.1.1",
"pg": "^8.17.0",
"react": "19.2.3", "react": "19.2.3",
"react-dom": "19.2.3" "react-dom": "19.2.3"
}, },
@@ -5183,6 +5184,95 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/pg": {
"version": "8.17.0",
"resolved": "https://registry.npmjs.org/pg/-/pg-8.17.0.tgz",
"integrity": "sha512-SRl6PbO7zqhD5bZ6lVtEFWknVeWv6Eab+PKzowWTEAce5MFiHTcSdi2N9M9m7VYAv1Hc3OOCxSka3hPBYoXHJA==",
"license": "MIT",
"dependencies": {
"pg-connection-string": "^2.10.0",
"pg-pool": "^3.11.0",
"pg-protocol": "^1.11.0",
"pg-types": "2.2.0",
"pgpass": "1.0.5"
},
"engines": {
"node": ">= 16.0.0"
},
"optionalDependencies": {
"pg-cloudflare": "^1.3.0"
},
"peerDependencies": {
"pg-native": ">=3.0.1"
},
"peerDependenciesMeta": {
"pg-native": {
"optional": true
}
}
},
"node_modules/pg-cloudflare": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.3.0.tgz",
"integrity": "sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==",
"license": "MIT",
"optional": true
},
"node_modules/pg-connection-string": {
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.10.0.tgz",
"integrity": "sha512-ur/eoPKzDx2IjPaYyXS6Y8NSblxM7X64deV2ObV57vhjsWiwLvUD6meukAzogiOsu60GO8m/3Cb6FdJsWNjwXg==",
"license": "MIT"
},
"node_modules/pg-int8": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
"integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==",
"license": "ISC",
"engines": {
"node": ">=4.0.0"
}
},
"node_modules/pg-pool": {
"version": "3.11.0",
"resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.11.0.tgz",
"integrity": "sha512-MJYfvHwtGp870aeusDh+hg9apvOe2zmpZJpyt+BMtzUWlVqbhFmMK6bOBXLBUPd7iRtIF9fZplDc7KrPN3PN7w==",
"license": "MIT",
"peerDependencies": {
"pg": ">=8.0"
}
},
"node_modules/pg-protocol": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.11.0.tgz",
"integrity": "sha512-pfsxk2M9M3BuGgDOfuy37VNRRX3jmKgMjcvAcWqNDpZSf4cUmv8HSOl5ViRQFsfARFn0KuUQTgLxVMbNq5NW3g==",
"license": "MIT"
},
"node_modules/pg-types": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
"integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
"license": "MIT",
"dependencies": {
"pg-int8": "1.0.1",
"postgres-array": "~2.0.0",
"postgres-bytea": "~1.0.0",
"postgres-date": "~1.0.4",
"postgres-interval": "^1.1.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/pgpass": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz",
"integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==",
"license": "MIT",
"dependencies": {
"split2": "^4.1.0"
}
},
"node_modules/picocolors": { "node_modules/picocolors": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@@ -5240,6 +5330,45 @@
"node": "^10 || ^12 || >=14" "node": "^10 || ^12 || >=14"
} }
}, },
"node_modules/postgres-array": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
"integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==",
"license": "MIT",
"engines": {
"node": ">=4"
}
},
"node_modules/postgres-bytea": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.1.tgz",
"integrity": "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/postgres-date": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
"integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/postgres-interval": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
"integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
"license": "MIT",
"dependencies": {
"xtend": "^4.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/prelude-ls": { "node_modules/prelude-ls": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@@ -5748,6 +5877,15 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/split2": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
"integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
"license": "ISC",
"engines": {
"node": ">= 10.x"
}
},
"node_modules/stable-hash": { "node_modules/stable-hash": {
"version": "0.0.5", "version": "0.0.5",
"resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz",
@@ -6393,6 +6531,15 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
"license": "MIT",
"engines": {
"node": ">=0.4"
}
},
"node_modules/yallist": { "node_modules/yallist": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",

View File

@@ -14,6 +14,7 @@
"@fontsource/roboto": "^5.2.9", "@fontsource/roboto": "^5.2.9",
"@mui/material": "^7.3.7", "@mui/material": "^7.3.7",
"next": "16.1.1", "next": "16.1.1",
"pg": "^8.17.0",
"react": "19.2.3", "react": "19.2.3",
"react-dom": "19.2.3" "react-dom": "19.2.3"
}, },

BIN
public/hero-background.mp4 Normal file

Binary file not shown.

View File

@@ -1,20 +1,10 @@
import type { Metadata } from "next"; import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css"; 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 = { export const metadata: Metadata = {
title: "Create Next App", title: "Tartarus",
description: "Generated by create next app", description: "you shouldn't be here"
}; };
export default function RootLayout({ export default function RootLayout({
@@ -24,7 +14,7 @@ export default function RootLayout({
}>) { }>) {
return ( return (
<html lang="en"> <html lang="en">
<body className={`${geistSans.variable} ${geistMono.variable}`}> <body className="main">
{children} {children}
</body> </body>
</html> </html>

View File

@@ -1,141 +0,0 @@
.page {
--background: #fafafa;
--foreground: #fff;
--text-primary: #000;
--text-secondary: #666;
--button-primary-hover: #383838;
--button-secondary-hover: #f2f2f2;
--button-secondary-border: #ebebeb;
display: flex;
min-height: 100vh;
align-items: center;
justify-content: center;
font-family: var(--font-geist-sans);
background-color: var(--background);
}
.main {
display: flex;
min-height: 100vh;
width: 100%;
max-width: 800px;
flex-direction: column;
align-items: flex-start;
justify-content: space-between;
background-color: var(--foreground);
padding: 120px 60px;
}
.intro {
display: flex;
flex-direction: column;
align-items: flex-start;
text-align: left;
gap: 24px;
}
.intro h1 {
max-width: 320px;
font-size: 40px;
font-weight: 600;
line-height: 48px;
letter-spacing: -2.4px;
text-wrap: balance;
color: var(--text-primary);
}
.intro p {
max-width: 440px;
font-size: 18px;
line-height: 32px;
text-wrap: balance;
color: var(--text-secondary);
}
.intro a {
font-weight: 500;
color: var(--text-primary);
}
.ctas {
display: flex;
flex-direction: row;
width: 100%;
max-width: 440px;
gap: 16px;
font-size: 14px;
}
.ctas a {
display: flex;
justify-content: center;
align-items: center;
height: 40px;
padding: 0 16px;
border-radius: 128px;
border: 1px solid transparent;
transition: 0.2s;
cursor: pointer;
width: fit-content;
font-weight: 500;
}
a.primary {
background: var(--text-primary);
color: var(--background);
gap: 8px;
}
a.secondary {
border-color: var(--button-secondary-border);
}
/* Enable hover only on non-touch devices */
@media (hover: hover) and (pointer: fine) {
a.primary:hover {
background: var(--button-primary-hover);
border-color: transparent;
}
a.secondary:hover {
background: var(--button-secondary-hover);
border-color: transparent;
}
}
@media (max-width: 600px) {
.main {
padding: 48px 24px;
}
.intro {
gap: 16px;
}
.intro h1 {
font-size: 32px;
line-height: 40px;
letter-spacing: -1.92px;
}
}
@media (prefers-color-scheme: dark) {
.logo {
filter: invert();
}
.page {
--background: #000;
--foreground: #000;
--text-primary: #ededed;
--text-secondary: #999;
--button-primary-hover: #ccc;
--button-secondary-hover: #1a1a1a;
--button-secondary-border: #1a1a1a;
}
}

View File

@@ -1,66 +1,136 @@
import Image from "next/image"; "use client";
import styles from "./page.module.css";
import * as React from "react";
import { useRouter } from "next/navigation";
import {
Box,
Card,
Container,
List,
ListItemButton,
ListItemText,
Stack,
Typography,
} from "@mui/material";
const navItems = [
{ label: "Products", path: "/products" },
{ label: "Pricing", path: "/pricing" },
{ label: "About", path: "/about" },
{ label: "Contact", path: "/contact" },
];
export default function Home() { export default function Home() {
const router = useRouter();
return ( return (
<div className={styles.page}> <Box
<main className={styles.main}> sx={{
<Image minHeight: "100vh",
className={styles.logo} position: "relative",
src="/next.svg" overflow: "hidden",
alt="Next.js logo" }}
width={100} >
height={20} <Box
priority component="video"
autoPlay
muted
loop
playsInline
src="/hero-background.mp4"
sx={{
position: "fixed",
inset: 0,
width: "100vw",
height: "100vh",
objectFit: "cover",
zIndex: 0,
}}
/> />
<div className={styles.intro}>
<h1>To get started, edit the page.tsx file.</h1> <Box
<p> sx={{
Looking for a starting point or more instructions? Head over to{" "} position: "fixed",
<a inset: 0,
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app" background:
target="_blank" "linear-gradient(90deg, rgba(0,0,0,0.55) 0%, rgba(0,0,0,0.25) 55%, rgba(0,0,0,0.55) 100%)",
rel="noopener noreferrer" zIndex: 1,
> }}
Templates
</a>{" "}
or the{" "}
<a
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"
>
Learning
</a>{" "}
center.
</p>
</div>
<div className={styles.ctas}>
<a
className={styles.primary}
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
className={styles.logo}
src="/vercel.svg"
alt="Vercel logomark"
width={16}
height={16}
/> />
Deploy Now
</a> <Container
<a maxWidth="lg"
className={styles.secondary} sx={{
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app" position: "relative",
target="_blank" zIndex: 2,
rel="noopener noreferrer" minHeight: "100vh",
display: "flex",
alignItems: "center",
justifyContent: "flex-end",
py: { xs: 3, md: 6 },
}}
> >
Documentation <Card
</a> elevation={10}
</div> sx={{
</main> width: { xs: "100%", sm: 420 },
</div> borderRadius: 4,
p: { xs: 2, sm: 3 },
backdropFilter: "blur(10px)",
backgroundColor: "rgba(255,255,255,0.10)",
border: "1px solid rgba(255,255,255,0.18)",
color: "white",
}}
>
<Stack spacing={2}>
<Box>
<Typography variant="h5" fontWeight={700}>
Greetings
</Typography>
<Typography variant="body2" sx={{ opacity: 0.85 }}>
Choose a section to continue.
</Typography>
</Box>
<List
disablePadding
sx={{
display: "flex",
flexDirection: "column",
gap: 1,
}}
>
{navItems.map((item) => (
<ListItemButton
key={item.path}
onClick={() => router.push(item.path)}
sx={{
borderRadius: 2,
border: "1px solid rgba(255,255,255,0.16)",
backgroundColor: "rgba(0,0,0,0.18)",
transition: "transform 120ms ease, background-color 120ms ease",
"&:hover": {
backgroundColor: "rgba(255,255,255,0.12)",
transform: "translateX(-4px)",
},
"&:active": {
transform: "translateX(-2px) scale(0.99)",
},
}}
>
<ListItemText
primary={item.label}
primaryTypographyProps={{
fontWeight: 600,
}}
/>
</ListItemButton>
))}
</List>
</Stack>
</Card>
</Container>
</Box>
); );
} }

11
src/paths.ts Normal file
View File

@@ -0,0 +1,11 @@
export const paths = {
home: '/',
products: {
home: '/demo',
},
auth: {
signIn: '/auth/sign-in',
resetPassword: '/auth/reset-password',
setPassword: '/auth/set-password',
},
} as const;

13
src/sql/products.sql Normal file
View File

@@ -0,0 +1,13 @@
DROP TABLE products IF EXISTS;
DROP product_record_num_sequence IF EXISTS;
DROP product_product_id_sequence IF EXISTS;
CREATE product_record_num_sequence CASCADE;
CREATE product_product_id_sequence CASCADE;
CREATE TABLE products(
record_num INTEGER PRIMARY KEY DEFAULT nextval('product_record_num_sequence'),
product_id INTEGER PRIMARY KEY DEFAULT,
name VARCHAR(20),
exp_date DATE NOT NULL,
);