Skip to content

Commit

Permalink
Tigris example with Next.js (#42662)
Browse files Browse the repository at this point in the history
  • Loading branch information
adilansari committed Nov 15, 2022
1 parent efbabd2 commit 0f8b3d6
Show file tree
Hide file tree
Showing 30 changed files with 1,296 additions and 0 deletions.
4 changes: 4 additions & 0 deletions examples/with-tigris/.env.development
@@ -0,0 +1,4 @@
# DO NOT ADD SECRETS TO THIS FILE. This is a good place for defaults.
# If you want to add secrets use `.env.development.local` instead.

TIGRIS_URI=localhost:8081
7 changes: 7 additions & 0 deletions examples/with-tigris/.env.local.example
@@ -0,0 +1,7 @@
# Enter your tigris uri, ex :- localhost:8081, api.preview.tigrisdata.cloud etc.
TIGRIS_URI=

# Client credentials, if using auth, can be generated from Tigris cloud console.
# See: https://docs.tigrisdata.com/auth
TIGRIS_CLIENT_ID=
TIGRIS_CLIENT_SECRET=
4 changes: 4 additions & 0 deletions examples/with-tigris/.env.production
@@ -0,0 +1,4 @@
# DO NOT ADD SECRETS TO THIS FILE. This is a good place for defaults.
# If you want to add secrets use `.env.production.local` instead.

TIGRIS_URI=api.preview.tigrisdata.cloud
27 changes: 27 additions & 0 deletions examples/with-tigris/.gitignore
@@ -0,0 +1,27 @@
# 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/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# local env files
.env*.local
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts
171 changes: 171 additions & 0 deletions examples/with-tigris/README.md
@@ -0,0 +1,171 @@
# ⚡ ️Tigris example app on Next.js - Todo list

A simple todo app built on [Next.js][next-url] and [Tigris](https://docs.tigrisdata.com/)
using [TypeScript client](https://docs.tigrisdata.com/typescript/), deployed on [Vercel][vercel-url].

### Project demo

https://tigris-nextjs-starter-kit.vercel.app/

# ⚙️ Deploying your own

All you need is a [Github](https://github.com), [Vercel][vercel-url] and Tigris
account([sign up for a free account](https://www.tigrisdata.com/nextjs#signup-form)). Now, Hit "Deploy"
and follow instructions to deploy app to your Vercel account

[![Deploy with Vercel](https://vercel.com/button)][deploy-url]

:tada: All done. You should be able to use app on the URL provided by Vercel. Feel free to play around
or do a [code walkthrough](#code-walkthrough) next :tada:

> [Tigris integration](https://vercel.com/integrations/tigris) with Vercel will automatically fetch
> access keys to populate [Environment Variables](.env.local.example) when deploying app.
<details>
<summary>2. Running Next.js server & Tigris dev environment on your local computer</summary>

## 📖 Running Next.js server & Tigris locally

### Prerequisites

1. Tigris installed on your dev computer
1. For **macOS**: `brew install tigrisdata/tigris/tigris-cli`
2. Other operating systems: [See installation instructions here](https://docs.tigrisdata.com/cli/installation)
2. Node.js version 16+

### Instructions

1. Clone this repo on your computer

```shell
git clone https://github.com/tigrisdata/tigris-vercel-starter
```

2. Install dependencies

```shell
cd tigris-vercel-starter
npm install
```

3. Start Tigris local development environment

```shell
tigris dev start
```

4. Run the Next.js server

```shell
npm run dev
```

> Note: This step uses a custom dev & build script to initialize Tigris database and collection for
> the app and requires [ts-node](https://www.npmjs.com/package/ts-node#installation) to be installed.
:tada: All done. You should be able to use app on `localhost:3000` in browser. Feel free to play
around or do a [code walk-through](#code-walkthrough) next :tada:

</details>

# 📖 How to use

Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init), [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/), or [pnpm](https://pnpm.io) to bootstrap the example:

```bash
npx create-next-app --example with-tigris tigris-next-app
```

```bash
yarn create next-app --example with-tigris tigris-next-app
```

```bash
pnpm create next-app --example with-tigris tigris-next-app
```

Deploy it to the cloud with [Vercel](https://vercel.com/new?utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)).

# 👀 Code walkthrough

<details>
<summary> 📂 File structure</summary>

```text
├── package.json
├── lib
│ ├── tigris.ts
├── models
│ └── tigris
│ └── todoStarterApp
│ └── todoItems.ts
└── pages
├── index.tsx
└── api
├── item
│ ├── [id].ts
└── items
├── index.ts
└── search.ts
```

</details>

<details>
<summary> 🪢 Tigris schema definition</summary>

[models/tigris/todoStarterApp/todoItems.ts](models/tigris/todoStarterApp/todoItems.ts) - The to-do list app
has a single collection `todoItems` that stores the to-do items in `todoStarterApp` database. The
Database and Collection get automatically provisioned by the [setup script](scripts/setup.ts).

This is an inspiration from Next.js based file system router. Create a folder or drop a schema file
inside database folder under `models/tigris/`, and you're able to instantly create Databases and
Collections in Tigris for your application.

</details>

<details>
<summary> 🌐 Connecting to Tigris</summary>

[lib/tigris.ts](lib/tigris.ts) - Loads the environment variables you specified previously in creating a Vercel project
section and uses them to configure the Tigris client.

</details>

<details>
<summary> ❇️ API routes to access data in Tigris collection</summary>

All the Next.js API routes are defined under `pages/api/`. We have three files exposing endpoints:

#### [`pages/api/items/index.ts`](pages/api/items/index.ts)

- `GET /api/items` to get an array of to-do items as Array<TodoItem>
- `POST /api/items` to add an item to the list

#### [`/pages/api/items/search.ts`](/pages/api/items/search.ts)

- `GET /api/items/search?q=query` to find and return items matching the given query

#### [`pages/api/item/[id].ts`](pages/api/item/[id].ts)

- `GET /api/item/{id}` to fetch an item
- `PUT /api/item/{id}` to update the given item
- `DELETE /api/item/[id]` to delete an item

</details>

# 🚀 Next steps

In a few steps, we learnt how to bootstrap a Next.js app using Tigris and deploy it on Vercel. Feel
free to add more functionalities or customize App for your use-case and learn more about
[Tigris data platform](https://docs.tigrisdata.com/overview/)

<!-- MARKDOWN LINKS & IMAGES -->

[typescript]: https://img.shields.io/badge/TypeScript-007ACC?style=for-the-badge&logo=typescript&logoColor=white
[typescript-url]: https://www.typescriptlang.org/
[vercel]: https://img.shields.io/badge/vercel-F22F46?style=for-the-badge&logo=vercel&logoColor=white
[vercel-url]: https://vercel.com/
[deploy-url]: https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Ftigrisdata%2Ftigris-vercel-starter&project-name=todo-list-app-tigris&repo-name=todo-list-webapp-tigris&demo-title=My%20To-do%20list%20webapp&demo-description=A%20To-do%20list%20webapp%20using%20NextJS%20and%20Tigris&integration-ids=oac_Orjx197uMuJobdSaEpVv2Zn8
[next.js]: https://img.shields.io/badge/next.js-000000?style=for-the-badge&logo=nextdotjs&logoColor=white
[next-url]: https://nextjs.org/
47 changes: 47 additions & 0 deletions examples/with-tigris/components/EachToDo.tsx
@@ -0,0 +1,47 @@
import Image from 'next/image'
import React from 'react'
import { TodoItem } from '../models/tigris/todoStarterApp/todoItems'
import styles from '../styles/EachToDo.module.css'

type Props = {
toDoItem: TodoItem
deleteHandler: (id?: number) => void
updateHandler: (item: TodoItem) => void
}
const EachTodo = ({ toDoItem, deleteHandler, updateHandler }: Props) => {
return (
<>
<li className={styles.each}>
<button
className={styles.eachButton}
onClick={() => {
updateHandler(toDoItem)
}}
>
<Image
src={toDoItem.completed ? '/circle-checked.svg' : '/circle.svg'}
layout="fixed"
width={20}
height={20}
alt="Check Image"
/>
<span
style={toDoItem.completed ? { textDecoration: 'line-through' } : {}}
>
{toDoItem.text}
</span>
</button>
<button
className={styles.deleteBtn}
onClick={() => {
deleteHandler(toDoItem.id)
}}
>
<Image src="/delete.svg" width={24} height={24} alt="Check Image" />
</button>
</li>
</>
)
}

export default EachTodo
14 changes: 14 additions & 0 deletions examples/with-tigris/components/LoaderWave.tsx
@@ -0,0 +1,14 @@
import React from 'react'
import styles from '../styles/LoaderWave.module.css'

const LoaderWave = () => {
return (
<div className={styles.holder}>
<div className={`${styles.loader} ${styles.l1}`}></div>
<div className={`${styles.loader} ${styles.l2}`}></div>
<div className={`${styles.loader} ${styles.l3}`}></div>
</div>
)
}

export default LoaderWave
28 changes: 28 additions & 0 deletions examples/with-tigris/lib/tigris.ts
@@ -0,0 +1,28 @@
import { DB, Tigris } from '@tigrisdata/core'

const DB_NAME = 'todoStarterApp'

declare global {
// eslint-disable-next-line no-var
var tigrisDb: DB
}

let tigrisDb: DB

// Caching the client because `next dev` would otherwise create a
// new connection on every file save while previous connection is active due to
// hot reloading. However, in production, Next.js would completely tear down before
// restarting, thus, disconnecting and reconnecting to Tigris.
if (process.env.NODE_ENV !== 'production') {
if (!global.tigrisDb) {
const tigrisClient = new Tigris()
global.tigrisDb = tigrisClient.getDatabase(DB_NAME)
}
tigrisDb = global.tigrisDb
} else {
const tigrisClient = new Tigris()
tigrisDb = tigrisClient.getDatabase(DB_NAME)
}

// export to share DB across modules
export default tigrisDb
22 changes: 22 additions & 0 deletions examples/with-tigris/models/tigris/todoStarterApp/todoItems.ts
@@ -0,0 +1,22 @@
import {
TigrisCollectionType,
TigrisDataTypes,
TigrisSchema,
} from '@tigrisdata/core/dist/types'

export const COLLECTION_NAME = 'todoItems'

export interface TodoItem extends TigrisCollectionType {
id?: number
text: string
completed: boolean
}

export const TodoItemSchema: TigrisSchema<TodoItem> = {
id: {
type: TigrisDataTypes.INT32,
primary_key: { order: 1, autoGenerate: true },
},
text: { type: TigrisDataTypes.STRING },
completed: { type: TigrisDataTypes.BOOLEAN },
}
6 changes: 6 additions & 0 deletions examples/with-tigris/next.config.js
@@ -0,0 +1,6 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
swcMinify: true,
}

module.exports = nextConfig
23 changes: 23 additions & 0 deletions examples/with-tigris/package.json
@@ -0,0 +1,23 @@
{
"private": true,
"scripts": {
"predev": "APP_ENV=development npm run setup",
"dev": "next dev",
"build": "next build",
"postbuild": "APP_ENV=production npm run setup",
"start": "next start",
"setup": "npx ts-node scripts/setup.ts"
},
"dependencies": {
"@tigrisdata/core": "beta",
"next": "latest",
"react": "18.2.0",
"react-dom": "18.2.0"
},
"devDependencies": {
"@types/node": "18.11.2",
"@types/react": "18.0.21",
"@types/react-dom": "18.0.6",
"typescript": "4.8.4"
}
}
9 changes: 9 additions & 0 deletions examples/with-tigris/pages/_app.tsx
@@ -0,0 +1,9 @@
import '../styles/globals.css'
import type { AppProps } from 'next/app'
import React from 'react'

function MyApp({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />
}

export default MyApp

0 comments on commit 0f8b3d6

Please sign in to comment.