├── .env.example ├── .github ├── CODE_OF_CONDUCT.md ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── azure-static-web-apps-agreeable-sea-088859a10.yml ├── .gitignore ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── LICENSE.md ├── README.md ├── components └── Product.js ├── lib └── prisma.js ├── next.config.js ├── package.json ├── pages ├── _app.js ├── api │ └── products.js └── index.js ├── postcss.config.js ├── prisma ├── DigiCertGlobalRootCA.crt.pem ├── data.js ├── schema.prisma └── seed.js ├── public ├── favicon.ico ├── images │ ├── helmet.jpg │ ├── shirt.jpg │ ├── socks.jpg │ └── sweatshirt.jpg └── vercel.svg ├── styles └── globals.css └── tailwind.config.js /.env.example: -------------------------------------------------------------------------------- 1 | DATABASE_URL=mysql://:@/?sslaccept=strict 2 | -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Microsoft Open Source Code of Conduct 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 4 | 5 | Resources: 6 | 7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) 8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns 10 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 4 | > Please provide us with the following information: 5 | > --------------------------------------------------------------- 6 | 7 | ### This issue is for a: (mark with an `x`) 8 | ``` 9 | - [ ] bug report -> please search issues before submitting 10 | - [ ] feature request 11 | - [ ] documentation issue or request 12 | - [ ] regression (a behavior that used to work and stopped in a new release) 13 | ``` 14 | 15 | ### Minimal steps to reproduce 16 | > 17 | 18 | ### Any log messages given by the failure 19 | > 20 | 21 | ### Expected/desired behavior 22 | > 23 | 24 | ### OS and Version? 25 | > Windows 7, 8 or 10. Linux (which distribution). macOS (Yosemite? El Capitan? Sierra?) 26 | 27 | ### Versions 28 | > 29 | 30 | ### Mention any other details that might be useful 31 | 32 | > --------------------------------------------------------------- 33 | > Thanks! We'll be in touch soon. 34 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Purpose 2 | 3 | * ... 4 | 5 | ## Does this introduce a breaking change? 6 | 7 | ``` 8 | [ ] Yes 9 | [ ] No 10 | ``` 11 | 12 | ## Pull Request Type 13 | What kind of change does this Pull Request introduce? 14 | 15 | 16 | ``` 17 | [ ] Bugfix 18 | [ ] Feature 19 | [ ] Code style update (formatting, local variables) 20 | [ ] Refactoring (no functional changes, no api changes) 21 | [ ] Documentation content changes 22 | [ ] Other... Please describe: 23 | ``` 24 | 25 | ## How to Test 26 | * Get the code 27 | 28 | ``` 29 | git clone [repo-address] 30 | cd [repo-name] 31 | git checkout [branch-name] 32 | npm install 33 | ``` 34 | 35 | * Test the code 36 | 37 | ``` 38 | ``` 39 | 40 | ## What to Check 41 | Verify that the following are valid 42 | * ... 43 | 44 | ## Other Information 45 | -------------------------------------------------------------------------------- /.github/workflows/azure-static-web-apps-agreeable-sea-088859a10.yml: -------------------------------------------------------------------------------- 1 | name: Azure Static Web Apps CI/CD 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | types: [opened, synchronize, reopened, closed] 9 | branches: 10 | - main 11 | 12 | jobs: 13 | build_and_deploy_job: 14 | if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action != 'closed') 15 | runs-on: ubuntu-latest 16 | name: Build and Deploy Job 17 | steps: 18 | - uses: actions/checkout@v3 19 | with: 20 | submodules: true 21 | - name: Build And Deploy 22 | id: builddeploy 23 | uses: Azure/static-web-apps-deploy@v1 24 | with: 25 | azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_AGREEABLE_SEA_088859A10 }} 26 | repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments) 27 | action: "upload" 28 | ###### Repository/Build Configurations - These values can be configured to match your app requirements. ###### 29 | # For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig 30 | app_location: "/" # App source code path 31 | api_location: "" # Api source code path - optional 32 | output_location: "" # Built app content directory - optional 33 | ###### End of Repository/Build Configurations ###### 34 | 35 | close_pull_request_job: 36 | if: github.event_name == 'pull_request' && github.event.action == 'closed' 37 | runs-on: ubuntu-latest 38 | name: Close Pull Request Job 39 | steps: 40 | - name: Close Pull Request 41 | id: closepullrequest 42 | uses: Azure/static-web-apps-deploy@v1 43 | with: 44 | azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_AGREEABLE_SEA_088859A10 }} 45 | action: "close" 46 | -------------------------------------------------------------------------------- /.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 | 18 | # misc 19 | .DS_Store 20 | 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | .pnpm-debug.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 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [project-title] Changelog 2 | 3 | 4 | # x.y.z (yyyy-mm-dd) 5 | 6 | *Features* 7 | * ... 8 | 9 | *Bug Fixes* 10 | * ... 11 | 12 | *Breaking Changes* 13 | * ... 14 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to [project-title] 2 | 3 | This project welcomes contributions and suggestions. Most contributions require you to agree to a 4 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us 5 | the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com. 6 | 7 | When you submit a pull request, a CLA bot will automatically determine whether you need to provide 8 | a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions 9 | provided by the bot. You will only need to do this once across all repos using our CLA. 10 | 11 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 12 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or 13 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 14 | 15 | - [Code of Conduct](#coc) 16 | - [Issues and Bugs](#issue) 17 | - [Feature Requests](#feature) 18 | - [Submission Guidelines](#submit) 19 | 20 | ## Code of Conduct 21 | Help us keep this project open and inclusive. Please read and follow our [Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 22 | 23 | ## Found an Issue? 24 | If you find a bug in the source code or a mistake in the documentation, you can help us by 25 | [submitting an issue](#submit-issue) to the GitHub Repository. Even better, you can 26 | [submit a Pull Request](#submit-pr) with a fix. 27 | 28 | ## Want a Feature? 29 | You can *request* a new feature by [submitting an issue](#submit-issue) to the GitHub 30 | Repository. If you would like to *implement* a new feature, please submit an issue with 31 | a proposal for your work first, to be sure that we can use it. 32 | 33 | * **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr). 34 | 35 | ## Submission Guidelines 36 | 37 | ### Submitting an Issue 38 | Before you submit an issue, search the archive, maybe your question was already answered. 39 | 40 | If your issue appears to be a bug, and hasn't been reported, open a new issue. 41 | Help us to maximize the effort we can spend fixing issues and adding new 42 | features, by not reporting duplicate issues. Providing the following information will increase the 43 | chances of your issue being dealt with quickly: 44 | 45 | * **Overview of the Issue** - if an error is being thrown a non-minified stack trace helps 46 | * **Version** - what version is affected (e.g. 0.1.2) 47 | * **Motivation for or Use Case** - explain what are you trying to do and why the current behavior is a bug for you 48 | * **Browsers and Operating System** - is this a problem with all browsers? 49 | * **Reproduce the Error** - provide a live example or a unambiguous set of steps 50 | * **Related Issues** - has a similar issue been reported before? 51 | * **Suggest a Fix** - if you can't fix the bug yourself, perhaps you can point to what might be 52 | causing the problem (line of code or commit) 53 | 54 | You can file new issues by providing the above information at the corresponding repository's issues link: https://github.com/[organization-name]/[repository-name]/issues/new]. 55 | 56 | ### Submitting a Pull Request (PR) 57 | Before you submit your Pull Request (PR) consider the following guidelines: 58 | 59 | * Search the repository (https://github.com/[organization-name]/[repository-name]/pulls) for an open or closed PR 60 | that relates to your submission. You don't want to duplicate effort. 61 | 62 | * Make your changes in a new git fork: 63 | 64 | * Commit your changes using a descriptive commit message 65 | * Push your fork to GitHub: 66 | * In GitHub, create a pull request 67 | * If we suggest changes then: 68 | * Make the required updates. 69 | * Rebase your fork and force push to your GitHub repository (this will update your Pull Request): 70 | 71 | ```shell 72 | git rebase master -i 73 | git push -f 74 | ``` 75 | 76 | That's it! Thank you for your contribution! 77 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Azure Samples 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 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. 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 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Next.js + Azure Database for MySQL 2 | 3 | This is a [Next.js](https://nextjs.org/) project that uses [Prisma](https://www.prisma.io/) to connect to a [Azure database for MySQL](https://learn.microsoft.com/azure/mysql/) database and [Tailwind CSS](https://tailwindcss.com/) for styling. 4 | 5 | ## Prerequisites 6 | 7 | - [Node.js](https://nodejs.org/en/download/) 8 | - Create [Azure database for MySQL Flexible Server](https://learn.microsoft.com/azure/mysql/flexible-server/quickstart-create-server-portal) in Azure. Create a [free Azure account](https://azure.microsoft.com/en-us/free/) if you dont have one. 9 | 10 | ## Set up the database 11 | In the [Azure portal](https://portal.azure.com), go to MySQL Flexible server resource and select **Add** to create new database called `products`. 12 | 13 | ![image](https://user-images.githubusercontent.com/3684166/215588422-f5735f74-dace-4da4-9995-903ed618eaf5.png) 14 | 15 | ## Set up the starter Next.js app 16 | 17 | 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: 18 | 19 | ```bash 20 | npx create-next-app nextjs-azure-mysql 21 | # or 22 | yarn create next-app nextjs-azure-mysql 23 | # or 24 | pnpm create next-app nextjs-azure-mysql 25 | ``` 26 | 27 | ## Download SSL certificate 28 | Azure database for MySQL Flexible Server uses a public SSL CA certificate to connect. Placing the [DigiCertGlobalRootCA.crt.pem](https://dl.cacerts.digicert.com/DigiCertGlobalRootCA.crt.pem) in the `prisma` folder will help with authentication over SSL to work seamlessly. 29 | 30 | ## MySQL connection string 31 | Now you need to create a connection string in the following format for the Azure database for MySQL Flexible Server. When creating the server, you provided an admin username and password which you will use in the connection string. Note that SSL is enabled by default on Azure database for MySQL Flexible server and hence please use `sslaccept=strict` in the connection string. If you have [disabled SSL](https://learn.microsoft.com/azure/mysql/flexible-server/how-to-connect-tls-ssl#disable-ssl-enforcement-on-your-flexible-server) on the server, you can remove it from the connection string. 32 | 33 | ```text 34 | mysql://:@/?sslaccept=strict 35 | ``` 36 | 37 | Example 38 | ```text 39 | mysql://demoadminuser:adminpassword@mysqlserver1.mysql.database.azure.com/products?sslaccept=strict 40 | ``` 41 | 42 | Add the connection string as environment variable in the Vercel project configuration 43 | 44 | ![image](https://user-images.githubusercontent.com/3684166/215590298-08e34ff7-7f40-4a78-aa0e-d75b1da32593.png) 45 | 46 | 47 | ## Push the schema into the database 48 | Push the database schema to your Azure database for MySQL Flexible Server database `products` using Prisma. 49 | 50 | `npx prisma db push` 51 | 52 | Run the seed script to populate your database with `Product` and `Category` data. 53 | 54 | `npm run seed` 55 | 56 | ## Run the App 57 | 58 | Run the app with following command: 59 | 60 | `npm run dev` 61 | 62 | Open your browser at [localhost:3000](localhost:3000) to see the running application. 63 | 64 | ## Deploy your own 65 | 66 | After you've got your application running locally, it's time to deploy it. Deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=next-example): 67 | 68 | [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https://github.com/mksuni/nextjs-app-azure-db-mysql&repository-name=nextjs-app-azure-db-mysql&env=DATABASE_URL) 69 | 70 | -------------------------------------------------------------------------------- /components/Product.js: -------------------------------------------------------------------------------- 1 | import Image from 'next/image' 2 | 3 | export default function Product({ product }) { 4 | const { name, description, price, image, category } = product 5 | 6 | return ( 7 |
11 | {name} 19 |
20 |
{name}
21 |

{description}

22 |

${price}

23 |
24 |
25 | 26 | {category.name} 27 | 28 |
29 |
30 | ) 31 | } 32 | -------------------------------------------------------------------------------- /lib/prisma.js: -------------------------------------------------------------------------------- 1 | import { PrismaClient } from '@prisma/client' 2 | 3 | let prisma 4 | 5 | if (process.env.NODE_ENV === 'production') { 6 | prisma = new PrismaClient() 7 | } else { 8 | if (!global.prisma) { 9 | global.prisma = new PrismaClient() 10 | } 11 | prisma = global.prisma 12 | } 13 | 14 | export default prisma 15 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | module.exports = { 3 | reactStrictMode: true, 4 | } 5 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "dev": "next dev", 5 | "build": "npx prisma generate && next build", 6 | "start": "next start", 7 | "seed": "node prisma/seed.js" 8 | }, 9 | "dependencies": { 10 | "@prisma/client": "4.16.2", 11 | "next": "latest", 12 | "react": "18.2.0", 13 | "react-dom": "18.2.0" 14 | }, 15 | "devDependencies": { 16 | "autoprefixer": "10.4.2", 17 | "postcss": "8.4.31", 18 | "prisma": "4.16.2", 19 | "tailwindcss": "3.0.23" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /pages/_app.js: -------------------------------------------------------------------------------- 1 | import '../styles/globals.css' 2 | 3 | export default function MyApp({ Component, pageProps }) { 4 | return 5 | } 6 | -------------------------------------------------------------------------------- /pages/api/products.js: -------------------------------------------------------------------------------- 1 | // Next.js API route support: https://nextjs.org/docs/api-routes/introduction 2 | import prisma from './../../lib/prisma.js' 3 | 4 | export default async function handler(req, res) { 5 | if (req.method === 'GET') { 6 | try { 7 | const data = await prisma.product.findMany({}) 8 | return res.status(200).json({ data }) 9 | } catch (err) { 10 | console.error(err) 11 | return res.status(500).json({ msg: 'Something went wrong' }) 12 | } 13 | } else { 14 | return res.status(405).json({ msg: 'Method not allowed' }) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /pages/index.js: -------------------------------------------------------------------------------- 1 | import Head from 'next/head' 2 | import Product from '../components/Product' 3 | import prisma from '../lib/prisma' 4 | 5 | export default function Home({ products }) { 6 | return ( 7 |
8 | 9 | Next.js and Azure Database for MySQL Quickstart 10 | 11 | 12 | 13 | 14 |
15 |

Next.js and Azure Database for MySQL Quickstart

16 |

17 | 🔥 Shop from the hottest items in the world 🔥 18 |

19 |
20 | {products.map((product) => ( 21 | 22 | ))} 23 |
24 |
25 | 26 |
27 |
28 |
29 | ) 30 | } 31 | 32 | export async function getStaticProps(context) { 33 | const data = await prisma.product.findMany({ 34 | include: { 35 | category: true, 36 | }, 37 | }) 38 | 39 | //convert decimal value to string to pass through as json 40 | const products = data.map((product) => ({ 41 | ...product, 42 | price: product.price.toString(), 43 | })) 44 | return { 45 | props: { products }, 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /prisma/DigiCertGlobalRootCA.crt.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh 3 | MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 4 | d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD 5 | QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT 6 | MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j 7 | b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG 8 | 9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB 9 | CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 10 | nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt 11 | 43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P 12 | T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 13 | gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO 14 | BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR 15 | TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw 16 | DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr 17 | hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg 18 | 06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF 19 | PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls 20 | YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk 21 | CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= 22 | -----END CERTIFICATE----- 23 | -------------------------------------------------------------------------------- /prisma/data.js: -------------------------------------------------------------------------------- 1 | const { Prisma } = require('@prisma/client') 2 | 3 | const categories = [ 4 | { 5 | name: 'Hats', 6 | description: 'Things you can wear on your head', 7 | }, 8 | { 9 | name: 'Socks', 10 | description: 'Things you can wear on your feet', 11 | }, 12 | { 13 | name: 'Shirts', 14 | description: 'Things you wear on the top half of your body', 15 | }, 16 | ] 17 | 18 | const products = [ 19 | { 20 | name: 'Cool helmet.', 21 | description: 'A nice helmet to wear on your head', 22 | price: new Prisma.Decimal(19.95), 23 | image: '/images/helmet.jpg', 24 | category_id: 1, 25 | }, 26 | { 27 | name: 'Grey T-Shirt', 28 | description: 'A nice shirt that you can wear on your body', 29 | price: new Prisma.Decimal(22.95), 30 | image: '/images/shirt.jpg', 31 | category_id: 3, 32 | }, 33 | { 34 | name: 'Socks', 35 | description: 'Cool socks that you can wear on your feet', 36 | price: new Prisma.Decimal(12.95), 37 | image: '/images/socks.jpg', 38 | category_id: 2, 39 | }, 40 | { 41 | name: 'Sweatshirt', 42 | description: 'Cool sweatshirt that you can wear on your body', 43 | price: new Prisma.Decimal(12.95), 44 | image: '/images/sweatshirt.jpg', 45 | category_id: 3, 46 | }, 47 | ] 48 | 49 | module.exports = { 50 | products, 51 | categories, 52 | } 53 | -------------------------------------------------------------------------------- /prisma/schema.prisma: -------------------------------------------------------------------------------- 1 | generator client { 2 | provider = "prisma-client-js" 3 | previewFeatures = ["referentialIntegrity"] 4 | } 5 | 6 | datasource db { 7 | provider = "mysql" 8 | url = env("DATABASE_URL") 9 | referentialIntegrity = "prisma" 10 | } 11 | 12 | model Product { 13 | id Int @id @default(autoincrement()) 14 | name String 15 | description String 16 | price Decimal 17 | image String 18 | category Category? @relation(fields: [category_id], references: [id]) 19 | category_id Int 20 | 21 | @@index([category_id]) 22 | } 23 | 24 | model Category { 25 | id Int @id @default(autoincrement()) 26 | name String 27 | description String 28 | products Product[] 29 | } 30 | -------------------------------------------------------------------------------- /prisma/seed.js: -------------------------------------------------------------------------------- 1 | const { PrismaClient } = require('@prisma/client') 2 | const { categories, products } = require('./data.js') 3 | const prisma = new PrismaClient() 4 | 5 | const load = async () => { 6 | try { 7 | await prisma.category.deleteMany() 8 | console.log('Deleted records in category table') 9 | 10 | await prisma.product.deleteMany() 11 | console.log('Deleted records in product table') 12 | 13 | await prisma.$queryRaw`ALTER TABLE Product AUTO_INCREMENT = 1` 14 | console.log('reset product auto increment to 1') 15 | 16 | await prisma.$queryRaw`ALTER TABLE Category AUTO_INCREMENT = 1` 17 | console.log('reset category auto increment to 1') 18 | 19 | await prisma.category.createMany({ 20 | data: categories, 21 | }) 22 | console.log('Added category data') 23 | 24 | await prisma.product.createMany({ 25 | data: products, 26 | }) 27 | console.log('Added product data') 28 | } catch (e) { 29 | console.error(e) 30 | process.exit(1) 31 | } finally { 32 | await prisma.$disconnect() 33 | } 34 | } 35 | 36 | load() 37 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/vercel-nextjs-app-azure-db-mysql/7eb352c7524798d6f245c0b37bed9ab71c85115d/public/favicon.ico -------------------------------------------------------------------------------- /public/images/helmet.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/vercel-nextjs-app-azure-db-mysql/7eb352c7524798d6f245c0b37bed9ab71c85115d/public/images/helmet.jpg -------------------------------------------------------------------------------- /public/images/shirt.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/vercel-nextjs-app-azure-db-mysql/7eb352c7524798d6f245c0b37bed9ab71c85115d/public/images/shirt.jpg -------------------------------------------------------------------------------- /public/images/socks.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/vercel-nextjs-app-azure-db-mysql/7eb352c7524798d6f245c0b37bed9ab71c85115d/public/images/socks.jpg -------------------------------------------------------------------------------- /public/images/sweatshirt.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/vercel-nextjs-app-azure-db-mysql/7eb352c7524798d6f245c0b37bed9ab71c85115d/public/images/sweatshirt.jpg -------------------------------------------------------------------------------- /public/vercel.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /styles/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: [ 4 | './pages/**/*.{js,ts,jsx,tsx}', 5 | './components/**/*.{js,ts,jsx,tsx}', 6 | ], 7 | theme: { 8 | extend: {}, 9 | }, 10 | plugins: [], 11 | } 12 | --------------------------------------------------------------------------------