8 | )
9 | }
10 |
11 | export default Loading;
12 |
--------------------------------------------------------------------------------
/components/Nl2br.tsx:
--------------------------------------------------------------------------------
1 | const Nl2br = ({ children }: { children: string }) => (
2 | <>
3 | {children.split(/(\n)/g).map((t, index) => (t === '\n' ? : t))}
4 | >
5 | )
6 |
7 | export default Nl2br;
8 |
--------------------------------------------------------------------------------
/constants/api.ts:
--------------------------------------------------------------------------------
1 | import "server-only";
2 | export const apiUrl = "http://127.0.0.1:3000/api";
3 |
--------------------------------------------------------------------------------
/globals/db.ts:
--------------------------------------------------------------------------------
1 | // https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices
2 | import { PrismaClient } from '@prisma/client';
3 | import "server-only";
4 |
5 | const globalForPrisma = global as unknown as { prisma: PrismaClient }
6 |
7 | export const prisma =
8 | globalForPrisma.prisma ||
9 | new PrismaClient({
10 | log: ['query'],
11 | })
12 |
13 | if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
14 |
--------------------------------------------------------------------------------
/next.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const nextConfig = {
3 | experimental: {
4 | appDir: true,
5 | typedRoutes: true,
6 | },
7 | }
8 |
9 | module.exports = nextConfig
10 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nextjs-app-directory-demo",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start",
9 | "lint": "next lint"
10 | },
11 | "prisma": {
12 | "seed": "ts-node --compiler-options {\"module\":\"CommonJS\"} prisma/seed.ts"
13 | },
14 | "dependencies": {
15 | "@prisma/client": "^4.11.0",
16 | "@types/node": "18.14.2",
17 | "@types/react": "18.0.28",
18 | "@types/react-dom": "18.0.11",
19 | "eslint": "8.35.0",
20 | "eslint-config-next": "13.2.1",
21 | "next": "13.2.1",
22 | "react": "18.2.0",
23 | "react-dom": "18.2.0",
24 | "server-only": "^0.0.1",
25 | "sharp": "^0.31.3",
26 | "swr": "^2.0.4",
27 | "typescript": "4.9.5",
28 | "zod": "^3.20.6"
29 | },
30 | "devDependencies": {
31 | "autoprefixer": "^10.4.13",
32 | "postcss": "^8.4.21",
33 | "prisma": "^4.11.0",
34 | "tailwindcss": "^3.2.7",
35 | "ts-node": "^10.9.1"
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/prisma/.gitignore:
--------------------------------------------------------------------------------
1 | dev.db*
2 |
--------------------------------------------------------------------------------
/prisma/migrations/20230301183727_init/migration.sql:
--------------------------------------------------------------------------------
1 | -- CreateTable
2 | CREATE TABLE "metadata" (
3 | "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
4 | "key" TEXT NOT NULL,
5 | "value" TEXT NOT NULL
6 | );
7 |
8 | -- CreateTable
9 | CREATE TABLE "notes" (
10 | "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
11 | "title" TEXT NOT NULL,
12 | "body" TEXT NOT NULL,
13 | "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
14 | "updated_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
15 | );
16 |
17 | -- CreateIndex
18 | CREATE UNIQUE INDEX "metadata_key_key" ON "metadata"("key");
19 |
--------------------------------------------------------------------------------
/prisma/migrations/migration_lock.toml:
--------------------------------------------------------------------------------
1 | # Please do not edit this file manually
2 | # It should be added in your version-control system (i.e. Git)
3 | provider = "sqlite"
--------------------------------------------------------------------------------
/prisma/schema.prisma:
--------------------------------------------------------------------------------
1 | // This is your Prisma schema file,
2 | // learn more about it in the docs: https://pris.ly/d/prisma-schema
3 |
4 | generator client {
5 | provider = "prisma-client-js"
6 | }
7 |
8 | datasource db {
9 | provider = "sqlite"
10 | url = env("DATABASE_URL")
11 | }
12 |
13 | model Metadata {
14 | id Int @id @default(autoincrement())
15 | key String @unique
16 | value String
17 |
18 | @@map("metadata")
19 | }
20 |
21 | model Note {
22 | id Int @id @default(autoincrement())
23 | title String
24 | body String
25 | createdAt DateTime @default(now()) @map("created_at")
26 | updatedAt DateTime @default(now()) @map("updated_at")
27 |
28 | @@map("notes")
29 | }
30 |
--------------------------------------------------------------------------------
/prisma/seed.ts:
--------------------------------------------------------------------------------
1 | import { Prisma, PrismaClient } from '@prisma/client';
2 |
3 | const prisma = new PrismaClient()
4 |
5 | async function main() {
6 | // delete all
7 | await prisma.metadata.deleteMany();
8 | await prisma.note.deleteMany();
9 | // seeding
10 | const metadatas: Prisma.MetadataCreateInput[] = [
11 | {
12 | key: "version",
13 | value: "13.2.1",
14 | },
15 | {
16 | key: "faq",
17 | value: faq,
18 | },
19 | {
20 | key: "tos",
21 | value: tos,
22 | },
23 | ];
24 | for (const metadata of metadatas) {
25 | await prisma.metadata.create({
26 | data: metadata
27 | });
28 | }
29 |
30 | const notes: Prisma.NoteCreateInput[] = [
31 | {
32 | title: "First note",
33 | body: "This is the first note.",
34 | },
35 | {
36 | title: "Second note",
37 | body: "This is the second note.",
38 | },
39 | {
40 | title: "Third note",
41 | body: "This is the third note.",
42 | },
43 | {
44 | title: "Fourth note",
45 | body: "This is the fourth note.",
46 | },
47 | ];
48 | for (const note of notes) {
49 | await prisma.note.create({
50 | data: note
51 | })
52 | }
53 | }
54 |
55 | main()
56 | .then(async () => {
57 | await prisma.$disconnect()
58 | })
59 | .catch(async (e) => {
60 | console.error(e)
61 | await prisma.$disconnect()
62 | process.exit(1)
63 | });
64 |
65 | const faq = `
66 | Q: How do I create a new note?
67 | A: To create a new note, click the "New Note" button located in the top left corner of the screen. This will open a blank note where you can begin typing.
68 |
69 | Q: Can I customize the appearance of my notes?
70 | A: Yes, you can customize the appearance of your notes by changing the font, font size, and background color. Simply click the "Settings" button and select "Appearance" to make these changes.
71 |
72 | Q: Can I share my notes with others?
73 | A: Yes, you can share your notes with others by clicking the "Share" button located at the bottom of the note. You can then enter the email address of the person you wish to share the note with.
74 |
75 | Q: How do I delete a note?
76 | A: To delete a note, click on the note you wish to delete and then click the "Delete" button located at the bottom of the note.
77 |
78 | Q: Is my data secure?
79 | A: Yes, we take the security and privacy of your data very seriously. All notes are stored on secure servers and are encrypted for added protection.
80 |
81 | Q: Can I access my notes on multiple devices?
82 | A: Yes, you can access your notes on multiple devices by logging into your account on our website. All notes will be synced across all devices.
83 |
84 | Q: What happens if I forget my password?
85 | A: If you forget your password, you can reset it by clicking the "Forgot Password" link located on the login page. You will then be prompted to enter your email address to receive instructions on how to reset your password.
86 |
87 | Q: Do you offer a mobile app?
88 | A: Yes, we offer a mobile app for both iOS and Android devices. You can download the app from the App Store or Google Play.
89 | `
90 | const tos = `
91 | Welcome to our website. These Terms of Service ("TOS") govern your use of our website, including any content, functionality, and services offered on or through the website. By using our website, you accept and agree to be bound by these TOS. If you do not agree with these TOS, you may not use our website.
92 |
93 | User Conduct
94 | You agree to use our website only for lawful purposes and in a manner that does not violate the rights of any third party. You agree not to use our website in any way that could damage, disable, overburden, or impair our servers or networks. You also agree not to access or attempt to access any information or data on our website that you are not authorized to access.
95 |
96 | Intellectual Property
97 | All content on our website, including text, graphics, logos, images, and software, is owned by us or our licensors and is protected by copyright and other intellectual property laws. You may not copy, distribute, modify, or create derivative works of any content on our website without our prior written consent.
98 |
99 | Disclaimer of Warranties
100 | Our website is provided "as is" and without warranties of any kind, either express or implied. We do not warrant that our website will be uninterrupted or error-free, that defects will be corrected, or that our website or the servers that make it available are free of viruses or other harmful components.
101 |
102 | Limitation of Liability
103 | In no event shall we be liable for any direct, indirect, incidental, consequential, special, or exemplary damages arising from or in connection with your use of our website, even if we have been advised of the possibility of such damages. Our liability to you for any cause whatsoever, and regardless of the form of the action, will at all times be limited to the amount paid by you, if any, to access our website.
104 |
105 | Indemnification
106 | You agree to indemnify, defend, and hold us harmless from any claim, demand, or damage, including reasonable attorneys' fees, arising out of your use of our website, your violation of these TOS, or your violation of any rights of another.
107 |
108 | Governing Law and Jurisdiction
109 | These TOS and any disputes arising out of or related to your use of our website will be governed by and construed in accordance with the laws of [insert jurisdiction], without giving effect to any principles of conflicts of law. Any legal action or proceeding arising out of or related to these TOS or your use of our website shall be brought exclusively in [insert court of jurisdiction], and you consent to the jurisdiction of such courts.
110 |
111 | Modifications to these TOS
112 | We reserve the right to modify these TOS at any time without notice. Your continued use of our website following any such modification constitutes your agreement to be bound by the modified TOS.
113 | `;
114 |
--------------------------------------------------------------------------------
/public/cover.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tim0401/nextjs-app-directory-demo/0d0572a7042fc5125fc92da6a6dd6b9dbdbe9c9e/public/cover.jpeg
--------------------------------------------------------------------------------
/public/next.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | module.exports = {
3 | content: [
4 | "./app/**/*.{js,ts,jsx,tsx}",
5 | "./components/**/*.{js,ts,jsx,tsx}",
6 | ],
7 | theme: {
8 | extend: {},
9 | },
10 | plugins: [],
11 | }
12 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "strict": true,
8 | "forceConsistentCasingInFileNames": true,
9 | "noEmit": true,
10 | "esModuleInterop": true,
11 | "module": "esnext",
12 | "moduleResolution": "node",
13 | "resolveJsonModule": true,
14 | "isolatedModules": true,
15 | "jsx": "preserve",
16 | "incremental": true,
17 | "plugins": [
18 | {
19 | "name": "next"
20 | }
21 | ],
22 | "paths": {
23 | "@/*": ["./*"]
24 | }
25 | },
26 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
27 | "exclude": ["node_modules"]
28 | }
29 |
--------------------------------------------------------------------------------