migrate to monorepo
parent
db48c7c962
commit
3f267afb84
|
@ -0,0 +1 @@
|
||||||
|
/nix/store/0yw3h1p66cx0yr3yg4z90v1n0pqj1jnf-source
|
|
@ -0,0 +1 @@
|
||||||
|
/nix/store/477zl9l6k5vjdzfvj4gp577lgh9cml80-source
|
|
@ -0,0 +1 @@
|
||||||
|
/nix/store/9cj1830pvd88lrwmmxw65achd3lw2q9n-source
|
|
@ -0,0 +1 @@
|
||||||
|
/nix/store/gpn8846qjzkyn19m61x33zshhhnb5zmz-source
|
|
@ -0,0 +1 @@
|
||||||
|
/nix/store/q3dc8i1zdl3870mp56ff0rkz1hzc55ry-source
|
|
@ -0,0 +1 @@
|
||||||
|
/nix/store/sk4ga2wy0b02k7pnzakwq4r3jdknda4g-source
|
|
@ -0,0 +1 @@
|
||||||
|
/nix/store/y0vjv4jpzrwdw0x5m4p9c2p4w7mrcz3w-source
|
|
@ -0,0 +1 @@
|
||||||
|
/nix/store/pvhv7qw9cbdldpid1kdw43l83kqg2ds5-nix-shell-env
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,4 @@
|
||||||
|
if command -v nix-shell &> /dev/null
|
||||||
|
then
|
||||||
|
use flake
|
||||||
|
fi
|
|
@ -0,0 +1,10 @@
|
||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
// This tells ESLint to load the config from the package `eslint-config-custom`
|
||||||
|
extends: ["custom"],
|
||||||
|
settings: {
|
||||||
|
next: {
|
||||||
|
rootDir: ["apps/*/"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
|
@ -0,0 +1,33 @@
|
||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
node_modules
|
||||||
|
.pnp
|
||||||
|
.pnp.js
|
||||||
|
|
||||||
|
# testing
|
||||||
|
coverage
|
||||||
|
|
||||||
|
# next.js
|
||||||
|
.next/
|
||||||
|
out/
|
||||||
|
build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
*.pem
|
||||||
|
|
||||||
|
# debug
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
.pnpm-debug.log*
|
||||||
|
|
||||||
|
# local env files
|
||||||
|
.env.local
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
|
||||||
|
# turbo
|
||||||
|
.turbo
|
|
@ -0,0 +1,79 @@
|
||||||
|
# Felia
|
||||||
|
|
||||||
|
Scaffolded by `pnpm create turbo@latest`
|
||||||
|
|
||||||
|
This project manages my homelab infrastructure under a monorepo to keep things
|
||||||
|
centralized and easily sharable across different modules
|
||||||
|
|
||||||
|
|
||||||
|
# Turbo-repo details
|
||||||
|
|
||||||
|
## What's inside?
|
||||||
|
|
||||||
|
This turborepo uses [pnpm](https://pnpm.io) as a package manager. It includes the following packages/apps:
|
||||||
|
|
||||||
|
### Apps and Packages
|
||||||
|
|
||||||
|
- `docs`: a [Next.js](https://nextjs.org/) app
|
||||||
|
- `web`: another [Next.js](https://nextjs.org/) app
|
||||||
|
- `ui`: a stub React component library shared by both `web` and `docs` applications
|
||||||
|
- `eslint-config-custom`: `eslint` configurations (includes `eslint-config-next` and `eslint-config-prettier`)
|
||||||
|
- `tsconfig`: `tsconfig.json`s used throughout the monorepo
|
||||||
|
|
||||||
|
Each package/app is 100% [TypeScript](https://www.typescriptlang.org/).
|
||||||
|
|
||||||
|
### Utilities
|
||||||
|
|
||||||
|
This turborepo has some additional tools already setup for you:
|
||||||
|
|
||||||
|
- [TypeScript](https://www.typescriptlang.org/) for static type checking
|
||||||
|
- [ESLint](https://eslint.org/) for code linting
|
||||||
|
- [Prettier](https://prettier.io) for code formatting
|
||||||
|
|
||||||
|
### Build
|
||||||
|
|
||||||
|
To build all apps and packages, run the following command:
|
||||||
|
|
||||||
|
```
|
||||||
|
cd my-turborepo
|
||||||
|
pnpm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Develop
|
||||||
|
|
||||||
|
To develop all apps and packages, run the following command:
|
||||||
|
|
||||||
|
```
|
||||||
|
cd my-turborepo
|
||||||
|
pnpm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### Remote Caching
|
||||||
|
|
||||||
|
Turborepo can use a technique known as [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching) to share cache artifacts across machines, enabling you to share build caches with your team and CI/CD pipelines.
|
||||||
|
|
||||||
|
By default, Turborepo will cache locally. To enable Remote Caching you will need an account with Vercel. If you don't have an account you can [create one](https://vercel.com/signup), then enter the following commands:
|
||||||
|
|
||||||
|
```
|
||||||
|
cd my-turborepo
|
||||||
|
pnpm dlx turbo login
|
||||||
|
```
|
||||||
|
|
||||||
|
This will authenticate the Turborepo CLI with your [Vercel account](https://vercel.com/docs/concepts/personal-accounts/overview).
|
||||||
|
|
||||||
|
Next, you can link your Turborepo to your Remote Cache by running the following command from the root of your turborepo:
|
||||||
|
|
||||||
|
```
|
||||||
|
pnpm dlx turbo link
|
||||||
|
```
|
||||||
|
|
||||||
|
## Useful Links
|
||||||
|
|
||||||
|
Learn more about the power of Turborepo:
|
||||||
|
|
||||||
|
- [Pipelines](https://turbo.build/repo/docs/core-concepts/monorepos/running-tasks)
|
||||||
|
- [Caching](https://turbo.build/repo/docs/core-concepts/caching)
|
||||||
|
- [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching)
|
||||||
|
- [Filtering](https://turbo.build/repo/docs/core-concepts/monorepos/filtering)
|
||||||
|
- [Configuration Options](https://turbo.build/repo/docs/reference/configuration)
|
||||||
|
- [CLI Usage](https://turbo.build/repo/docs/reference/command-line-reference)
|
|
@ -0,0 +1,10 @@
|
||||||
|
# Since .env is gitignored, you can use .env-example to build a new `.env` file when you clone the repo.
|
||||||
|
# Keep this file up-to-date when you add new variables to `.env`.
|
||||||
|
|
||||||
|
# This file will be committed to version control, so make sure not to have any secrets in it.
|
||||||
|
# If you are cloning this repo, create a copy of this file named `.env` and populate it with your secrets.
|
||||||
|
|
||||||
|
# When adding additional env variables, the schema in /env/schema.mjs should be updated accordingly
|
||||||
|
|
||||||
|
# Prisma
|
||||||
|
DATABASE_URL=file:./db.sqlite
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
|
"parserOptions": {
|
||||||
|
"project": "./tsconfig.json"
|
||||||
|
},
|
||||||
|
"plugins": ["@typescript-eslint"],
|
||||||
|
"extends": ["next/core-web-vitals", "plugin:@typescript-eslint/recommended"],
|
||||||
|
"rules": {
|
||||||
|
"@typescript-eslint/consistent-type-imports": "warn"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# database
|
||||||
|
/prisma/db.sqlite
|
||||||
|
/prisma/db.sqlite-journal
|
||||||
|
|
||||||
|
# next.js
|
||||||
|
/.next/
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
*.pem
|
||||||
|
|
||||||
|
# debug
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
.pnpm-debug.log*
|
||||||
|
|
||||||
|
# local env files
|
||||||
|
.env
|
||||||
|
.env*.local
|
||||||
|
|
||||||
|
# vercel
|
||||||
|
.vercel
|
||||||
|
|
||||||
|
# typescript
|
||||||
|
*.tsbuildinfo
|
|
@ -0,0 +1,27 @@
|
||||||
|
# Create T3 App
|
||||||
|
|
||||||
|
This is an app bootstrapped according to the [init.tips](https://init.tips) stack, also known as the T3-Stack.
|
||||||
|
|
||||||
|
## What's next? How do I make an app with this?
|
||||||
|
|
||||||
|
We try to keep this project as simple as possible, so you can start with the most basic configuration and then move on to more advanced configuration.
|
||||||
|
|
||||||
|
If you are not familiar with the different technologies used in this project, please refer to the respective docs. If you still are in the wind, please join our [Discord](https://t3.gg/discord) and ask for help.
|
||||||
|
|
||||||
|
- [Next-Auth.js](https://next-auth.js.org)
|
||||||
|
- [Prisma](https://prisma.io)
|
||||||
|
- [TailwindCSS](https://tailwindcss.com)
|
||||||
|
- [tRPC](https://trpc.io)
|
||||||
|
|
||||||
|
We also [roll our own docs](https://beta.create.t3.gg) with some summary information and links to the respective documentation.
|
||||||
|
|
||||||
|
Also checkout these awesome tutorials on `create-t3-app`.
|
||||||
|
|
||||||
|
- [Build a Blog With the T3 Stack - tRPC, TypeScript, Next.js, Prisma & Zod](https://www.youtube.com/watch?v=syEWlxVFUrY)
|
||||||
|
- [Build a Live Chat Application with the T3 Stack - TypeScript, Tailwind, tRPC](https://www.youtube.com/watch?v=dXRRY37MPuk)
|
||||||
|
- [Build a full stack app with create-t3-app](https://www.nexxel.dev/blog/ct3a-guestbook)
|
||||||
|
- [A first look at create-t3-app](https://dev.to/ajcwebdev/a-first-look-at-create-t3-app-1i8f)
|
||||||
|
|
||||||
|
## How do I deploy this?
|
||||||
|
|
||||||
|
Follow our deployment guides for [Vercel](https://beta.create.t3.gg/en/deployment/vercel) and [Docker](https://beta.create.t3.gg/en/deployment/docker) for more information.
|
|
@ -0,0 +1,5 @@
|
||||||
|
/// <reference types="next" />
|
||||||
|
/// <reference types="next/image-types/global" />
|
||||||
|
|
||||||
|
// NOTE: This file should not be edited
|
||||||
|
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
|
@ -0,0 +1,17 @@
|
||||||
|
// @ts-check
|
||||||
|
/**
|
||||||
|
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation.
|
||||||
|
* This is especially useful for Docker builds.
|
||||||
|
*/
|
||||||
|
!process.env.SKIP_ENV_VALIDATION && (await import("./src/env/server.mjs"));
|
||||||
|
|
||||||
|
/** @type {import("next").NextConfig} */
|
||||||
|
const config = {
|
||||||
|
reactStrictMode: true,
|
||||||
|
swcMinify: true,
|
||||||
|
i18n: {
|
||||||
|
locales: ["en"],
|
||||||
|
defaultLocale: "en",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
export default config;
|
|
@ -0,0 +1,44 @@
|
||||||
|
{
|
||||||
|
"name": "about-me",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"build": "next build",
|
||||||
|
"dev": "next dev",
|
||||||
|
"postinstall": "prisma generate",
|
||||||
|
"lint": "next lint",
|
||||||
|
"start": "next start"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@prisma/client": "^4.5.0",
|
||||||
|
"@tanstack/react-query": "^4.10.0",
|
||||||
|
"@trpc/client": "10.0.0-rc.4",
|
||||||
|
"@trpc/next": "10.0.0-rc.4",
|
||||||
|
"@trpc/react-query": "10.0.0-rc.4",
|
||||||
|
"@trpc/server": "10.0.0-rc.4",
|
||||||
|
"next": "13.0.2",
|
||||||
|
"react": "18.2.0",
|
||||||
|
"react-dom": "18.2.0",
|
||||||
|
"superjson": "1.9.1",
|
||||||
|
"zod": "^3.18.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^18.0.0",
|
||||||
|
"@types/react": "^18.0.14",
|
||||||
|
"@types/react-dom": "^18.0.5",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^5.33.0",
|
||||||
|
"@typescript-eslint/parser": "^5.33.0",
|
||||||
|
"autoprefixer": "^10.4.7",
|
||||||
|
"eslint": "^8.26.0",
|
||||||
|
"eslint-config-next": "13.0.2",
|
||||||
|
"postcss": "^8.4.14",
|
||||||
|
"prettier": "^2.7.1",
|
||||||
|
"prettier-plugin-tailwindcss": "^0.1.13",
|
||||||
|
"prisma": "^4.5.0",
|
||||||
|
"tailwindcss": "^3.2.0",
|
||||||
|
"typescript": "^4.8.4"
|
||||||
|
},
|
||||||
|
"ct3aMetadata": {
|
||||||
|
"initVersion": "6.9.0"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
module.exports = {
|
||||||
|
plugins: {
|
||||||
|
tailwindcss: {},
|
||||||
|
autoprefixer: {},
|
||||||
|
},
|
||||||
|
};
|
|
@ -0,0 +1,4 @@
|
||||||
|
/** @type {import("prettier").Config} */
|
||||||
|
module.exports = {
|
||||||
|
plugins: [require.resolve("prettier-plugin-tailwindcss")],
|
||||||
|
};
|
|
@ -0,0 +1,17 @@
|
||||||
|
// This is your Prisma schema file,
|
||||||
|
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
||||||
|
|
||||||
|
generator client {
|
||||||
|
provider = "prisma-client-js"
|
||||||
|
}
|
||||||
|
|
||||||
|
datasource db {
|
||||||
|
provider = "sqlite"
|
||||||
|
url = env("DATABASE_URL")
|
||||||
|
}
|
||||||
|
|
||||||
|
model Example {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
|
@ -0,0 +1,35 @@
|
||||||
|
// @ts-check
|
||||||
|
import { clientEnv, clientSchema } from "./schema.mjs";
|
||||||
|
|
||||||
|
const _clientEnv = clientSchema.safeParse(clientEnv);
|
||||||
|
|
||||||
|
export const formatErrors = (
|
||||||
|
/** @type {import('zod').ZodFormattedError<Map<string,string>,string>} */
|
||||||
|
errors,
|
||||||
|
) =>
|
||||||
|
Object.entries(errors)
|
||||||
|
.map(([name, value]) => {
|
||||||
|
if (value && "_errors" in value)
|
||||||
|
return `${name}: ${value._errors.join(", ")}\n`;
|
||||||
|
})
|
||||||
|
.filter(Boolean);
|
||||||
|
|
||||||
|
if (!_clientEnv.success) {
|
||||||
|
console.error(
|
||||||
|
"❌ Invalid environment variables:\n",
|
||||||
|
...formatErrors(_clientEnv.error.format()),
|
||||||
|
);
|
||||||
|
throw new Error("Invalid environment variables");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let key of Object.keys(_clientEnv.data)) {
|
||||||
|
if (!key.startsWith("NEXT_PUBLIC_")) {
|
||||||
|
console.warn(
|
||||||
|
`❌ Invalid public environment variable name: ${key}. It must begin with 'NEXT_PUBLIC_'`,
|
||||||
|
);
|
||||||
|
|
||||||
|
throw new Error("Invalid public environment variable name");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const env = _clientEnv.data;
|
|
@ -0,0 +1,30 @@
|
||||||
|
// @ts-check
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify your server-side environment variables schema here.
|
||||||
|
* This way you can ensure the app isn't built with invalid env vars.
|
||||||
|
*/
|
||||||
|
export const serverSchema = z.object({
|
||||||
|
DATABASE_URL: z.string().url(),
|
||||||
|
NODE_ENV: z.enum(["development", "test", "production"]),
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify your client-side environment variables schema here.
|
||||||
|
* This way you can ensure the app isn't built with invalid env vars.
|
||||||
|
* To expose them to the client, prefix them with `NEXT_PUBLIC_`.
|
||||||
|
*/
|
||||||
|
export const clientSchema = z.object({
|
||||||
|
// NEXT_PUBLIC_BAR: z.string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* You can't destruct `process.env` as a regular object, so you have to do
|
||||||
|
* it manually here. This is because Next.js evaluates this at build time,
|
||||||
|
* and only used environment variables are included in the build.
|
||||||
|
* @type {{ [k in keyof z.infer<typeof clientSchema>]: z.infer<typeof clientSchema>[k] | undefined }}
|
||||||
|
*/
|
||||||
|
export const clientEnv = {
|
||||||
|
// NEXT_PUBLIC_BAR: process.env.NEXT_PUBLIC_BAR,
|
||||||
|
};
|
|
@ -0,0 +1,27 @@
|
||||||
|
// @ts-check
|
||||||
|
/**
|
||||||
|
* This file is included in `/next.config.mjs` which ensures the app isn't built with invalid env vars.
|
||||||
|
* It has to be a `.mjs`-file to be imported there.
|
||||||
|
*/
|
||||||
|
import { serverSchema } from "./schema.mjs";
|
||||||
|
import { env as clientEnv, formatErrors } from "./client.mjs";
|
||||||
|
|
||||||
|
const _serverEnv = serverSchema.safeParse(process.env);
|
||||||
|
|
||||||
|
if (!_serverEnv.success) {
|
||||||
|
console.error(
|
||||||
|
"❌ Invalid environment variables:\n",
|
||||||
|
...formatErrors(_serverEnv.error.format()),
|
||||||
|
);
|
||||||
|
throw new Error("Invalid environment variables");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let key of Object.keys(_serverEnv.data)) {
|
||||||
|
if (key.startsWith("NEXT_PUBLIC_")) {
|
||||||
|
console.warn("❌ You are exposing a server-side env-variable:", key);
|
||||||
|
|
||||||
|
throw new Error("You are exposing a server-side env-variable");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const env = { ..._serverEnv.data, ...clientEnv };
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { type AppType } from "next/app";
|
||||||
|
|
||||||
|
import { trpc } from "../utils/trpc";
|
||||||
|
|
||||||
|
import "../styles/globals.css";
|
||||||
|
|
||||||
|
const MyApp: AppType = ({ Component, pageProps }) => {
|
||||||
|
return <Component {...pageProps} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default trpc.withTRPC(MyApp);
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { type NextApiRequest, type NextApiResponse } from "next";
|
||||||
|
|
||||||
|
import { prisma } from "../../server/db/client";
|
||||||
|
|
||||||
|
const examples = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||||
|
const examples = await prisma.example.findMany();
|
||||||
|
res.status(200).json(examples);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default examples;
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { createNextApiHandler } from "@trpc/server/adapters/next";
|
||||||
|
|
||||||
|
import { env } from "../../../env/server.mjs";
|
||||||
|
import { createContext } from "../../../server/trpc/context";
|
||||||
|
import { appRouter } from "../../../server/trpc/router/_app";
|
||||||
|
|
||||||
|
// export API handler
|
||||||
|
export default createNextApiHandler({
|
||||||
|
router: appRouter,
|
||||||
|
createContext,
|
||||||
|
onError:
|
||||||
|
env.NODE_ENV === "development"
|
||||||
|
? ({ path, error }) => {
|
||||||
|
console.error(`❌ tRPC failed on ${path}: ${error}`);
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
});
|
|
@ -0,0 +1,90 @@
|
||||||
|
import { type NextPage } from "next";
|
||||||
|
import Head from "next/head";
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
import { trpc } from "../utils/trpc";
|
||||||
|
|
||||||
|
const Home: NextPage = () => {
|
||||||
|
const hello = trpc.example.hello.useQuery({ text: "from tRPC" });
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Head>
|
||||||
|
<title>Create T3 App</title>
|
||||||
|
<meta name="description" content="Generated by create-t3-app" />
|
||||||
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
</Head>
|
||||||
|
|
||||||
|
<main className="container mx-auto flex min-h-screen flex-col items-center justify-center p-4">
|
||||||
|
<h1 className="text-5xl font-extrabold leading-normal text-gray-700 md:text-[5rem]">
|
||||||
|
Create <span className="text-purple-300">T3</span> App
|
||||||
|
</h1>
|
||||||
|
<p className="text-2xl text-gray-700">This stack uses:</p>
|
||||||
|
<div className="mt-3 grid gap-3 pt-3 text-center md:grid-cols-2 lg:w-2/3">
|
||||||
|
<TechnologyCard
|
||||||
|
name="NextJS"
|
||||||
|
description="The React framework for production"
|
||||||
|
documentation="https://nextjs.org/"
|
||||||
|
/>
|
||||||
|
<TechnologyCard
|
||||||
|
name="TypeScript"
|
||||||
|
description="Strongly typed programming language that builds on JavaScript, giving you better tooling at any scale"
|
||||||
|
documentation="https://www.typescriptlang.org/"
|
||||||
|
/>
|
||||||
|
<TechnologyCard
|
||||||
|
name="TailwindCSS"
|
||||||
|
description="Rapidly build modern websites without ever leaving your HTML"
|
||||||
|
documentation="https://tailwindcss.com/"
|
||||||
|
/>
|
||||||
|
<TechnologyCard
|
||||||
|
name="tRPC"
|
||||||
|
description="End-to-end typesafe APIs made easy"
|
||||||
|
documentation="https://trpc.io/"
|
||||||
|
/>
|
||||||
|
<TechnologyCard
|
||||||
|
name="Next-Auth"
|
||||||
|
description="Authentication for Next.js"
|
||||||
|
documentation="https://next-auth.js.org/"
|
||||||
|
/>
|
||||||
|
<TechnologyCard
|
||||||
|
name="Prisma"
|
||||||
|
description="Build data-driven JavaScript & TypeScript apps in less time"
|
||||||
|
documentation="https://www.prisma.io/docs/"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="flex w-full items-center justify-center pt-6 text-2xl text-blue-500">
|
||||||
|
{hello.data ? <p>{hello.data.greeting}</p> : <p>Loading..</p>}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Home;
|
||||||
|
|
||||||
|
type TechnologyCardProps = {
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
documentation: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const TechnologyCard: React.FC<TechnologyCardProps> = ({
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
documentation,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<section className="flex flex-col justify-center rounded border-2 border-gray-500 p-6 shadow-xl duration-500 motion-safe:hover:scale-105">
|
||||||
|
<h2 className="text-lg text-gray-700">{name}</h2>
|
||||||
|
<p className="text-sm text-gray-600">{description}</p>
|
||||||
|
<Link
|
||||||
|
className="m-auto mt-3 w-fit text-sm text-violet-500 underline decoration-dotted underline-offset-2"
|
||||||
|
href={documentation}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
Documentation
|
||||||
|
</Link>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { PrismaClient } from "@prisma/client";
|
||||||
|
|
||||||
|
import { env } from "../../env/server.mjs";
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
// eslint-disable-next-line no-var
|
||||||
|
var prisma: PrismaClient | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const prisma =
|
||||||
|
global.prisma ||
|
||||||
|
new PrismaClient({
|
||||||
|
log:
|
||||||
|
env.NODE_ENV === "development" ? ["query", "error", "warn"] : ["error"],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (env.NODE_ENV !== "production") {
|
||||||
|
global.prisma = prisma;
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
import { type inferAsyncReturnType } from "@trpc/server";
|
||||||
|
import { type CreateNextContextOptions } from "@trpc/server/adapters/next";
|
||||||
|
|
||||||
|
import { prisma } from "../db/client";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace this with an object if you want to pass things to createContextInner
|
||||||
|
*/
|
||||||
|
type CreateContextOptions = Record<string, never>;
|
||||||
|
|
||||||
|
/** Use this helper for:
|
||||||
|
* - testing, so we dont have to mock Next.js' req/res
|
||||||
|
* - trpc's `createSSGHelpers` where we don't have req/res
|
||||||
|
* @see https://beta.create.t3.gg/en/usage/trpc#-servertrpccontextts
|
||||||
|
**/
|
||||||
|
export const createContextInner = async (opts: CreateContextOptions) => {
|
||||||
|
return {
|
||||||
|
prisma,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the actual context you'll use in your router
|
||||||
|
* @link https://trpc.io/docs/context
|
||||||
|
**/
|
||||||
|
export const createContext = async (opts: CreateNextContextOptions) => {
|
||||||
|
return await createContextInner({});
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Context = inferAsyncReturnType<typeof createContext>;
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { router } from "../trpc";
|
||||||
|
import { exampleRouter } from "./example";
|
||||||
|
|
||||||
|
export const appRouter = router({
|
||||||
|
example: exampleRouter,
|
||||||
|
});
|
||||||
|
|
||||||
|
// export type definition of API
|
||||||
|
export type AppRouter = typeof appRouter;
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
import { router, publicProcedure } from "../trpc";
|
||||||
|
|
||||||
|
export const exampleRouter = router({
|
||||||
|
hello: publicProcedure
|
||||||
|
.input(z.object({ text: z.string().nullish() }).nullish())
|
||||||
|
.query(({ input }) => {
|
||||||
|
return {
|
||||||
|
greeting: `Hello ${input?.text ?? "world"}`,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
getAll: publicProcedure.query(({ ctx }) => {
|
||||||
|
return ctx.prisma.example.findMany();
|
||||||
|
}),
|
||||||
|
});
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { initTRPC } from "@trpc/server";
|
||||||
|
import superjson from "superjson";
|
||||||
|
|
||||||
|
import { type Context } from "./context";
|
||||||
|
|
||||||
|
const t = initTRPC.context<Context>().create({
|
||||||
|
transformer: superjson,
|
||||||
|
errorFormatter({ shape }) {
|
||||||
|
return shape;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const router = t.router;
|
||||||
|
|
||||||
|
export const publicProcedure = t.procedure;
|
|
@ -0,0 +1,3 @@
|
||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
|
@ -0,0 +1,42 @@
|
||||||
|
import { httpBatchLink, loggerLink } from "@trpc/client";
|
||||||
|
import { createTRPCNext } from "@trpc/next";
|
||||||
|
import { type inferRouterInputs, type inferRouterOutputs } from "@trpc/server";
|
||||||
|
import superjson from "superjson";
|
||||||
|
|
||||||
|
import { type AppRouter } from "../server/trpc/router/_app";
|
||||||
|
|
||||||
|
const getBaseUrl = () => {
|
||||||
|
if (typeof window !== "undefined") return ""; // browser should use relative url
|
||||||
|
if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`; // SSR should use vercel url
|
||||||
|
return `http://localhost:${process.env.PORT ?? 3000}`; // dev SSR should use localhost
|
||||||
|
};
|
||||||
|
|
||||||
|
export const trpc = createTRPCNext<AppRouter>({
|
||||||
|
config() {
|
||||||
|
return {
|
||||||
|
transformer: superjson,
|
||||||
|
links: [
|
||||||
|
loggerLink({
|
||||||
|
enabled: (opts) =>
|
||||||
|
process.env.NODE_ENV === "development" ||
|
||||||
|
(opts.direction === "down" && opts.result instanceof Error),
|
||||||
|
}),
|
||||||
|
httpBatchLink({
|
||||||
|
url: `${getBaseUrl()}/api/trpc`,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
ssr: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inference helper for inputs
|
||||||
|
* @example type HelloInput = RouterInputs['example']['hello']
|
||||||
|
**/
|
||||||
|
export type RouterInputs = inferRouterInputs<AppRouter>;
|
||||||
|
/**
|
||||||
|
* Inference helper for outputs
|
||||||
|
* @example type HelloOutput = RouterOutputs['example']['hello']
|
||||||
|
**/
|
||||||
|
export type RouterOutputs = inferRouterOutputs<AppRouter>;
|
|
@ -0,0 +1,8 @@
|
||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
module.exports = {
|
||||||
|
content: ["./src/**/*.{js,ts,jsx,tsx}"],
|
||||||
|
theme: {
|
||||||
|
extend: {},
|
||||||
|
},
|
||||||
|
plugins: [],
|
||||||
|
};
|
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es2017",
|
||||||
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
|
"allowJs": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"incremental": true,
|
||||||
|
"noUncheckedIndexedAccess": true
|
||||||
|
},
|
||||||
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.cjs", "**/*.mjs"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
extends: ["custom"],
|
||||||
|
};
|
|
@ -0,0 +1,30 @@
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
First, run the development server:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||||
|
|
||||||
|
You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file.
|
||||||
|
|
||||||
|
[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`.
|
||||||
|
|
||||||
|
The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
|
||||||
|
|
||||||
|
## Learn More
|
||||||
|
|
||||||
|
To learn more about Next.js, take a look at the following resources:
|
||||||
|
|
||||||
|
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
||||||
|
- [Learn Next.js](https://nextjs.org/learn/foundations/about-nextjs) - an interactive Next.js tutorial.
|
||||||
|
|
||||||
|
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
|
||||||
|
|
||||||
|
## Deploy on Vercel
|
||||||
|
|
||||||
|
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme) from the creators of Next.js.
|
||||||
|
|
||||||
|
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
|
|
@ -0,0 +1,5 @@
|
||||||
|
/// <reference types="next" />
|
||||||
|
/// <reference types="next/image-types/global" />
|
||||||
|
|
||||||
|
// NOTE: This file should not be edited
|
||||||
|
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
|
@ -0,0 +1,6 @@
|
||||||
|
module.exports = {
|
||||||
|
reactStrictMode: true,
|
||||||
|
experimental: {
|
||||||
|
transpilePackages: ["ui"],
|
||||||
|
},
|
||||||
|
};
|
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
"name": "docs",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "next dev --port 3001",
|
||||||
|
"build": "next build",
|
||||||
|
"start": "next start",
|
||||||
|
"lint": "next lint"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"next": "13.0.0",
|
||||||
|
"react": "18.2.0",
|
||||||
|
"react-dom": "18.2.0",
|
||||||
|
"ui": "workspace:*"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.0.0",
|
||||||
|
"eslint-config-custom": "workspace:*",
|
||||||
|
"eslint": "7.32.0",
|
||||||
|
"tsconfig": "workspace:*",
|
||||||
|
"@types/node": "^17.0.12",
|
||||||
|
"@types/react": "^18.0.22",
|
||||||
|
"@types/react-dom": "^18.0.7",
|
||||||
|
"typescript": "^4.5.3"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { Button } from "ui";
|
||||||
|
|
||||||
|
export default function Docs() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1>Docs</h1>
|
||||||
|
<Button />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"extends": "tsconfig/nextjs.json",
|
||||||
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
# Hashicorp's Vault Administration
|
||||||
|
|
||||||
|
A dump of knowledge, commands, and documentations to lookup for troubleshooting
|
||||||
|
or setting up
|
||||||
|
|
||||||
|
## CLI getting started
|
||||||
|
|
||||||
|
`export VAULT_ADDR='https://c4c.pegasust.com'`
|
||||||
|
|
||||||
|
`vault login`
|
||||||
|
|
||||||
|
- Note, the vault will first need to be unsealed
|
||||||
|
- The first time we log in as admin, it's probably best to use the
|
||||||
|
root token to access.
|
||||||
|
|
||||||
|
|
||||||
|
## Seal/unseal
|
||||||
|
|
||||||
|
- Vault server begins sealed
|
||||||
|
- I generated with 6/10 cluster vault configuration (10 keys & require 6 keys to unseal)
|
||||||
|
- These keys can be shared to other admins
|
||||||
|
- This means an admin only need 6 keys to unseal the vault when needed
|
||||||
|
|
||||||
|
## Enabling GitHub auth
|
||||||
|
|
||||||
|
- First, add our policy:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vault policy write {POLICY_NAME} {POLICY_FILE}
|
||||||
|
```
|
||||||
|
- Our deployment's replacements:
|
||||||
|
- `{POLICY_NAME}` is `web-app-admin`
|
||||||
|
- `{POLICY_FILE}` is `config/hashicorp-policy/web-app-admin.hcl`
|
||||||
|
|
||||||
|
- Then, we enable GitHub auth and attach `web-app-admin` to our `web-app-dev` team
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vault auth enable github
|
||||||
|
vault write auth/github/config organization={GITHUB_ORG}
|
||||||
|
vault write auth/github/map/teams/{GITHUB_TEAM} value={VAULT_POLICY}
|
||||||
|
```
|
||||||
|
|
||||||
|
- Our deployment's version replaces:
|
||||||
|
- `{GITHUB_ORG}` is `change-for-change`
|
||||||
|
- `{GITHUB_TEAM}` is `web-app-dev`
|
||||||
|
- `{VAULT_POLICY}` is `web-app-admin`
|
||||||
|
|
||||||
|
## Updating policy
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vault write sys/policy/{POLICY_NAME} policy=@{POLICY_FILE}
|
||||||
|
```
|
||||||
|
|
||||||
|
- An example is:
|
||||||
|
- `{POLICY_NAME}`: `web-app-admin`
|
||||||
|
- `{POLICY_FILE}`: `config/hashicorp-policy/web-app-admin.hcl`
|
||||||
|
|
||||||
|
## Bootstrapping our vault
|
||||||
|
|
||||||
|
`vault secrets enable -path=secret kv`
|
||||||
|
`vault secrets enable -path=secretv2 kv-v2`
|
|
@ -0,0 +1,66 @@
|
||||||
|
# c4c-secrets
|
||||||
|
|
||||||
|
A dive into secret management for c4c web-app
|
||||||
|
|
||||||
|
# HashiCorp vault
|
||||||
|
|
||||||
|
- `docker-compose.yml` -> `docker-compose.hashicorp.yml`
|
||||||
|
- Uses in-file store (maybe slow/unreliable!)
|
||||||
|
- Can be migrated to AWS in the future
|
||||||
|
|
||||||
|
- Pretty good cli experience
|
||||||
|
|
||||||
|
- You could try my (@Pegasust) deployment at [pegasust.com/vault](https://pegasust.com/vault)
|
||||||
|
- Log in with your GitHub account
|
||||||
|
(this is done with personal access token [docs](https://www.vaultproject.io/docs/auth/github))
|
||||||
|
- Make sure that you're in our change-for-change organization
|
||||||
|
- And also is in web-dev GitHub team
|
||||||
|
|
||||||
|
## Installing the CLI
|
||||||
|
|
||||||
|
See here [hashicorp's official installtion guide](https://developer.hashicorp.com/vault/downloads)
|
||||||
|
|
||||||
|
- You could also access the secrets with the web UI. But to streamline the env
|
||||||
|
exchange process, we should use the CLI
|
||||||
|
|
||||||
|
## Login as user (CLI)
|
||||||
|
|
||||||
|
`export VAULT_ADDR='https://c4c.pegasust.com'`
|
||||||
|
`vault login -method=github`
|
||||||
|
|
||||||
|
## Vault onto `.env*`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vault kv get --format=json path/to/secret | jq -r '.data|to_entries|map("\(.key)=\(.value|tostring)")|.[]'
|
||||||
|
# Likely
|
||||||
|
vault kv get --format=json secret/c4c-web-app | jq -r '.data|to_entries|map("\(.key)=\(.value|tostring)")|.[]'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Simple put-get-list
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# put
|
||||||
|
vault kv put path/to/secret hello="world"
|
||||||
|
# get
|
||||||
|
vault kv get path/to/secret hello
|
||||||
|
# list
|
||||||
|
vault kv get path/to/secret
|
||||||
|
```
|
||||||
|
|
||||||
|
## `.env.*` onto Vault
|
||||||
|
|
||||||
|
- NOTE: This does not support syntax like `HELLO='WORLD'`. Everything must be
|
||||||
|
in the form of: `HELLO=WORLD`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vault kv put path/to/secret `cat .env`
|
||||||
|
# Likely
|
||||||
|
vault kv put secret/c4c-web-app `grep -v ^# .env`
|
||||||
|
```
|
||||||
|
|
||||||
|
## About the `cubbyhole` secret engine
|
||||||
|
|
||||||
|
- It is per-token (that means per-auth) secret storage
|
||||||
|
- Can be used as secret manager
|
||||||
|
- Don't count on my deployment to be 100\% reliable!
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
# Read the configuration secret example
|
||||||
|
path "secret/config" {
|
||||||
|
capabilities = ["read"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "secret" {
|
||||||
|
capabilities = ["list"]
|
||||||
|
}
|
||||||
|
path "secret/*" {
|
||||||
|
capabilities = ["list"]
|
||||||
|
}
|
||||||
|
path "secret/c4c-web-app" {
|
||||||
|
capabilities = ["read", "list", "create", "update"]
|
||||||
|
}
|
||||||
|
path "secret/c4c-web-app/*" {
|
||||||
|
capabilities = ["read", "create", "update", "list"]
|
||||||
|
}
|
||||||
|
path "secretv2" {
|
||||||
|
capabilities = ["list"]
|
||||||
|
}
|
||||||
|
path "secretv2/*" {
|
||||||
|
capabilities = ["list"]
|
||||||
|
}
|
||||||
|
path "secretv2/c4c-web-app" {
|
||||||
|
capabilities = ["read", "list", "create", "update"]
|
||||||
|
}
|
||||||
|
path "secretv2/c4c-web-app/*" {
|
||||||
|
capabilities = ["read", "create", "update", "list"]
|
||||||
|
}
|
||||||
|
|
||||||
|
# List secrets engines
|
||||||
|
path "sys/mounts" {
|
||||||
|
capabilities = ["read"]
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"backend": {
|
||||||
|
"file": {
|
||||||
|
"path": "/vault/file"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"listener": {
|
||||||
|
"tcp":{
|
||||||
|
"address": "0.0.0.0:8200",
|
||||||
|
"tls_disable": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ui": true
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
version: '3.5'
|
||||||
|
services:
|
||||||
|
vault:
|
||||||
|
image: vault:1.11.3
|
||||||
|
restart: always
|
||||||
|
entrypoint: vault server -config=vault/config/vault.json
|
||||||
|
volumes:
|
||||||
|
- hashicorp_vault:/vault
|
||||||
|
- ./config/hashicorp:/vault/config
|
||||||
|
cap_add:
|
||||||
|
- IPC_LOCK
|
||||||
|
networks: [felia]
|
||||||
|
ports:
|
||||||
|
- 8200:8200
|
||||||
|
volumes:
|
||||||
|
hashicorp_vault:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
felia:
|
||||||
|
name: felia-nginx-net
|
|
@ -0,0 +1,4 @@
|
||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
extends: ["custom"],
|
||||||
|
};
|
|
@ -0,0 +1,30 @@
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
First, run the development server:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||||
|
|
||||||
|
You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file.
|
||||||
|
|
||||||
|
[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`.
|
||||||
|
|
||||||
|
The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
|
||||||
|
|
||||||
|
## Learn More
|
||||||
|
|
||||||
|
To learn more about Next.js, take a look at the following resources:
|
||||||
|
|
||||||
|
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
||||||
|
- [Learn Next.js](https://nextjs.org/learn/foundations/about-nextjs) - an interactive Next.js tutorial.
|
||||||
|
|
||||||
|
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
|
||||||
|
|
||||||
|
## Deploy on Vercel
|
||||||
|
|
||||||
|
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme) from the creators of Next.js.
|
||||||
|
|
||||||
|
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
|
|
@ -0,0 +1,5 @@
|
||||||
|
/// <reference types="next" />
|
||||||
|
/// <reference types="next/image-types/global" />
|
||||||
|
|
||||||
|
// NOTE: This file should not be edited
|
||||||
|
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
|
@ -0,0 +1,6 @@
|
||||||
|
module.exports = {
|
||||||
|
reactStrictMode: true,
|
||||||
|
experimental: {
|
||||||
|
transpilePackages: ["ui"],
|
||||||
|
},
|
||||||
|
};
|
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
"name": "web",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "next dev",
|
||||||
|
"build": "next build",
|
||||||
|
"start": "next start",
|
||||||
|
"lint": "next lint"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"next": "13.0.0",
|
||||||
|
"react": "18.2.0",
|
||||||
|
"react-dom": "18.2.0",
|
||||||
|
"ui": "workspace:*"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.0.0",
|
||||||
|
"eslint-config-custom": "workspace:*",
|
||||||
|
"eslint": "7.32.0",
|
||||||
|
"tsconfig": "workspace:*",
|
||||||
|
"@types/node": "^17.0.12",
|
||||||
|
"@types/react": "^18.0.22",
|
||||||
|
"@types/react-dom": "^18.0.7",
|
||||||
|
"typescript": "^4.5.3"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { Button } from "ui";
|
||||||
|
|
||||||
|
export default function Web() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1>Web</h1>
|
||||||
|
<Button />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"extends": "tsconfig/nextjs.json",
|
||||||
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
|
@ -1 +0,0 @@
|
||||||
/home/ubuntu_admin/local_repos/c4c-secret-manager/
|
|
|
@ -0,0 +1,120 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"flake-utils": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1667395993,
|
||||||
|
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-utils_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1667077288,
|
||||||
|
"narHash": "sha256-bdC8sFNDpT0HK74u9fUkpbf1MEzVYJ+ka7NXCdgBoaA=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "6ee9ebb6b1ee695d2cacc4faa053a7b9baa76817",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1667629849,
|
||||||
|
"narHash": "sha256-P+v+nDOFWicM4wziFK9S/ajF2lc0N2Rg9p6Y35uMoZI=",
|
||||||
|
"owner": "nixos",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "3bacde6273b09a21a8ccfba15586fb165078fb62",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nixos",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1667050928,
|
||||||
|
"narHash": "sha256-xOn0ZgjImIyeecEsrjxuvlW7IW5genTwvvnDQRFncB8=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "fdebb81f45a1ba2c4afca5fd9f526e1653ad0949",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": "flake-utils",
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"turbo": "turbo"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rust-overlay": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": [
|
||||||
|
"turbo",
|
||||||
|
"flake-utils"
|
||||||
|
],
|
||||||
|
"nixpkgs": [
|
||||||
|
"turbo",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1667098607,
|
||||||
|
"narHash": "sha256-zTYgUaS+81mNq8Z0v2WYr46ACJFBeWqcQfOVQaTxtNE=",
|
||||||
|
"owner": "oxalica",
|
||||||
|
"repo": "rust-overlay",
|
||||||
|
"rev": "de5c4d5d40ae0a0dab67c5f7ae8d26c5445cf00d",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "oxalica",
|
||||||
|
"repo": "rust-overlay",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"turbo": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": "flake-utils_2",
|
||||||
|
"nixpkgs": "nixpkgs_2",
|
||||||
|
"rust-overlay": "rust-overlay"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1667101919,
|
||||||
|
"narHash": "sha256-xOCDfi7ADRkfmHt83gQ+rs7Oaqij4IMV1NF3PQZtF+c=",
|
||||||
|
"owner": "dlip",
|
||||||
|
"repo": "turbo",
|
||||||
|
"rev": "ffce29ea3b5ede544128b790d67c80aa2d3efc03",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "dlip",
|
||||||
|
"repo": "turbo",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
{
|
||||||
|
description = "Provides devShell and (very unlikely) package & app";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||||
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
# https://github.com/vercel/turbo/issues/2293#issuecomment-1296094236
|
||||||
|
# work-around for turbo-repo on nix
|
||||||
|
turbo.url = "github:dlip/turbo";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, turbo, flake-utils, nixpkgs }:
|
||||||
|
with flake-utils; lib.eachSystem lib.defaultSystems (sys:
|
||||||
|
let
|
||||||
|
overlays = [ turbo.overlay ];
|
||||||
|
# pkgs is our tweaked nixpkgs
|
||||||
|
pkgs = import nixpkgs { system = sys; overlays = overlays; };
|
||||||
|
shellMsg = ''
|
||||||
|
echo "Hello from nix ${sys}"
|
||||||
|
'';
|
||||||
|
shellAliases = ''
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
{
|
||||||
|
devShell = pkgs.mkShell {
|
||||||
|
nativeBuildInputs = [ pkgs.bashInteractive ];
|
||||||
|
buildInputs = [
|
||||||
|
pkgs.nodejs-18_x
|
||||||
|
pkgs.nodePackages.pnpm
|
||||||
|
pkgs.nodePackages.prisma
|
||||||
|
pkgs.prisma-engines
|
||||||
|
pkgs.turbo
|
||||||
|
# pkgs.turbo-tooling
|
||||||
|
pkgs.vault
|
||||||
|
pkgs.jq
|
||||||
|
pkgs.pscale
|
||||||
|
pkgs.act
|
||||||
|
pkgs.cypress
|
||||||
|
];
|
||||||
|
shellHook =
|
||||||
|
# https://github.com/prisma/prisma/issues/3026#issuecomment-927258138
|
||||||
|
# nix-direnv is required (impure build?) https://github.com/nix-community/nix-direnv
|
||||||
|
''
|
||||||
|
# Prisma
|
||||||
|
export PRISMA_MIGRATION_ENGINE_BINARY="${pkgs.prisma-engines}/bin/migration-engine"
|
||||||
|
export PRISMA_QUERY_ENGINE_BINARY="${pkgs.prisma-engines}/bin/query-engine"
|
||||||
|
export PRISMA_QUERY_ENGINE_LIBRARY="${pkgs.prisma-engines}/lib/libquery_engine.node"
|
||||||
|
export PRISMA_INTROSPECTION_ENGINE_BINARY="${pkgs.prisma-engines}/bin/introspection-engine"
|
||||||
|
export PRISMA_FMT_BINARY="${pkgs.prisma-engines}/bin/prisma-fmt"
|
||||||
|
|
||||||
|
# Turbo
|
||||||
|
export TURBO_BINARY_PATH="${pkgs.turbo}/bin/turbo"
|
||||||
|
|
||||||
|
# Cypress
|
||||||
|
export CYPRESS_RUN_BINARY="${pkgs.cypress}/bin/Cypress"
|
||||||
|
'' + shellAliases + shellMsg;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"name": "felia",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"private": true,
|
||||||
|
"workspaces": [
|
||||||
|
"apps/*",
|
||||||
|
"packages/*"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"build": "turbo run build",
|
||||||
|
"dev": "turbo run dev --parallel",
|
||||||
|
"lint": "turbo run lint",
|
||||||
|
"format": "prettier --write \"**/*.{ts,tsx,md}\""
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"eslint-config-custom": "workspace:*",
|
||||||
|
"prettier": "latest",
|
||||||
|
"turbo": "1.6.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {},
|
||||||
|
"packageManager": "pnpm@7.14.0"
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
module.exports = {
|
||||||
|
extends: ["next", "prettier"],
|
||||||
|
settings: {
|
||||||
|
next: {
|
||||||
|
rootDir: [
|
||||||
|
"apps/docs/",
|
||||||
|
"apps/web/",
|
||||||
|
"packages/ui/",
|
||||||
|
"packages/config/",
|
||||||
|
"packages/tsconfig/",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"name": "config",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"main": "index.js",
|
||||||
|
"license": "MIT",
|
||||||
|
"files": [
|
||||||
|
"eslint-preset.js"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"eslint": "^8.27.0",
|
||||||
|
"eslint-config-next": "^12.0.3",
|
||||||
|
"eslint-config-prettier": "^8.3.0",
|
||||||
|
"typescript": "^4.8.4"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
module.exports = {
|
||||||
|
extends: ["next", "turbo", "prettier"],
|
||||||
|
rules: {
|
||||||
|
"@next/next/no-html-link-for-pages": "off",
|
||||||
|
"react/jsx-key": "off",
|
||||||
|
},
|
||||||
|
};
|
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"name": "eslint-config-custom",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"main": "index.js",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"eslint": "^7.23.0",
|
||||||
|
"eslint-config-next": "13.0.0",
|
||||||
|
"eslint-config-prettier": "^8.3.0",
|
||||||
|
"eslint-plugin-react": "7.31.8",
|
||||||
|
"eslint-config-turbo": "latest"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"typescript": "^4.7.4"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
# `tsconfig`
|
||||||
|
|
||||||
|
These are base shared `tsconfig.json`s from which all other `tsconfig.json`'s inherit from.
|
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/tsconfig",
|
||||||
|
"display": "Default",
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": false,
|
||||||
|
"declaration": true,
|
||||||
|
"declarationMap": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"inlineSources": false,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"noUnusedLocals": false,
|
||||||
|
"noUnusedParameters": false,
|
||||||
|
"preserveWatchOutput": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": true
|
||||||
|
},
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/tsconfig",
|
||||||
|
"display": "Next.js",
|
||||||
|
"extends": "./base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
|
"allowJs": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"incremental": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"jsx": "preserve"
|
||||||
|
},
|
||||||
|
"include": ["src", "next-env.d.ts"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"name": "tsconfig",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"private": true,
|
||||||
|
"files": [
|
||||||
|
"base.json",
|
||||||
|
"nextjs.json",
|
||||||
|
"react-library.json"
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/tsconfig",
|
||||||
|
"display": "React Library",
|
||||||
|
"extends": "./base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"lib": ["ES2015"],
|
||||||
|
"module": "ESNext",
|
||||||
|
"target": "es6"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
import * as React from "react";
|
||||||
|
export const Button = () => {
|
||||||
|
return <button>Boop</button>;
|
||||||
|
};
|
|
@ -0,0 +1,2 @@
|
||||||
|
import * as React from "react";
|
||||||
|
export * from "./Button";
|
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"name": "ui",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"main": "./index.tsx",
|
||||||
|
"types": "./index.tsx",
|
||||||
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"lint": "eslint *.ts*"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/react": "^18.0.17",
|
||||||
|
"@types/react-dom": "^18.0.6",
|
||||||
|
"eslint": "^7.32.0",
|
||||||
|
"eslint-config-custom": "workspace:*",
|
||||||
|
"react": "^18.2.0",
|
||||||
|
"tsconfig": "workspace:*",
|
||||||
|
"typescript": "^4.5.2"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"extends": "tsconfig/react-library.json",
|
||||||
|
"include": ["."],
|
||||||
|
"exclude": ["dist", "build", "node_modules"]
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,3 @@
|
||||||
|
packages:
|
||||||
|
- "apps/*"
|
||||||
|
- "packages/*"
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://turbo.build/schema.json",
|
||||||
|
"pipeline": {
|
||||||
|
"build": {
|
||||||
|
"dependsOn": ["^build"],
|
||||||
|
"outputs": ["dist/**", ".next/**"]
|
||||||
|
},
|
||||||
|
"lint": {
|
||||||
|
"outputs": []
|
||||||
|
},
|
||||||
|
"dev": {
|
||||||
|
"cache": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue