├── .eslintrc.json
├── .gitignore
├── LICENSE
├── README.md
├── app
├── api
│ ├── favorites
│ │ ├── [name]
│ │ │ └── route.ts
│ │ └── route.ts
│ ├── getPokemon
│ │ └── route.js
│ └── nvisionParser
│ │ └── route.js
├── components
│ ├── FavoriteCard.tsx
│ ├── PokemonList.tsx
│ ├── SavePokemon.tsx
│ └── ServerCard.tsx
├── favorites
│ └── page.tsx
├── layout.tsx
├── loading.tsx
├── models
│ └── FavoritesModel.ts
├── nvisionDashboard
│ ├── Wrapper.tsx
│ └── page.tsx
├── page.tsx
└── whos
│ └── [name]
│ └── page.tsx
├── assets
├── TableGifHigh.gif
└── treeGif.gif
├── instrumentation.js
├── next.config.js
├── nvisionServer.js
├── package.json
├── postcss.config.js
├── styles
└── globals.css
├── tailwind.config.js
├── tsconfig.json
├── types.ts
└── utils
└── dbConnect.js
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "next/core-web-vitals"
3 | }
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # next.js
12 | /.next/
13 | /out/
14 |
15 | # production
16 | /build
17 | /dist
18 |
19 | # misc
20 | .DS_Store
21 | *.pem
22 |
23 | # debug
24 | npm-debug.log*
25 | yarn-debug.log*
26 | yarn-error.log*
27 |
28 | # local env files
29 | .env*.local
30 |
31 | # vercel
32 | .vercel
33 |
34 | # typescript
35 | *.tsbuildinfo
36 | next-env.d.ts
37 |
38 | .env
39 | dev.db*
40 | node_modules
41 | package-lock.json
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 OSLabs Beta
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # nVision
2 |
3 | nVision is an open-source developer tool for Next.js applications that provides users server-side network request metrics and an interactive hierarchical file tree, aiding with rapid debugging and deployment.
4 |
5 | _Note: nVision currently only supports App Router_
6 |
7 | ## Getting Started
8 |
9 | Run the following commands to install nVision's npm package and add the necessary files required to implement nVision:
10 | ```bash
11 | npm install nvisionjs
12 | npx nvisionjs-create
13 | ```
14 |
15 | Add the below to your `next.config.js`
16 | ```javascript
17 | experimental: { instrumentationHook: true },
18 | ```
19 |
20 | Add the following script to your `package.json`
21 | ```json
22 | "nvision": "node --require ./nvisionServer.js & next dev"
23 | ```
24 |
25 | Run the following command to start the development server
26 | ```bash
27 | npm run nvision
28 | ```
29 |
30 | Open your dashboard by going [http://localhost:3000/nvisionDashboard](http://localhost:3000/nvisionDashboard) (or wherever your app is hosted)
31 |
32 | Open your application in a new window to view real time updates on the dashboard
33 |
34 |
35 | ## Features
36 | - Users can interact with their app and view server-side network activity on the dashboard table such as routes, status codes, methods and duration of network calls
37 | - Users can view the directory structure of their app in tree form to help visualize complex applications
38 |
39 |
40 | ## Examples
41 | ### Table view
42 |
43 |
44 |
45 |
46 | ### Tree view
47 |
48 |
49 |
50 |
51 |
52 | ## Upcoming Features
53 | - Augmented metrics for client-side and database requests
54 | - Expanded network activity visualization
55 | - Support for Pages Router
56 | - New dashboard tab to display route connections between pages
57 |
58 |
59 | ## Contributors
60 |
61 | Caitlin O'Donohue - [GitHub](https://github.com/codeFromCO) | [Linkedin](https://www.linkedin.com/in/caitlin-odonohue/)
62 |
63 | Sunny Pacheco - [GitHub](https://github.com/xsunnibunnix) | [Linkedin](https://www.linkedin.com/in/sunnypacheco/)
64 |
65 | Jiyoung Lee - [GitHub](https://github.com/jiyoungglee/) | [Linkedin](https://www.linkedin.com/in/jiyoung-g-lee/)
66 |
67 | Isaac Lee - [GitHub](https://github.com/Third-Isaac) | [Linkedin](https://www.linkedin.com/in/thirdisaac/)
68 |
69 | Bennett Ma - [GitHub](https://github.com/bmgitcode) | [Linkedin](https://www.linkedin.com/in/bennett-ma/)
70 |
71 |
72 | ## Special Mentions
73 | Special thanks to the [NetPulse](https://github.com/oslabs-beta/NetPulse) team for their advice and inspiration.
74 |
75 |
76 | ## License
77 |
78 | Distributed under the MIT License. See [License](https://choosealicense.com/licenses/mit/) for more information.
79 |
80 | ## Tech Stack
81 |
82 |
83 | 
84 | 
85 | 
86 | 
87 | 
88 | 
89 | 
90 | 
91 | 
92 | 
93 | 
94 | 
95 |
96 |
97 |
--------------------------------------------------------------------------------
/app/api/favorites/[name]/route.ts:
--------------------------------------------------------------------------------
1 | import Favorite from "@/app/models/FavoritesModel";
2 | import { connectToDB } from "@/utils/dbConnect";
3 |
4 | export async function POST(request: Request, { params }: { params: { name: string } }) {
5 | try {
6 | await connectToDB();
7 | const newFavorite = new Favorite({name: params.name})
8 | await newFavorite.save();
9 | return new Response(JSON.stringify(newFavorite), { status: 201 });
10 | } catch(err) {
11 | return new Response("Failed to add to favorites", { status: 500 });
12 | }
13 | }
14 |
15 | export async function DELETE(request: Request, { params }: { params: { name: string } }) {
16 | try {
17 | await connectToDB();
18 | const deleted = await Favorite.findOneAndDelete({name: params.name});
19 | return new Response(JSON.stringify(deleted), { status: 200 });
20 | } catch(err) {
21 | return new Response("Failed to remove from favorites", { status: 500 });
22 | }
23 | }
--------------------------------------------------------------------------------
/app/api/favorites/route.ts:
--------------------------------------------------------------------------------
1 | import Favorite from '@/app/models/FavoritesModel';
2 | import { connectToDB } from '@/utils/dbConnect';
3 |
4 | export async function GET(request: Request) {
5 | try {
6 | await connectToDB();
7 | const favorites = await Favorite.find();
8 |
9 | return new Response(JSON.stringify(favorites), { status: 200 });
10 | } catch (err) {
11 | return new Response('Failed to get favorites', { status: 500 });
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/app/api/getPokemon/route.js:
--------------------------------------------------------------------------------
1 | import { NextResponse } from 'next/server';
2 |
3 | export async function GET() {
4 | const res = await fetch(`https://pokeapi.co/api/v2/pokemon/`, {
5 | cache: 'no-store',
6 | });
7 | const data = await res.json();
8 | return NextResponse.json(data, { status: 200 });
9 | }
10 |
--------------------------------------------------------------------------------
/app/api/nvisionParser/route.js:
--------------------------------------------------------------------------------
1 | import fileParser from '@nvisionjs/parse'
2 |
3 | const path = require('path');
4 |
5 | export async function GET(request) {
6 | try {
7 | const appDirPath = path.join(process.cwd(), 'app');
8 | const results = await fileParser(appDirPath)
9 | return new Response(JSON.stringify(results))
10 | }
11 | catch(e) {
12 | console.error(e)
13 | }
14 | }
--------------------------------------------------------------------------------
/app/components/FavoriteCard.tsx:
--------------------------------------------------------------------------------
1 | import Link from 'next/link';
2 | import { useEffect, useState } from 'react';
3 |
4 | interface CardProps {
5 | name: string;
6 | deleteFunc?: Function;
7 | }
8 |
9 | const FavoriteCard = (props: CardProps) => {
10 | const [pokemonPhoto, setPokemonPhoto] = useState('');
11 |
12 | useEffect(() => {
13 | async function fetchPokemonInfo() {
14 | const response = await fetch(
15 | `https://pokeapi.co/api/v2/pokemon/${props.name}`
16 | );
17 | const data = await response.json();
18 |
19 | setPokemonPhoto(data.sprites.front_default);
20 | }
21 |
22 | fetchPokemonInfo();
23 | }, [props.name]);
24 |
25 | return (
26 |
27 |
28 | {props.name[0].toUpperCase().concat(props.name.slice(1))}
29 |
30 |
31 |
32 |
Learn more
33 |
34 | {props.deleteFunc && (
35 |
{
38 | if (props.deleteFunc) props.deleteFunc(props.name);
39 | }}
40 | >
41 | Delete
42 |
43 | )}
44 |
45 | );
46 | };
47 |
48 | export default FavoriteCard;
49 |
--------------------------------------------------------------------------------
/app/components/PokemonList.tsx:
--------------------------------------------------------------------------------
1 | import { v4 as uuid } from 'uuid';
2 | import ServerCard from './ServerCard';
3 |
4 | const fetchAllPokemon = async () => {
5 | try {
6 | const response = await fetch('https://pokeapi.co/api/v2/pokemon/', {
7 | method: 'GET',
8 | });
9 | const data = await response.json();
10 | return data.results;
11 | } catch (err) {
12 | console.error(err);
13 | }
14 | };
15 |
16 | const PokemonList = async () => {
17 | const pokemon = await fetchAllPokemon();
18 | return (
19 |
20 | {pokemon.map(({name}: {name: string}) => {
21 | return ;
22 | })}
23 |
24 | );
25 | };
26 |
27 | export default PokemonList;
--------------------------------------------------------------------------------
/app/components/SavePokemon.tsx:
--------------------------------------------------------------------------------
1 | 'use client';
2 |
3 | import Link from "next/link";
4 |
5 | export const SavePokemon = (props) => {
6 | const { pokemonName } = props;
7 | function savePokemon(name: String) {
8 | fetch(`/api/favorites/${name}/`, {
9 | method: 'POST',
10 | });
11 | }
12 |
13 | return (
14 |
15 |
16 | savePokemon(pokemonName)}
19 | >
20 | Save Pokemon
21 |
22 |
23 |
24 | )
25 | }
--------------------------------------------------------------------------------
/app/components/ServerCard.tsx:
--------------------------------------------------------------------------------
1 | import Link from 'next/link';
2 |
3 | interface CardProps {
4 | name: string;
5 | deleteFunc?: Function;
6 | }
7 |
8 | const fetchPokemonInfo = async (name: string) => {
9 | const response = await fetch(
10 | `https://pokeapi.co/api/v2/pokemon/${name}`
11 | );
12 | const data = await response.json();
13 |
14 | return data.sprites.front_default;
15 | };
16 |
17 | const ServerCard = async (props: CardProps) => {
18 | const pokemonPhoto = await fetchPokemonInfo(props.name)
19 |
20 | return (
21 |
22 |
23 | {props.name[0].toUpperCase().concat(props.name.slice(1))}
24 |
25 |
26 |
27 |
Learn more
28 |
29 | {props.deleteFunc && (
30 |
{
33 | if (props.deleteFunc) props.deleteFunc(props.name);
34 | }}
35 | >
36 | Delete
37 |
38 | )}
39 |
40 | );
41 | };
42 |
43 | export default ServerCard;
--------------------------------------------------------------------------------
/app/favorites/page.tsx:
--------------------------------------------------------------------------------
1 | 'use client';
2 | import Link from 'next/link';
3 | import { useEffect, useState } from 'react';
4 | import FavoriteCard from '../components/FavoriteCard';
5 | import { v4 as uuid } from 'uuid';
6 |
7 | interface PokemonObj {
8 | name: string;
9 | }
10 |
11 | const Favorites = () => {
12 | const [favorites, setFavorites] = useState<[]>([]);
13 |
14 | async function deletePokemon(name: String) {
15 | await fetch(`/api/favorites/${name}/`, {
16 | method: 'DELETE',
17 | });
18 | getFavs();
19 | }
20 |
21 | const getFavs = async () => {
22 | try {
23 | const response = await fetch('/api/favorites', {
24 | method: 'GET',
25 | });
26 | const data = await response.json();
27 | setFavorites(data);
28 | } catch (err) {
29 | console.error(err);
30 | }
31 | };
32 |
33 | useEffect(() => {
34 | getFavs();
35 | }, []);
36 |
37 | return (
38 |
39 |
Favorite Pokemon
40 |
41 |
42 | GET MORE POKEMON
43 |
44 |
45 |
46 | {favorites.map((pokemon: PokemonObj) => (
47 |
52 | ))}
53 |
54 |
55 | );
56 | };
57 |
58 | export default Favorites;
59 |
--------------------------------------------------------------------------------
/app/layout.tsx:
--------------------------------------------------------------------------------
1 | import '../styles/globals.css';
2 |
3 | export const metadata = {
4 | title: 'nVision demo app',
5 | description: 'created by nVision',
6 | };
7 |
8 | export default function RootLayout({
9 | children,
10 | }: {
11 | children: React.ReactNode;
12 | }) {
13 | return (
14 |
15 |
16 |
19 |
20 | {children}
21 |
22 |
23 | );
24 | }
25 |
--------------------------------------------------------------------------------
/app/loading.tsx:
--------------------------------------------------------------------------------
1 | const Loading = () => {
2 | return Loading... ;
3 | };
4 |
5 | export default Loading;
6 |
--------------------------------------------------------------------------------
/app/models/FavoritesModel.ts:
--------------------------------------------------------------------------------
1 | import { Schema, model, models } from 'mongoose';
2 |
3 | interface Favorite {
4 | name: object;
5 | }
6 |
7 | const FavoriteSchema = new Schema({
8 | name: {
9 | type: String,
10 | unique: [true, 'You can only favorite a pokemon once'],
11 | },
12 | });
13 |
14 | const Favorite = models.Favorite || model('Favorite', FavoriteSchema);
15 |
16 | export default Favorite;
17 |
--------------------------------------------------------------------------------
/app/nvisionDashboard/Wrapper.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 |
3 | import Dashboard from '@nvisionjs/dashboard';
4 | import React from 'react';
5 |
6 | const Wrapper = (props) => {
7 | const {info} = props
8 | return (
9 |
10 | )
11 | }
12 |
13 | export default Wrapper;
--------------------------------------------------------------------------------
/app/nvisionDashboard/page.tsx:
--------------------------------------------------------------------------------
1 | import Wrapper from './Wrapper';
2 |
3 | async function getFiles() {
4 | const files = await fetch('http://localhost:3000/api/nvisionParser', {
5 | method: 'GET',
6 | cache: 'no-store'
7 | });
8 | const parsedFiles = await files.json();
9 | return parsedFiles;
10 | }
11 |
12 | export default async function Dashboard() {
13 | const result = await getFiles();
14 |
15 | return (
16 | <>
17 |
18 | >
19 | );
20 | }
21 |
--------------------------------------------------------------------------------
/app/page.tsx:
--------------------------------------------------------------------------------
1 | import Link from 'next/link';
2 | import PokemonList from './components/PokemonList';
3 |
4 | const Home = () => {
5 | return (
6 |
7 |
Pokemon
8 |
9 |
FAVORITES
10 |
11 |
12 |
13 | );
14 | };
15 |
16 | export default Home;
17 |
--------------------------------------------------------------------------------
/app/whos/[name]/page.tsx:
--------------------------------------------------------------------------------
1 | import Link from 'next/link';
2 | import { SavePokemon } from '@/app/components/SavePokemon';
3 |
4 | async function fetchPokemonInfo(name: String) {
5 | const response = await fetch(`https://pokeapi.co/api/v2/pokemon/${name}`);
6 |
7 | const data = await response.json();
8 |
9 | return data;
10 | }
11 |
12 | interface pokemonObj {
13 | name: String;
14 | }
15 |
16 | interface contextObj {
17 | params: pokemonObj;
18 | }
19 |
20 | const PokemonInfo = async (context: contextObj) => {
21 | const pokemonName = context.params.name;
22 | const charStats = await fetchPokemonInfo(pokemonName);
23 |
24 | return (
25 |
26 |
Get Stats
27 |
28 |
29 | GET MORE POKEMON
30 |
31 |
32 | FAVORITES
33 |
34 |
35 |
36 |
37 |
38 |
39 | Name:
40 | {charStats.forms[0].name[0]
41 | .toUpperCase()
42 | .concat(charStats.forms[0].name.slice(1))}{' '}
43 |
44 |
45 | Type:
46 | {charStats.types[0].type.name}
47 |
48 |
49 | Height:
50 | {charStats.height}
51 |
52 |
53 | Weight:
54 | {charStats.weight}
55 |
56 |
57 |
58 |
62 |
63 |
64 |
65 |
66 |
67 | );
68 | };
69 |
70 | export default PokemonInfo;
71 |
--------------------------------------------------------------------------------
/assets/TableGifHigh.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/nVision/d7f3e3379deefa08708729d59cc7fa4af193de6a/assets/TableGifHigh.gif
--------------------------------------------------------------------------------
/assets/treeGif.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/nVision/d7f3e3379deefa08708729d59cc7fa4af193de6a/assets/treeGif.gif
--------------------------------------------------------------------------------
/instrumentation.js:
--------------------------------------------------------------------------------
1 | export async function register() {
2 | console.log('registered');
3 | if (process.env.NEXT_RUNTIME === 'nodejs') {
4 | const {startTrace} = await import('@nvisionjs/trace');
5 | startTrace();
6 | }
7 | }
--------------------------------------------------------------------------------
/next.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const nextConfig = {
3 | experimental: {
4 | instrumentationHook: true
5 | },
6 | // webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
7 | // config.externals.push({
8 | // 'utf-8-validate': 'commonjs utf-8-validate',
9 | // 'bufferutil': 'commonjs bufferutil',
10 | // })
11 | // return config
12 | // },
13 | }
14 |
15 | module.exports = nextConfig
16 |
--------------------------------------------------------------------------------
/nvisionServer.js:
--------------------------------------------------------------------------------
1 | require('@nvisionjs/server');
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "pokemon",
3 | "version": "0.1.0",
4 | "private": true,
5 | "contributors": [
6 | "Bennett Ma",
7 | "Caitlin O'Donohue",
8 | "Isaac Lee",
9 | "Jiyoung Lee",
10 | "Sunny Pacheco"
11 | ],
12 | "keywords": [
13 | "nextjs",
14 | "next",
15 | "react",
16 | "devtool"
17 | ],
18 | "license": "MIT",
19 | "homepage": "http://nvisionjs.com",
20 | "repository": {
21 | "type": "git",
22 | "url": "https://github.com/oslabs-beta/nVision"
23 | },
24 | "scripts": {
25 | "nvision": "node --require ./nvisionServer.js & next dev",
26 | "dev": "next dev",
27 | "build": "next build",
28 | "start": "next start",
29 | "server": "node server.js && npm run start",
30 | "lint": "next lint"
31 | },
32 | "dependencies": {
33 | "@types/node": "^20.4.0",
34 | "@types/react": "18.2.14",
35 | "@types/react-dom": "18.2.6",
36 | "autoprefixer": "10.4.14",
37 | "dotenv": "^16.3.1",
38 | "eslint": "8.44.0",
39 | "eslint-config-next": "13.4.3",
40 | "express": "^4.18.2",
41 | "mongoose": "^7.4.0",
42 | "next": "^13.4.12",
43 | "nvisionjs": "^1.2.5",
44 | "react": "18.2.0",
45 | "react-dom": "18.2.0",
46 | "uuid": "^9.0.0"
47 | },
48 | "devDependencies": {
49 | "@types/uuid": "^9.0.2",
50 | "autoprefixer": "^10.4.14",
51 | "daisyui": "^3.2.1",
52 | "nodemon": "^3.0.1",
53 | "postcss": "^8.4.25",
54 | "prisma": "^4.16.2",
55 | "tailwindcss": "^3.3.2",
56 | "ts-node": "^10.9.1",
57 | "typescript": "^5.1.6"
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/styles/globals.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&display=swap");
2 |
3 | @tailwind base;
4 | @tailwind components;
5 | @tailwind utilities;
6 |
7 | /*
8 | Note: The styles for this gradient grid background is heavily inspired by the creator of this amazing site (https://dub.sh) – all credits go to them!
9 | */
10 |
11 | .main {
12 | width: 100vw;
13 | min-height: 100vh;
14 | position: fixed;
15 | display: flex;
16 | justify-content: center;
17 | padding: 120px 24px 160px 24px;
18 | pointer-events: none;
19 | }
20 |
21 | .main:before {
22 | background: radial-gradient(circle, rgba(2, 0, 36, 0) 0, #fafafa 100%);
23 | position: absolute;
24 | content: "";
25 | z-index: 2;
26 | width: 100%;
27 | height: 100%;
28 | top: 0;
29 | }
30 |
31 | .main:after {
32 | content: "";
33 | z-index: 1;
34 | position: absolute;
35 | width: 100%;
36 | height: 100%;
37 | top: 0;
38 | opacity: 0.4;
39 | filter: invert(1);
40 | }
41 |
42 | .gradient {
43 | height: fit-content;
44 | z-index: 3;
45 | width: 100%;
46 | max-width: 640px;
47 | background-image: radial-gradient(
48 | at 27% 37%,
49 | hsla(215, 98%, 61%, 1) 0px,
50 | transparent 0%
51 | ),
52 | radial-gradient(at 97% 21%, hsla(125, 98%, 72%, 1) 0px, transparent 50%),
53 | radial-gradient(at 52% 99%, hsla(354, 98%, 61%, 1) 0px, transparent 50%),
54 | radial-gradient(at 10% 29%, hsla(256, 96%, 67%, 1) 0px, transparent 50%),
55 | radial-gradient(at 97% 96%, hsla(38, 60%, 74%, 1) 0px, transparent 50%),
56 | radial-gradient(at 33% 50%, hsla(222, 67%, 73%, 1) 0px, transparent 50%),
57 | radial-gradient(at 79% 53%, hsla(343, 68%, 79%, 1) 0px, transparent 50%);
58 | position: absolute;
59 | content: "";
60 | width: 100%;
61 | height: 100%;
62 | filter: blur(100px) saturate(150%);
63 | top: 80px;
64 | opacity: 0.15;
65 | }
66 |
67 | @media screen and (max-width: 640px) {
68 | .main {
69 | padding: 0;
70 | }
71 | }
72 |
73 | /* Tailwind Styles */
74 |
75 | .app {
76 | @apply relative z-10 flex justify-center items-center flex-col max-w-7xl mx-auto sm:px-16 px-6;
77 | }
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | const daisyui = require('daisyui');
2 |
3 | /** @type {import('tailwindcss').Config} */
4 | module.exports = {
5 | content: [
6 | './pages/**/*.{js,ts,jsx,tsx,mdx}',
7 | './components/**/*.{js,ts,jsx,tsx,mdx}',
8 | './app/**/*.{js,ts,jsx,tsx,mdx}',
9 | ],
10 | theme: {
11 | extend: {
12 | fontFamily: {
13 | satoshi: ['Satoshi', 'sans-serif'],
14 | inter: ['Inter', 'sans-serif'],
15 | },
16 | },
17 | },
18 | daisyui: {
19 | themes: ['acid', 'night'],
20 | darkTheme: 'night',
21 | base: true,
22 | styled: true,
23 | utils: true,
24 | },
25 | plugins: [require('daisyui')],
26 | }
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2015",
4 | "lib": [
5 | "dom",
6 | "dom.iterable",
7 | "esnext"
8 | ],
9 | "allowJs": true,
10 | "skipLibCheck": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "noEmit": true,
13 | "esModuleInterop": true,
14 | "module": "CommonJS",
15 | "moduleResolution": "NodeNext",
16 | "resolveJsonModule": true,
17 | "isolatedModules": true,
18 | "jsx": "preserve",
19 | "incremental": true,
20 | "allowSyntheticDefaultImports": true,
21 | "strict": false,
22 | "plugins": [
23 | {
24 | "name": "next"
25 | }
26 | ],
27 | "paths": {
28 | "@/*": [
29 | "./*"
30 | ],
31 | "@/pages": [
32 | "./app"
33 | ]
34 | },
35 | },
36 | "include": [
37 | "next-env.d.ts",
38 | "**/*.ts",
39 | "**/*.tsx",
40 | ".next/types/**/*.ts",
41 | ],
42 | "exclude": [
43 | "node_modules"
44 | ]
45 | }
46 |
--------------------------------------------------------------------------------
/types.ts:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/nVision/d7f3e3379deefa08708729d59cc7fa4af193de6a/types.ts
--------------------------------------------------------------------------------
/utils/dbConnect.js:
--------------------------------------------------------------------------------
1 | import mongoose from 'mongoose';
2 |
3 | let isConnected = false;
4 |
5 | export const connectToDB = async () => {
6 | mongoose.set('strictQuery', true);
7 |
8 | if (isConnected) {
9 | console.log('MongoDB is already connected');
10 | return;
11 | }
12 | try {
13 | await mongoose.connect(process.env.MONGODB_URI, {
14 | dbName: 'favorite-pokemon',
15 | useNewUrlParser: true,
16 | useUnifiedTopology: true,
17 | });
18 | isConnected = true;
19 | } catch (error) {
20 | console.log(error);
21 | }
22 | };
23 |
--------------------------------------------------------------------------------