{"id":40013875,"url":"https://github.com/pyronear/pyro-openwebcams","last_synced_at":"2026-01-19T03:02:17.329Z","repository":{"id":327377798,"uuid":"1109048318","full_name":"pyronear/pyro-openwebcams","owner":"pyronear","description":"Identify and implement early detection of wildfires using as many open webcams as possible.","archived":false,"fork":false,"pushed_at":"2026-01-15T10:04:59.000Z","size":96,"stargazers_count":2,"open_issues_count":18,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-15T15:44:25.233Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pyronear.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-03T09:12:15.000Z","updated_at":"2026-01-15T10:01:35.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/pyronear/pyro-openwebcams","commit_stats":null,"previous_names":["pyronear/pyro-openwebcams"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/pyronear/pyro-openwebcams","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pyronear%2Fpyro-openwebcams","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pyronear%2Fpyro-openwebcams/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pyronear%2Fpyro-openwebcams/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pyronear%2Fpyro-openwebcams/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pyronear","download_url":"https://codeload.github.com/pyronear/pyro-openwebcams/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pyronear%2Fpyro-openwebcams/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28559351,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-19T00:46:33.223Z","status":"online","status_checked_at":"2026-01-19T02:00:08.049Z","response_time":67,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-19T03:02:17.193Z","updated_at":"2026-01-19T03:02:17.310Z","avatar_url":"https://github.com/pyronear.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Pyronear Open Webcams\n\nIdentify and implement Pyronear early detection of wildfires using as many open webcams as possible.\n\n## License\n\nDistributed under the Apache 2 License. See [`LICENSE`](LICENSE) for more information.\n\n## Table of Contents 📋\n\nWIP\n\n- [Features](https://github.com/cfatrane/nextjs-boilerplate?tab=readme-ov-file#features-%EF%B8%8F)\n- [Project Structure](https://github.com/cfatrane/nextjs-boilerplate?tab=readme-ov-file#project-structure-)\n\n## Features 🛠️\n\n- [**Commitlint**](https://commitlint.js.org/) : Commit conventions allow your team to add more semantic meaning to your git history. This e.g. includes type, scope or breaking changes.\n- [**Husky** 🐶](https://typicode.github.io/husky/) : Automatically lint your commit messages, code, and run tests upon committing or pushing.\n- [**i18n**](https://next-intl-docs.vercel.app/) : The process of designing and developing software so it can be adapted for users of different cultures and languages\n- [**Jest**](https://jestjs.io/) : For unit and integration testing\n- [**ESlint**](https://eslint.org/) : Statically analyzes your code to quickly find problems. It is built into most text editors and you can run ESLint as part of your continuous integration pipeline.\n- [**Next Themes**](https://github.com/pacocoursey/next-themes) : An abstraction for themes in your React app.\n- [**Prettier**](https://prettier.io/) : An opinionated code formatter. It enforces a consistent style by parsing your code and re-printing it with its own rules that take the maximum line length into account, wrapping code when necessary.\n- [**Prisma**](https://www.prisma.io/docs/orm) : Prisma ORM is an open-source next-generation ORM\n- [**React Hook Form**](https://react-hook-form.com/) : A library that helps you validate forms in React.\n- [**Shadcn**](https://ui.shadcn.com/) : A collection of beautifully designed, accessible, and customizable React components that you can use to build modern web applications with Next. js.\n- [**Tailwind**](https://tailwindcss.com/) : A utility-first CSS framework that streamlines web development by providing a set of pre-designed utility classes.\n- [**VSCode**](https://marketplace.visualstudio.com/vscode) : Configuration file and recommended extensions\n- [**Vercel**](https://vercel.com/) : Vercel provides the developer tools and cloud infrastructure to build, scale, and secure a faster, more personalized web.\n- [**Zod**](https://zod.dev/) : Schema validation with static type inference\n\n### Soon ⏱️\n\n- [**Crowdin**](https://crowdin.com/) : A localization management platform that aims to make the translation process more efficient.\n- **Github Actions** : A continuous integration and continuous delivery (CI/CD) platform that allows you to automate your build, test, and deployment pipeline.\n- [**Storybook**](https://storybook.js.org/) : A development environment tool that is used as a playground for UI components. It allows us, the developers, to create and test components in isolation.\n- [**Sentry**](https://sentry.io/) : For real-time error tracking and monitoring\n- [**Posthog**](https://posthog.com/) : PostHog is the only all-in-one platform for product analytics, feature flags, session replays, experiments, and surveys that's built for developer\n- [**Google Tag Manager**](https://nextjs.org/docs/app/building-your-application/optimizing/third-party-libraries#google-tag-manager)\n- [**Google Analytics**](https://nextjs.org/docs/app/building-your-application/optimizing/third-party-libraries#google-analytics)\n\n## Getting Started 🤔\n\nFirst, run the development server:\n\n```bash\nnpm run dev\n# or\nyarn dev\n# or\npnpm dev\n# or\nbun dev\n```\n\nOpen [http://localhost:3000](http://localhost:3000) with your browser to see the result.\n\nYou can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.\n\nThis project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.\n\n### Scripts\n\n```bash\n\"dev\": \"next dev\",\n\"dev:turbo\": \"next dev --turbo\",\n\"build\": \"next build\",\n\"start\": \"next start\",\n\"lint\": \"next lint\",\n\"lint:fix\": \"next lint --fix\",\n\"format\": \"prettier --check --ignore-path .gitignore .\",\n\"format:fix\": \"prettier --write --ignore-path .gitignore .\",\n\"prepare\": \"husky\",\n\"test\": \"jest\",\n\"test:watch\": \"jest --watch\",\n\"prisma:studio\": \"prisma studio\",\n\"prisma:generate\": \"prisma generate\",\n\"prisma:validate\": \"prisma validate\",\n\"prisma:format\": \"prisma format\",\n\"prisma:migrate:dev\": \"prisma migrate dev\",\n\"prisma:migrate:reset\": \"prisma migrate reset\",\n\"prisma:migrate:deploy\": \"prisma migrate deploy\",\n\"vercel-build\": \"prisma generate \u0026\u0026 prisma migrate deploy \u0026\u0026 next build\"\n```\n\n## Project Structure 📁\n\n```bash\n├── .env.example                # Example environment variables file\n├── .gitignore                  # Git ignore file to exclude files and directories from version control\n├── .husky                      # Husky configuration for Git hooks\n├── .prettierrc                 # Prettier configuration file\n├── .vscode                     # VSCode configurations (extensions, settings, etc.)\n├── commitlint.config.ts        # Commitlint configuration file\n├── components.json             # JSON file for component configurations\n├── eslint.config.mjs           # ESLint configuration file\n├── jest.config.ts              # Jest configuration file for testing\n├── jest.setup.ts               # Jest setup file for initializing tests\n├── messages                    # Folder for translation files\n│   ├── en                      # English translations\n│   └── fr                      # French translations\n├── next-env.d.ts               # TypeScript definitions for Next.js\n├── next.config.mjs             # Next.js configuration file\n├── package.json                # Project dependencies and scripts\n├── postcss.config.mjs          # PostCSS configuration file\n├── prisma                      # Prisma ORM configuration and migrations\n│   ├── migrations              # Folder for database migrations\n│   └── schema.prisma           # Prisma schema file\n├── public                      # Public assets directory\n├── src                         # Source code directory\n│   ├── app                     # Main application folder\n│   │   ├── [locale]            # Locale-specific routes\n│   │   │   ├── (auth)          # Authentication-related pages\n│   │   │   ├── dashboard       # Dashboard pages\n│   │   │   ├── layout.tsx      # Layout component for locale-specific routes\n│   │   │   ├── not-found.tsx   # 404 Not Found page for locale-specific routes\n│   │   │   ├── page.tsx        # Main page component for locale-specific routes\n│   │   │   └── settings        # Settings pages\n│   │   ├── favicon.ico         # Favicon for the application\n│   │   ├── global-error.tsx    # Global error handling component\n│   │   ├── globals.css         # Global CSS styles\n│   │   ├── layout.tsx          # Main layout component\n│   │   └── not-found.tsx       # 404 Not Found page\n│   ├── assets                  # Static assets like images, fonts, and icons\n│   ├── constants               # Constant values used across the application\n│   ├── components              # Reusable components\n│   │   ├── shared              # Shared components\n│   │   │   └── ThemeToggle     # Theme toggle component\n│   │   ├── theme-provider.tsx  # Theme provider component\n│   │   └── ui                  # UI components\n│   ├── db                      # Database-related utilities and configurations\n│   ├── i18n                    # Internationalization configuration\n│   ├── lib                     # Utility functions and libraries\n│   ├── middleware.ts           # Middleware configuration\n│   ├── services                # Service layer for API calls and business logic\n│   ├── types                   # TypeScript type definitions\n│   └── utils                   # List of utils functions\n├── tailwind.config.ts          # Tailwind CSS configuration file\n├── tsconfig.json               # TypeScript configuration file\n└── vercel.json                 # Vercel deployment configuration\n```\n\n### Commitlint\n\ncommitlint checks if your commit messages meet the [conventional commit format](https://conventionalcommits.org).\n\nIn general the pattern mostly looks like this:\n\n```sh\ntype(scope?): subject  #scope is optional; multiple scopes are supported (current delimiter options: \"/\", \"\\\" and \",\")\n```\n\nReal world examples can look like this:\n\n```text\nchore: run tests on travis ci\n```\n\n```text\nfix(server): send cors headers\n```\n\n```text\nfeat(blog): add comment section\n```\n\nCommon types according to [commitlint-config-conventional (based on the Angular convention)](https://github.com/conventional-changelog/commitlint/tree/master/@commitlint/config-conventional#type-enum) can be:\n\n- build: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)\n- chore: Other changes that don't modify src or test files\n- ci: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)\n- docs: Documentation only changes\n- feat: A new feature\n- fix: A bug fix\n- perf: A code change that improves performance\n- refactor: A code change that neither fixes a bug nor adds a feature\n- revert: Reverts a previous commit\n- style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)\n- test: Adding missing tests or correcting existing tests\n\n#### Git Commit Messages\n\n- Use the present tense (\"Add feature\" not \"Added feature\")\n- Use the imperative mood (\"Move cursor to...\" not \"Moves cursor to...\")\n- Limit the first line to 72 characters or less\n- Reference issues and pull requests liberally after the first line\n- When only changing documentation, include `[ci skip]` in the commit title\n- Consider starting the commit message with an applicable emoji:\n  - 🎨 `:art:` when improving the format/structure of the code\n  - 🐎 `:racehorse:` when improving performance\n  - 🚱 `:non-potable_water:` when plugging memory leaks\n  - 📝 `:memo:` when writing docs\n  - 🐧 `:penguin:` when fixing something on Linux\n  - 🍎 `:apple:` when fixing something on macOS\n  - 🏁 `:checkered_flag:` when fixing something on Windows\n  - 🐛 `:bug:` when fixing a bug\n  - 🔥 `:fire:` when removing code or files\n  - 💚 `:green_heart:` when fixing the CI build\n  - ✅ `:white_check_mark:` when adding tests\n  - 🔒 `:lock:` when dealing with security\n  - ⬆️ `:arrow_up:` when upgrading dependencies\n  - ⬇️ `:arrow_down:` when downgrading dependencies\n  - 👕 `:shirt:` when removing linter warnings\n\n---\n\n### Eslint\n\nWIP\n\n---\n\n### i18n / Translation 🗺️\n\nThis project uses the `next-intl` library for internationalization (i18n). Below are the steps to set up and use i18n in this project.\n\n#### Setup\n\n1. **Configuration**:\n   The i18n configuration is defined in [`src/i18n/routing.ts`](src/i18n/routing.ts). This file sets up the supported locales and the default locale.\n\n   ```ts\n   import { createNavigation } from \"next-intl/navigation\";\n   import { defineRouting } from \"next-intl/routing\";\n\n   export const routing = defineRouting({\n     locales: [\"en\", \"fr\"],\n     defaultLocale: \"en\",\n   });\n\n   export type Locale = (typeof routing.locales)[number];\n\n   export const { Link, redirect, usePathname, useRouter, getPathname } =\n     createNavigation(routing);\n   ```\n\n2. **Middleware**:\n   The middleware for handling i18n routing is set up in [`src/middleware.ts`](src/middleware.ts). This middleware ensures that the correct locale is used based on the request.\n\n   ```ts\n   import createMiddleware from \"next-intl/middleware\";\n\n   import { routing } from \"./i18n/routing\";\n\n   export default createMiddleware(routing);\n\n   export const config = {\n     matcher: [\n       // Match only internationalized pathnames\n       \"/\",\n       \"/(en|fr)/:path*\",\n       // Skip Next.js internals and all static files, unless found in search params\n       \"/((?!_next|[^?]*\\\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)\",\n       // Always run for API routes\n       \"/(api|trpc)(.*)\",\n     ],\n   };\n   ```\n\n3. **Messages**:\n   Translation messages are stored in the `messages` directory. Each locale has its own folder containing JSON files for different namespaces. For example:\n\n   - `messages/en/home.json`\n   - `messages/fr/home.json`\n\n4. **Request Configuration**:\n   The request configuration for i18n is defined in [`src/i18n/request.ts`](src/i18n/request.ts). This file ensures that the correct messages are loaded based on the request locale.\n\n   ```ts\n   import { getRequestConfig } from \"next-intl/server\";\n\n   import { Locale, routing } from \"./routing\";\n\n   export default getRequestConfig(async ({ requestLocale }) =\u003e {\n     let locale = await requestLocale;\n     if (!locale || !routing.locales.includes(locale as Locale)) {\n       locale = routing.defaultLocale;\n     }\n\n     return {\n       locale,\n       messages: {\n         ...(await import(`../../messages/${locale}/home.json`)).default,\n         ...(await import(`../../messages/${locale}/auth.json`)).default,\n         ...(await import(`../../messages/${locale}/notFound.json`)).default,\n       },\n     };\n   });\n   ```\n\n#### Usage\n\n1. **Adding Translations**:\n   To add translations, create or update the JSON files in the `messages` directory. For example, to add a new translation for the home page in French, update `messages/fr/home.json`:\n\n   ```json\n   {\n     \"Home\": {\n       \"Docs\": {\n         \"title\": \"Documents\",\n         \"text\": \"Trouvez des informations détaillées sur les fonctionnalités et l'API de Next.js.\"\n       },\n       \"Learn\": {\n         \"title\": \"Apprendre\",\n         \"text\": \"Apprenez à connaître Next.js dans un cours interactif avec des quiz !\"\n       }\n     }\n   }\n   ```\n\n2. **Using Translations in Components**:\n   Use the `useTranslations` hook from `next-intl` to access translations in your components. For example, in a component:\n\n   ```tsx\n   import { useTranslations } from \"next-intl\";\n\n   export default function Home() {\n     const t = useTranslations(\"home\");\n\n     return (\n       \u003cmain\u003e\n         \u003ch1\u003e{t(\"Docs.title\")}\u003c/h1\u003e\n         \u003cp\u003e{t(\"Docs.text\")}\u003c/p\u003e\n       \u003c/main\u003e\n     );\n   }\n   ```\n\n3. **Linking to Different Locales**:\n   Use the `Link` component from `next-intl/navigation` to create links that respect the current locale. For example:\n\n   ```tsx\n   import { Link } from \"@/i18n/navigation\";\n\n   export default function Navigation() {\n     return (\n       \u003cnav\u003e\n         \u003cLink href=\"/\"\u003e{t(\"Home\")}\u003c/Link\u003e\n         \u003cLink href=\"/about\"\u003e{t(\"About\")}\u003c/Link\u003e\n       \u003c/nav\u003e\n     );\n   }\n   ```\n\nBy following these steps, you can set up and use i18n in your Next.js project to support multiple languages.\n\n---\n\n### Prisma\n\n```sh\n# Set up a new Prisma project\n$ prisma init\n# Generate artifacts (e.g. Prisma Client)\n$ prisma generate\n# Browse your data\n$ prisma studio\n# Create migrations from your Prisma schema, apply them to the database, generate artifacts (e.g. Prisma Client)\n$ prisma migrate dev\n# Pull the schema from an existing database, updating the Prisma schema\n$ prisma db pull\n# Push the Prisma schema state to the database\n$ prisma db push\n# Validate your Prisma schema\n$ prisma validate\n# Format your Prisma schema\n$ prisma format\n# Display Prisma version info\n$ prisma version\n# Display Prisma debug info\n$ prisma debug\n```\n\n#### Getting started with Prisma Migrate\n\n##### Customizing migrations\n\nIn some scenarios, you need to edit a migration file before you apply it. For example, to change the direction of a 1-1 relation (moving the foreign key from one side to another) without data loss, you need to move data as part of the migration - this SQL is not part of the default migration, and must be written by hand.\n\nThis guide explains how to edit migration files and gives some examples of use cases where you may want to do this.\n\n###### How to edit a migration file\n\nTo edit a migration file before applying it, the general procedure is the following:\n\n1. Make a schema change that requires custom SQL (for example, to preserve existing data)\n\n2. Create a draft migration using:\n\n   `npx prisma migrate dev --create-only`\n\n3. Modify the generated SQL file.\n\n4. Apply the modified SQL by running:\n\n   `npx prisma migrate dev`\n\n###### [Example: Rename a field](https://www.prisma.io/docs/orm/prisma-migrate/workflows/customizing-migrations#example-rename-a-field)\n\n###### [Example: Change the direction of a 1-1 relation](https://www.prisma.io/docs/orm/prisma-migrate/workflows/customizing-migrations#example-change-the-direction-of-a-1-1-relation)\n\n---\n\n### Storybook\n\nWIP\n\n---\n\n### Test\n\nGenerate a basic Jest configuration file by running the following command `npm init jest@latest`\n\nThis will take you through a series of prompts to setup Jest for your project, including automatically creating a `jest.config.ts`.\n\nJest will look for test files with any of the following popular naming conventions:\n\n- Files with `.js` suffix in `__tests__` folders.\n- Files with `.test.js` suffix.\n- Files with `.spec.js` suffix.\n\nThe `.test.js` / `.spec.js` files (or the `__tests__`folders) can be located at any depth under the `src` top level folder.\n\nWe recommend to put the test files (or `__tests__` folders) next to the code they are testing so that relative imports appear shorter. For example, if `App.test.js` and `App.js` are in the same folder, the test only needs to `import App from './App'` instead of a long relative path. Collocation also helps find tests more quickly in larger projects.\n\nTo run test `yarn test`\n\n## VSCode Extensions 💻\n\n### [Better Comments](https://marketplace.visualstudio.com/items?itemName=aaron-bond.better-comments)\n\nThe Better Comments extension will help you create more human-friendly comments in your code.\nWith this extension, you will be able to categorize your annotations into:\n\n- Alerts\n- Queries\n- TODOs\n- Highlights\n- Commented out code can also be styled to make it clear the code shouldn't be there\n- Any other comment styles you'd like can be specified in the settings\n\n### [Tailwind CSS IntelliSense](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss)\n\nTailwind CSS IntelliSense enhances the Tailwind development experience by providing Visual Studio Code users with advanced features such as autocomplete, syntax highlighting, and linting.\n\n### [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint)\n\nIntegrates ESLint into VS Code. If you are new to ESLint check the documentation.\n\nThe extension uses the ESLint library installed in the opened workspace folder. If the folder doesn't provide one the extension looks for a global install version. If you haven't installed ESLint either locally or globally do so by running npm install eslint in the workspace folder for a local install or `npm install -g eslint` for a global install.\n\nOn new folders you might also need to create an .eslintrc configuration file. You can do this by either using the VS Code command Create ESLint configuration or by running the eslint command in a terminal with `npx eslint --init`.\n\n### [i18n Ally](https://marketplace.visualstudio.com/items?itemName=SonarSource.sonarlint-vscode)\n\nGeneral Features\n\n- Supports multi-root workspaces\n- Supports remote development\n- Supports numerous popular frameworks\n- Supports linked locale messages\n- Uses i18n for the extension itself, of course. Translation List\n\n### [SonarLint](https://marketplace.visualstudio.com/items?itemName=Lokalise.i18n-ally)\n\nSonarLint by Sonar is a free IDE extension that empowers you to fix coding issues before they exist. More than a linter, SonarLint detects and highlights issues that can lead to bugs, vulnerabilities, and code smells as you create your code. It offers clear remediation guidance and educational help, so you can fix issues before the code is committed. SonarLint in VS Code supports analysis of JS/TS, Python, PHP, Java, C, C++, C#, Go, and IaC code locally in your IDE.\n\n### [Error Lens](https://marketplace.visualstudio.com/items?itemName=usernamehw.errorlens)\n\nErrorLens turbo-charges language diagnostic features by making diagnostics stand out more prominently, highlighting the entire line wherever a diagnostic is generated by the language and also prints the message inline.\n\n## Deployment 🚀\n\nThe easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template\u0026filter=next.js\u0026utm_source=create-next-app\u0026utm_campaign=create-next-app-readme) from the creators of Next.js.\n\nCheck out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.\n\n## Learn More 🧠\n\nTo learn more about Next.js, take a look at the following resources:\n\n- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.\n- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.\n\nYou can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!\n\n## Suggestions ☝️\n\n### Auth\n\n- [Kinde](https://kinde.com/)\n\n### Components\n\n- [shadcn](https://ui.shadcn.com/)\n- [MUI](https://mui.com/core/)\n- [Next UI](https://nextui.org/)\n- [Ant Design](https://ant.design/)\n- [Aceternity UI](https://ui.aceternity.com/)\n- [Preline UI](https://preline.co/index.html)\n- [Origin UI](https://originui.com/)\n- [Tailus](https://ui.tailus.io/)\n\n### Database\n\n- [Neon Tech](https://console.neon.tech/)\n- [Supabase](https://supabase.com/)\n- [Turso](https://turso.tech/)\n- [Planetscale](https://planetscale.com/)\n\n### State Management\n\n- [Redux + Next](https://redux-toolkit.js.org/usage/nextjs)\n- [Recoil](https://recoiljs.org/)\n- [Zustand](https://github.com/pmndrs/zustand)\n\n### Validation\n\n- [Joi](https://joi.dev/)\n- [Yup](https://github.com/jquense/yup)\n- [Zod](https://zod.dev/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpyronear%2Fpyro-openwebcams","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpyronear%2Fpyro-openwebcams","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpyronear%2Fpyro-openwebcams/lists"}