diff --git a/.gitignore b/.gitignore
index fd3dbb5..7e43796 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,7 @@
/.pnp
.pnp.js
.yarn/install-state.gz
+.env
# testing
/coverage
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..74fb772
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,13 @@
+# syntax=docker/dockerfile:1
+
+FROM node:18.17.0-bullseye
+
+WORKDIR /app
+
+EXPOSE 3000
+
+COPY . .
+
+RUN npm install
+
+CMD ["npm", "run", "dev"]
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..707c3fe
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,28 @@
+version: "3"
+services:
+ db:
+ container_name: plebdevs-db
+ image: postgres:13.2
+ restart: always
+ expose:
+ - "5432"
+ ports:
+ - "5432:5432"
+ env_file:
+ - .env
+ volumes:
+ - postgres_data:/var/lib/postgresql/data
+ app:
+ container_name: plebdevs
+ build: .
+ depends_on:
+ - db
+ env_file:
+ - .env
+ ports:
+ - "3000:3000"
+ links:
+ - db
+
+volumes:
+ postgres_data:
diff --git a/package-lock.json b/package-lock.json
index 966c3a3..005965a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,6 +9,8 @@
"version": "0.1.0",
"dependencies": {
"next": "14.0.4",
+ "primeicons": "^6.0.1",
+ "primereact": "^10.2.1",
"react": "^18",
"react-dom": "^18"
},
@@ -30,7 +32,6 @@
"version": "7.23.6",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.6.tgz",
"integrity": "sha512-zHd0eUrf5GZoOWVCXp6koAKQTfZV07eit6bGPmJgnZdnSAvvZee6zniW2XMF7Cmc4ISOOnPy3QaSiIJGJkVEDQ==",
- "dev": true,
"dependencies": {
"regenerator-runtime": "^0.14.0"
},
@@ -331,6 +332,34 @@
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
"dev": true
},
+ "node_modules/@types/prop-types": {
+ "version": "15.7.11",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz",
+ "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng=="
+ },
+ "node_modules/@types/react": {
+ "version": "18.2.45",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.45.tgz",
+ "integrity": "sha512-TtAxCNrlrBp8GoeEp1npd5g+d/OejJHFxS3OWmrPBMFaVQMSN0OFySozJio5BHxTuTeug00AVXVAjfDSfk+lUg==",
+ "dependencies": {
+ "@types/prop-types": "*",
+ "@types/scheduler": "*",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/@types/react-transition-group": {
+ "version": "4.4.10",
+ "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz",
+ "integrity": "sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==",
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
+ "node_modules/@types/scheduler": {
+ "version": "0.16.8",
+ "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz",
+ "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A=="
+ },
"node_modules/@typescript-eslint/parser": {
"version": "6.15.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.15.0.tgz",
@@ -830,6 +859,11 @@
"node": ">= 8"
}
},
+ "node_modules/csstype": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
+ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
+ },
"node_modules/damerau-levenshtein": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
@@ -923,6 +957,15 @@
"node": ">=6.0.0"
}
},
+ "node_modules/dom-helpers": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
+ "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
+ "dependencies": {
+ "@babel/runtime": "^7.8.7",
+ "csstype": "^3.0.2"
+ }
+ },
"node_modules/emoji-regex": {
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
@@ -2550,7 +2593,6 @@
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -2827,11 +2869,37 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/primeicons": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/primeicons/-/primeicons-6.0.1.tgz",
+ "integrity": "sha512-KDeO94CbWI4pKsPnYpA1FPjo79EsY9I+M8ywoPBSf9XMXoe/0crjbUK7jcQEDHuc0ZMRIZsxH3TYLv4TUtHmAA=="
+ },
+ "node_modules/primereact": {
+ "version": "10.2.1",
+ "resolved": "https://registry.npmjs.org/primereact/-/primereact-10.2.1.tgz",
+ "integrity": "sha512-F25053E1z+fod6V7AJ1Ix/DwSPkFQotk2+Idm0XkFsN+gQEywH7DgtbvNKpUA+LEq48h2+/WVK3D0V8IAm1Npg==",
+ "dependencies": {
+ "@types/react-transition-group": "^4.4.1",
+ "react-transition-group": "^4.4.1"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "@types/react": "^17.0.0 || ^18.0.0",
+ "react": "^17.0.0 || ^18.0.0",
+ "react-dom": "^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
"node_modules/prop-types": {
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
- "dev": true,
"dependencies": {
"loose-envify": "^1.4.0",
"object-assign": "^4.1.1",
@@ -2893,8 +2961,22 @@
"node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
- "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
- "dev": true
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ },
+ "node_modules/react-transition-group": {
+ "version": "4.4.5",
+ "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
+ "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
+ "dependencies": {
+ "@babel/runtime": "^7.5.5",
+ "dom-helpers": "^5.0.1",
+ "loose-envify": "^1.4.0",
+ "prop-types": "^15.6.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.6.0",
+ "react-dom": ">=16.6.0"
+ }
},
"node_modules/reflect.getprototypeof": {
"version": "1.0.4",
@@ -2919,8 +3001,7 @@
"node_modules/regenerator-runtime": {
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
- "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
- "dev": true
+ "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
},
"node_modules/regexp.prototype.flags": {
"version": "1.5.1",
diff --git a/package.json b/package.json
index c3ba939..afbbcbd 100644
--- a/package.json
+++ b/package.json
@@ -9,9 +9,11 @@
"lint": "next lint"
},
"dependencies": {
+ "next": "14.0.4",
+ "primeicons": "^6.0.1",
+ "primereact": "^10.2.1",
"react": "^18",
- "react-dom": "^18",
- "next": "14.0.4"
+ "react-dom": "^18"
},
"devDependencies": {
"eslint": "^8",
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
new file mode 100644
index 0000000..85733f7
--- /dev/null
+++ b/prisma/schema.prisma
@@ -0,0 +1,56 @@
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ npub String @unique
+ username String? @unique
+ purchased Purchase[]
+ role Role? @relation(fields: [roleId], references: [id])
+ roleId Int?
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+}
+
+model Role {
+ id Int @id @default(autoincrement())
+ name String @unique
+ users User[]
+}
+
+model Course {
+ id Int @id @default(autoincrement())
+ title String
+ description String
+ isFree Boolean @default(false)
+ resources Resource[]
+ purchases Purchase[]
+ noteId String? @unique
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+}
+
+model Resource {
+ id Int @id @default(autoincrement())
+ title String
+ content String // Markdown content
+ course Course? @relation(fields: [courseId], references: [id])
+ noteId String? @unique
+ courseId Int?
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+}
+
+model Purchase {
+ id Int @id @default(autoincrement())
+ user User @relation(fields: [userId], references: [id])
+ userId Int
+ course Course @relation(fields: [courseId], references: [id])
+ courseId Int
+ amountPaid Int // in satoshis
+ paymentType String // Webln or NWC
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+}
\ No newline at end of file
diff --git a/public/plebdevs-guy.jpg b/public/plebdevs-guy.jpg
new file mode 100644
index 0000000..a846e32
Binary files /dev/null and b/public/plebdevs-guy.jpg differ
diff --git a/src/components/navbar/Navbar.js b/src/components/navbar/Navbar.js
new file mode 100644
index 0000000..b407bcb
--- /dev/null
+++ b/src/components/navbar/Navbar.js
@@ -0,0 +1,36 @@
+import React from 'react';
+import Image from 'next/image';
+import { Button } from 'primereact/button';
+import { Menubar } from 'primereact/menubar';
+import 'primereact/resources/primereact.min.css'; // core css
+import 'primeicons/primeicons.css'; // icons
+import styles from './navbar.module.css';
+
+const end = (
+
+);
+
+const start = (
+
+
+
PlebDevs
+
+);
+
+const Navbar = () => {
+ return (
+
+ );
+};
+
+export default Navbar;
diff --git a/src/components/navbar/navbar.module.css b/src/components/navbar/navbar.module.css
new file mode 100644
index 0000000..c5c111d
--- /dev/null
+++ b/src/components/navbar/navbar.module.css
@@ -0,0 +1,17 @@
+.titleContainer {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: center;
+}
+
+.logo {
+ border-radius: 25px;
+ margin-right: 8px;
+}
+
+.title {
+ color: white;
+ font-size: 1.5rem;
+ font-weight: 600;
+}
\ No newline at end of file
diff --git a/src/pages/_app.js b/src/pages/_app.js
index 2300201..3f6f1e5 100644
--- a/src/pages/_app.js
+++ b/src/pages/_app.js
@@ -1,5 +1,11 @@
-import '@/styles/globals.css'
+import { PrimeReactProvider } from 'primereact/api';
+// import '@/styles/globals.css'
+import 'primereact/resources/themes/lara-dark-purple/theme.css';
-export default function App({ Component, pageProps }) {
- return
-}
+export default function MyApp({ Component, pageProps }) {
+ return (
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/pages/index.js b/src/pages/index.js
index 7d0373d..a9b28d0 100644
--- a/src/pages/index.js
+++ b/src/pages/index.js
@@ -1,9 +1,7 @@
import Head from 'next/head'
-import Image from 'next/image'
-import { Inter } from 'next/font/google'
import styles from '@/styles/Home.module.css'
+import Navbar from '@/components/navbar/Navbar'
-const inter = Inter({ subsets: ['latin'] })
export default function Home() {
return (
@@ -14,100 +12,8 @@ export default function Home() {
-
-
-
- Get started by editing
- src/pages/index.js
-
-
-
-
-
-
-
-
-
+
+
>
)
diff --git a/src/styles/Home.module.css b/src/styles/Home.module.css
index 7b8e4f9..82f1863 100644
--- a/src/styles/Home.module.css
+++ b/src/styles/Home.module.css
@@ -1,9 +1,6 @@
.main {
display: flex;
flex-direction: column;
- justify-content: space-between;
- align-items: center;
- padding: 6rem;
min-height: 100vh;
}
diff --git a/src/styles/globals.css b/src/styles/globals.css
index d4f491e..f00ce7c 100644
--- a/src/styles/globals.css
+++ b/src/styles/globals.css
@@ -104,4 +104,4 @@ a {
html {
color-scheme: dark;
}
-}
+}
\ No newline at end of file