patra-turbo-template 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +81 -0
- package/cli.js +47 -0
- package/package.json +30 -0
- package/template/README.md +20 -0
- package/template/apps/http-server/README.md +1 -0
- package/template/apps/http-server/index.ts +35 -0
- package/template/apps/http-server/package.json +22 -0
- package/template/apps/web/README.md +1 -0
- package/template/apps/web/app/favicon.ico +0 -0
- package/template/apps/web/app/fonts/GeistMonoVF.woff +0 -0
- package/template/apps/web/app/fonts/GeistVF.woff +0 -0
- package/template/apps/web/app/globals.css +1 -0
- package/template/apps/web/app/layout.tsx +31 -0
- package/template/apps/web/app/page.module.css +186 -0
- package/template/apps/web/app/page.tsx +25 -0
- package/template/apps/web/eslint.config.js +4 -0
- package/template/apps/web/next.config.js +4 -0
- package/template/apps/web/package.json +28 -0
- package/template/apps/web/postcss.config.mjs +7 -0
- package/template/apps/web/tsconfig.json +20 -0
- package/template/apps/ws-server/README.md +1 -0
- package/template/apps/ws-server/index.ts +25 -0
- package/template/apps/ws-server/package.json +27 -0
- package/template/apps/ws-server/tsconfig.json +29 -0
- package/template/bun.lock +1163 -0
- package/template/package.json +30 -0
- package/template/packages/db/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc +111 -0
- package/template/packages/db/README.md +15 -0
- package/template/packages/db/index.ts +19 -0
- package/template/packages/db/package.json +22 -0
- package/template/packages/db/prisma/schema.prisma +20 -0
- package/template/packages/db/prisma.config.ts +14 -0
- package/template/packages/db/tsconfig.json +29 -0
- package/template/packages/eslint-config/README.md +3 -0
- package/template/packages/eslint-config/base.js +32 -0
- package/template/packages/eslint-config/next.js +57 -0
- package/template/packages/eslint-config/package.json +24 -0
- package/template/packages/eslint-config/react-internal.js +39 -0
- package/template/packages/typescript-config/base.json +19 -0
- package/template/packages/typescript-config/nextjs.json +12 -0
- package/template/packages/typescript-config/package.json +14 -0
- package/template/packages/typescript-config/react-library.json +7 -0
- package/template/packages/ui/eslint.config.mjs +4 -0
- package/template/packages/ui/package.json +26 -0
- package/template/packages/ui/src/button.tsx +20 -0
- package/template/packages/ui/src/card.tsx +27 -0
- package/template/packages/ui/src/code.tsx +11 -0
- package/template/packages/ui/tsconfig.json +8 -0
- package/template/turbo.json +21 -0
package/README.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# patra-turbo-template
|
|
2
|
+
|
|
3
|
+
Scaffold a new Turborepo monorepo from the turbo-template (Next.js, Express, WebSocket, Prisma, Tailwind).
|
|
4
|
+
|
|
5
|
+
**Layout:** Both the npm package and the template live under `template/`:
|
|
6
|
+
- `template/create-turbo-template/` – this package (publish to npm)
|
|
7
|
+
- `template/turbo-template/` – the monorepo template (source for scaffolding)
|
|
8
|
+
|
|
9
|
+
## What to do next
|
|
10
|
+
|
|
11
|
+
1. **Bundle the template into the package** (so it’s included when you publish):
|
|
12
|
+
```bash
|
|
13
|
+
cd template/create-turbo-template
|
|
14
|
+
bun run copy-template
|
|
15
|
+
```
|
|
16
|
+
This copies `../turbo-template` into `./template` (creates `template/create-turbo-template/template/` with the app).
|
|
17
|
+
|
|
18
|
+
2. **Test locally** (from any empty folder):
|
|
19
|
+
```bash
|
|
20
|
+
node path/to/template/create-turbo-template/cli.js my-test-app
|
|
21
|
+
cd my-test-app && bun install && bun run dev
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
3. **Publish to npm**
|
|
25
|
+
Open a terminal, go into this package folder, then run:
|
|
26
|
+
```bash
|
|
27
|
+
cd path/to/CI_CD/template/create-turbo-template
|
|
28
|
+
npm login
|
|
29
|
+
npm publish
|
|
30
|
+
```
|
|
31
|
+
(Replace `path/to/CI_CD` with your actual path, e.g. `C:\Users\patra\Desktop\Devops_prac\CI_CD` on Windows.)
|
|
32
|
+
`prepublishOnly` will run `copy-template` again before packing, so the tarball always has an up-to-date `template/`.
|
|
33
|
+
|
|
34
|
+
## Usage (after publish)
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npx create-turbo-template my-app
|
|
38
|
+
cd my-app
|
|
39
|
+
bun install
|
|
40
|
+
bun run dev
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Or with npm:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npm create turbo-template@latest my-app
|
|
47
|
+
cd my-app
|
|
48
|
+
bun install
|
|
49
|
+
bun run dev
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Publishing to npm
|
|
53
|
+
|
|
54
|
+
1. **One-time: copy the template into the package**
|
|
55
|
+
```bash
|
|
56
|
+
cd create-turbo-template
|
|
57
|
+
bun run copy-template
|
|
58
|
+
```
|
|
59
|
+
This copies `../turbo-template` into `./template` (excluding node_modules, .git, etc.).
|
|
60
|
+
|
|
61
|
+
2. **Publish**
|
|
62
|
+
- If you don’t have an npm account: [npmjs.com](https://www.npmjs.com/signup)
|
|
63
|
+
- npm requires **two-factor authentication (2FA)** to publish. Enable it at [npmjs.com → Account → Security](https://www.npmjs.com/settings/~/account).
|
|
64
|
+
- Login: `npm login`
|
|
65
|
+
- Publish (choose one):
|
|
66
|
+
- **Unscoped (name must be free):** `npm publish`
|
|
67
|
+
- **Scoped (e.g. @yourusername/turbo-template):** change `"name": "create-turbo-template"` to `"name": "@yourusername/create-turbo-template"` in package.json, then `npm publish --access public`
|
|
68
|
+
|
|
69
|
+
3. **Later: after changing turbo-template**
|
|
70
|
+
- Run `bun run copy-template` again in `create-turbo-template`
|
|
71
|
+
- Bump version in package.json (e.g. `1.0.1`)
|
|
72
|
+
- Run `npm publish`
|
|
73
|
+
|
|
74
|
+
## What gets created
|
|
75
|
+
|
|
76
|
+
- `apps/web` – Next.js (port 3000)
|
|
77
|
+
- `apps/http-server` – Express API (port 3002)
|
|
78
|
+
- `apps/ws-server` – WebSocket server (port 3001)
|
|
79
|
+
- `packages/db` – Prisma + PostgreSQL
|
|
80
|
+
- `packages/ui` – Shared React components
|
|
81
|
+
- `packages/eslint-config`, `packages/typescript-config` – Shared configs
|
package/cli.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { mkdir, cp, readdir, readFile, writeFile } from "node:fs/promises";
|
|
4
|
+
import { join, dirname } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const TEMPLATE_DIR = join(__dirname, "template");
|
|
9
|
+
|
|
10
|
+
async function copyRecursive(src, dest) {
|
|
11
|
+
await mkdir(dest, { recursive: true });
|
|
12
|
+
const entries = await readdir(src, { withFileTypes: true });
|
|
13
|
+
for (const entry of entries) {
|
|
14
|
+
const srcPath = join(src, entry.name);
|
|
15
|
+
const destPath = join(dest, entry.name);
|
|
16
|
+
if (entry.isDirectory()) {
|
|
17
|
+
await copyRecursive(srcPath, destPath);
|
|
18
|
+
} else {
|
|
19
|
+
await cp(srcPath, destPath);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async function main() {
|
|
25
|
+
const projectName = process.argv[2] || "my-turbo-app";
|
|
26
|
+
const targetDir = join(process.cwd(), projectName);
|
|
27
|
+
|
|
28
|
+
console.log(`Creating ${projectName} from turbo-template...`);
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
await copyRecursive(TEMPLATE_DIR, targetDir);
|
|
32
|
+
const pkgPath = join(targetDir, "package.json");
|
|
33
|
+
const pkg = JSON.parse(await readFile(pkgPath, "utf8"));
|
|
34
|
+
pkg.name = projectName;
|
|
35
|
+
await writeFile(pkgPath, JSON.stringify(pkg, null, 2));
|
|
36
|
+
console.log(`Done. Next steps:\n cd ${projectName}\n bun install\n bun run dev`);
|
|
37
|
+
} catch (err) {
|
|
38
|
+
if (err.code === "ENOENT" && err.path === TEMPLATE_DIR) {
|
|
39
|
+
console.error("Error: template folder not found. Run 'npm run copy-template' in the package directory before publishing.");
|
|
40
|
+
} else {
|
|
41
|
+
console.error(err);
|
|
42
|
+
}
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
main();
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "patra-turbo-template",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Scaffold a new project from the turbo-template monorepo (Next.js, Express, WebSocket, Prisma, Tailwind)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"create-turbo-template": "./cli.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"cli.js",
|
|
11
|
+
"template"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"copy-template": "node copy-template.js",
|
|
15
|
+
"prepublishOnly": "node copy-template.js"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"turborepo",
|
|
19
|
+
"monorepo",
|
|
20
|
+
"template",
|
|
21
|
+
"next.js",
|
|
22
|
+
"prisma",
|
|
23
|
+
"express",
|
|
24
|
+
"scaffold"
|
|
25
|
+
],
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"engines": {
|
|
28
|
+
"node": ">=18"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Turborepo-template
|
|
2
|
+
This is a self managed turborepo for use in future and/or current projects
|
|
3
|
+
Frontend on: 3000
|
|
4
|
+
Websocket: 3001
|
|
5
|
+
http-server: 3002
|
|
6
|
+
|
|
7
|
+
- This was made to fix my repeated workspace issues in configuring a turborepo with
|
|
8
|
+
- websockets
|
|
9
|
+
- http server
|
|
10
|
+
- prisma DB
|
|
11
|
+
- next FE
|
|
12
|
+
|
|
13
|
+
- To be added soon
|
|
14
|
+
- [ ] Tailwind setup
|
|
15
|
+
- [ ] custom Razorpay FE and BE setup.
|
|
16
|
+
|
|
17
|
+
This set up is functional and tested. this is to be used whenever one needs a mono repo with all these configured
|
|
18
|
+
|
|
19
|
+
Maintained by: Abhinav Patra
|
|
20
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# `http-server`
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import express from "express";
|
|
2
|
+
import cors from "cors"
|
|
3
|
+
|
|
4
|
+
import { client } from "db/client"
|
|
5
|
+
|
|
6
|
+
const app = express();
|
|
7
|
+
app.use(express.json());
|
|
8
|
+
app.use(cors());
|
|
9
|
+
|
|
10
|
+
app.get('/', (req, res) => {
|
|
11
|
+
return res.json({
|
|
12
|
+
"message":"/ endpoint"
|
|
13
|
+
})
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
app.post('/signup', async(req, res) => {
|
|
17
|
+
const username = req.body.username;
|
|
18
|
+
const password = req.body.password;
|
|
19
|
+
console.log(password);
|
|
20
|
+
const user = await client.user.create({
|
|
21
|
+
data: {
|
|
22
|
+
username: username,
|
|
23
|
+
password: password
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
console.log(user);
|
|
27
|
+
res.send({
|
|
28
|
+
"message": "hello user, you have signed up",
|
|
29
|
+
"user details": user
|
|
30
|
+
})
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
app.listen(3002, () => {
|
|
34
|
+
console.log("http server Listening on port 3002")
|
|
35
|
+
})
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "http-server",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "bun run index.ts",
|
|
7
|
+
"build": "echo 'Add build script here'",
|
|
8
|
+
"test": "echo 'Add test script here'",
|
|
9
|
+
"lint": "echo 'Add lint script here'"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@types/cors": "^2.8.19",
|
|
13
|
+
"cors": "^2.8.6",
|
|
14
|
+
"express": "^5.2.1"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@repo/eslint-config": "*",
|
|
18
|
+
"@repo/typescript-config": "*",
|
|
19
|
+
"@types/express": "^5.0.6",
|
|
20
|
+
"db": "workspace:*"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Frontend
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import "tailwindcss";
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Metadata } from "next";
|
|
2
|
+
import localFont from "next/font/local";
|
|
3
|
+
import "./globals.css";
|
|
4
|
+
|
|
5
|
+
const geistSans = localFont({
|
|
6
|
+
src: "./fonts/GeistVF.woff",
|
|
7
|
+
variable: "--font-geist-sans",
|
|
8
|
+
});
|
|
9
|
+
const geistMono = localFont({
|
|
10
|
+
src: "./fonts/GeistMonoVF.woff",
|
|
11
|
+
variable: "--font-geist-mono",
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
export const metadata: Metadata = {
|
|
15
|
+
title: "Create Next App",
|
|
16
|
+
description: "Generated by create next app",
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export default function RootLayout({
|
|
20
|
+
children,
|
|
21
|
+
}: Readonly<{
|
|
22
|
+
children: React.ReactNode;
|
|
23
|
+
}>) {
|
|
24
|
+
return (
|
|
25
|
+
<html lang="en">
|
|
26
|
+
<body className={`${geistSans.variable} ${geistMono.variable}`}>
|
|
27
|
+
{children}
|
|
28
|
+
</body>
|
|
29
|
+
</html>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
.page {
|
|
2
|
+
--gray-rgb: 0, 0, 0;
|
|
3
|
+
--gray-alpha-200: rgba(var(--gray-rgb), 0.08);
|
|
4
|
+
--gray-alpha-100: rgba(var(--gray-rgb), 0.05);
|
|
5
|
+
|
|
6
|
+
--button-primary-hover: #383838;
|
|
7
|
+
--button-secondary-hover: #f2f2f2;
|
|
8
|
+
|
|
9
|
+
display: grid;
|
|
10
|
+
grid-template-rows: 20px 1fr 20px;
|
|
11
|
+
align-items: center;
|
|
12
|
+
justify-items: center;
|
|
13
|
+
min-height: 100svh;
|
|
14
|
+
padding: 80px;
|
|
15
|
+
gap: 64px;
|
|
16
|
+
font-synthesis: none;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@media (prefers-color-scheme: dark) {
|
|
20
|
+
.page {
|
|
21
|
+
--gray-rgb: 255, 255, 255;
|
|
22
|
+
--gray-alpha-200: rgba(var(--gray-rgb), 0.145);
|
|
23
|
+
--gray-alpha-100: rgba(var(--gray-rgb), 0.06);
|
|
24
|
+
|
|
25
|
+
--button-primary-hover: #ccc;
|
|
26
|
+
--button-secondary-hover: #1a1a1a;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.main {
|
|
31
|
+
display: flex;
|
|
32
|
+
flex-direction: column;
|
|
33
|
+
gap: 32px;
|
|
34
|
+
grid-row-start: 2;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.main ol {
|
|
38
|
+
font-family: var(--font-geist-mono);
|
|
39
|
+
padding-left: 0;
|
|
40
|
+
margin: 0;
|
|
41
|
+
font-size: 14px;
|
|
42
|
+
line-height: 24px;
|
|
43
|
+
letter-spacing: -0.01em;
|
|
44
|
+
list-style-position: inside;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.main li:not(:last-of-type) {
|
|
48
|
+
margin-bottom: 8px;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.main code {
|
|
52
|
+
font-family: inherit;
|
|
53
|
+
background: var(--gray-alpha-100);
|
|
54
|
+
padding: 2px 4px;
|
|
55
|
+
border-radius: 4px;
|
|
56
|
+
font-weight: 600;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.ctas {
|
|
60
|
+
display: flex;
|
|
61
|
+
gap: 16px;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.ctas a {
|
|
65
|
+
appearance: none;
|
|
66
|
+
border-radius: 128px;
|
|
67
|
+
height: 48px;
|
|
68
|
+
padding: 0 20px;
|
|
69
|
+
font-family: var(--font-geist-sans);
|
|
70
|
+
border: 1px solid transparent;
|
|
71
|
+
transition: background 0.2s, color 0.2s, border-color 0.2s;
|
|
72
|
+
cursor: pointer;
|
|
73
|
+
display: flex;
|
|
74
|
+
align-items: center;
|
|
75
|
+
justify-content: center;
|
|
76
|
+
font-size: 16px;
|
|
77
|
+
line-height: 20px;
|
|
78
|
+
font-weight: 500;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
a.primary {
|
|
82
|
+
background: var(--foreground);
|
|
83
|
+
color: var(--background);
|
|
84
|
+
gap: 8px;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
a.secondary {
|
|
88
|
+
border-color: var(--gray-alpha-200);
|
|
89
|
+
min-width: 180px;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
button.secondary {
|
|
93
|
+
appearance: none;
|
|
94
|
+
border-radius: 128px;
|
|
95
|
+
height: 48px;
|
|
96
|
+
padding: 0 20px;
|
|
97
|
+
font-family: var(--font-geist-sans);
|
|
98
|
+
border: 1px solid transparent;
|
|
99
|
+
transition: background 0.2s, color 0.2s, border-color 0.2s;
|
|
100
|
+
cursor: pointer;
|
|
101
|
+
display: flex;
|
|
102
|
+
align-items: center;
|
|
103
|
+
justify-content: center;
|
|
104
|
+
font-size: 16px;
|
|
105
|
+
line-height: 20px;
|
|
106
|
+
font-weight: 500;
|
|
107
|
+
background: transparent;
|
|
108
|
+
border-color: var(--gray-alpha-200);
|
|
109
|
+
min-width: 180px;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.footer {
|
|
113
|
+
font-family: var(--font-geist-sans);
|
|
114
|
+
grid-row-start: 3;
|
|
115
|
+
display: flex;
|
|
116
|
+
gap: 24px;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.footer a {
|
|
120
|
+
display: flex;
|
|
121
|
+
align-items: center;
|
|
122
|
+
gap: 8px;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.footer img {
|
|
126
|
+
flex-shrink: 0;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/* Enable hover only on non-touch devices */
|
|
130
|
+
@media (hover: hover) and (pointer: fine) {
|
|
131
|
+
a.primary:hover {
|
|
132
|
+
background: var(--button-primary-hover);
|
|
133
|
+
border-color: transparent;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
a.secondary:hover {
|
|
137
|
+
background: var(--button-secondary-hover);
|
|
138
|
+
border-color: transparent;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.footer a:hover {
|
|
142
|
+
text-decoration: underline;
|
|
143
|
+
text-underline-offset: 4px;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
@media (max-width: 600px) {
|
|
148
|
+
.page {
|
|
149
|
+
padding: 32px;
|
|
150
|
+
padding-bottom: 80px;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.main {
|
|
154
|
+
align-items: center;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.main ol {
|
|
158
|
+
text-align: center;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.ctas {
|
|
162
|
+
flex-direction: column;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.ctas a {
|
|
166
|
+
font-size: 14px;
|
|
167
|
+
height: 40px;
|
|
168
|
+
padding: 0 16px;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
a.secondary {
|
|
172
|
+
min-width: auto;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.footer {
|
|
176
|
+
flex-wrap: wrap;
|
|
177
|
+
align-items: center;
|
|
178
|
+
justify-content: center;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
@media (prefers-color-scheme: dark) {
|
|
183
|
+
.logo {
|
|
184
|
+
filter: invert();
|
|
185
|
+
}
|
|
186
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import Image, { type ImageProps } from "next/image";
|
|
2
|
+
|
|
3
|
+
type Props = Omit<ImageProps, "src"> & {
|
|
4
|
+
srcLight: string;
|
|
5
|
+
srcDark: string;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const ThemeImage = (props: Props) => {
|
|
9
|
+
const { srcLight, srcDark, ...rest } = props;
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<>
|
|
13
|
+
<Image {...rest} src={srcLight} className="imgLight" />
|
|
14
|
+
<Image {...rest} src={srcDark} className="imgDark" />
|
|
15
|
+
</>
|
|
16
|
+
);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export default function Home() {
|
|
20
|
+
return (
|
|
21
|
+
<div className="">
|
|
22
|
+
<h1>Hello World</h1>
|
|
23
|
+
</div>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "web",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"private": true,
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "next dev --port 3000",
|
|
8
|
+
"build": "next build",
|
|
9
|
+
"start": "next start",
|
|
10
|
+
"lint": "eslint --max-warnings 0",
|
|
11
|
+
"check-types": "next typegen && tsc --noEmit"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@repo/ui": "*",
|
|
15
|
+
"next": "16.1.5",
|
|
16
|
+
"react": "^19.2.0",
|
|
17
|
+
"react-dom": "^19.2.0"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@repo/eslint-config": "*",
|
|
21
|
+
"@repo/typescript-config": "*",
|
|
22
|
+
"@types/node": "^22.15.3",
|
|
23
|
+
"@types/react": "19.2.2",
|
|
24
|
+
"@types/react-dom": "19.2.2",
|
|
25
|
+
"eslint": "^9.39.1",
|
|
26
|
+
"typescript": "5.9.2"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "@repo/typescript-config/nextjs.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"plugins": [
|
|
5
|
+
{
|
|
6
|
+
"name": "next"
|
|
7
|
+
}
|
|
8
|
+
]
|
|
9
|
+
},
|
|
10
|
+
"include": [
|
|
11
|
+
"**/*.ts",
|
|
12
|
+
"**/*.tsx",
|
|
13
|
+
"next-env.d.ts",
|
|
14
|
+
"next.config.js",
|
|
15
|
+
".next/types/**/*.ts"
|
|
16
|
+
],
|
|
17
|
+
"exclude": [
|
|
18
|
+
"node_modules"
|
|
19
|
+
]
|
|
20
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# `ws-server`
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { WebSocketServer } from "ws";
|
|
2
|
+
import { client } from "db/client"
|
|
3
|
+
|
|
4
|
+
const server = new WebSocketServer({
|
|
5
|
+
port: 3001
|
|
6
|
+
},() => {
|
|
7
|
+
console.log("WebSocket server is running on port 3001");
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
server.on("connection", async (socket) => {
|
|
11
|
+
const num = Math.random() * 100;
|
|
12
|
+
await client.user.create({
|
|
13
|
+
data: {
|
|
14
|
+
username: `Abhinav${num}`,
|
|
15
|
+
password: "12345678"
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
console.log("user connected");
|
|
20
|
+
socket.send("Connected to the websocket from turbo repo ws-server")
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
server.on("error", (error) => {
|
|
24
|
+
console.error("WebSocket server error:", error);
|
|
25
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ws-server",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "bun run index.ts",
|
|
7
|
+
"build": "echo 'Add build script here'",
|
|
8
|
+
"test": "echo 'Add test script here'",
|
|
9
|
+
"lint": "echo 'Add lint script here'"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@repo/eslint-config": "*",
|
|
13
|
+
"@repo/typescript-config": "*",
|
|
14
|
+
"@repo/ui": "*",
|
|
15
|
+
"@types/ws": "^8.18.1",
|
|
16
|
+
"db": "*",
|
|
17
|
+
"ws": "^8.19.0"
|
|
18
|
+
},
|
|
19
|
+
"module": "index.ts",
|
|
20
|
+
"type": "module",
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@types/bun": "latest"
|
|
23
|
+
},
|
|
24
|
+
"peerDependencies": {
|
|
25
|
+
"typescript": "^5"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
// Environment setup & latest features
|
|
4
|
+
"lib": ["ESNext"],
|
|
5
|
+
"target": "ESNext",
|
|
6
|
+
"module": "Preserve",
|
|
7
|
+
"moduleDetection": "force",
|
|
8
|
+
"jsx": "react-jsx",
|
|
9
|
+
"allowJs": true,
|
|
10
|
+
|
|
11
|
+
// Bundler mode
|
|
12
|
+
"moduleResolution": "bundler",
|
|
13
|
+
"allowImportingTsExtensions": true,
|
|
14
|
+
"verbatimModuleSyntax": true,
|
|
15
|
+
"noEmit": true,
|
|
16
|
+
|
|
17
|
+
// Best practices
|
|
18
|
+
"strict": true,
|
|
19
|
+
"skipLibCheck": true,
|
|
20
|
+
"noFallthroughCasesInSwitch": true,
|
|
21
|
+
"noUncheckedIndexedAccess": true,
|
|
22
|
+
"noImplicitOverride": true,
|
|
23
|
+
|
|
24
|
+
// Some stricter flags (disabled by default)
|
|
25
|
+
"noUnusedLocals": false,
|
|
26
|
+
"noUnusedParameters": false,
|
|
27
|
+
"noPropertyAccessFromIndexSignature": false
|
|
28
|
+
}
|
|
29
|
+
}
|