{
  "/apk": {
    "title": "Index",
    "data": {
      "download-apk-file#Download APK file": "You can download the APK file from the following link:\nhttps://cdn.tanna.app/biddo/app-release-v0.15.apk"
    }
  },
  "/apps/mobile-app": {
    "title": "Mobile App",
    "data": {
      "video-preview#Video Preview": "",
      "features#Features": "Create Auctions: Easily create auctions for a wide array of items including art, LEGO sets, cars, houses, and more.\nFlexible Bidding System: Users an place bids on auction items with the option for auction owners to accept or reject any offer, ensuring complete control over the transaction.\nUser-Friendly Interface: A sleek, intuitive interface designed to provide an exceptional user experience on both iOS and Android devices.\nSign In & Sign Up: Seamless registration and login using Firebase, supporting email and password, Apple, Google, and anonymous sign-in. Includes a \"Forgot Password\" feature.\nIntro Screen: Skippable introduction screen showcasing how the app works for new users.\nLocation Setting: Users can set precise auction locations using Google Maps for enhanced accuracy.\nFavorite Auctions: Save favorite auctions for quick access and tracking.\nAdvanced Search & Filter: Users can filter auctions by category, location, or price and search for auctions or other users by keywords.\nAuction Reporting: Users can report auctions, accounts, or bids if they encounter any issues.\nLast Seen Auctions: View a history of last seen auctions for easy reference.\nImage Upload: Users can upload images when creating an auction to provide detailed visuals of the items.\nPush Notifications: Customizable push notifications, allowing users to select which notifications they want to receive.\nMulti-Language Support: Supports multiple languages, including English, Romanian, French, German, Italian, Spanish, and Japanese.\nTheme Modes: Offers both light mode and dark mode themes for user preference.\nChat Functionality: Users can chat with each other, complete with an emoji plugin for enriched communication.\nProfile Management: Users can update their name and profile picture within the app and manage their personal information.\nAccount Management: Option for users to delete their account, including all associated data.\nFollow & Unfollow: Users can follow or unfollow others, receiving notifications when followed users create auctions.\nBlocking Users: Users can block others, preventing blocked accounts from placing bids on their auctions.\nAuction Management: Users can update or remove their auctions effortlessly.\nMap Screen with Auction Locator: Users can easily explore auctions happening near them by accessing a dedicated map screen. This feature displays all active auctions pinned to their specific locations, allowing users to discover items for sale in their vicinity or any other area of interest. This visual approach to browsing auctions provides a convenient way to find local deals or items in specific geographic locations.\nPersonalised Auction Recommendations: Enhance the user experience with tailored auction suggestions. The app analyzes users' favorite auctions and categories to recommend new auctions that align with their interests. This intelligent recommendation system ensures that users are always presented with auctions that they are most likely to find appealing, increasing engagement and the chances of successful bids.\nAuction Promotion with In-App Coins: Users can boost the visibility of their auctions by promoting them within the app. This functionality allows sellers to use in-app coins to highlight their auctions, giving them a better chance of attracting more bids. The promotion system is straightforward and efficient, helping users to make their auctions stand out in a competitive marketplace.\nRevenueCat Integration for Coin Purchases: The app integrates seamlessly with RevenueCat, allowing users to purchase in-app coins securely and conveniently. These coins can be used for various premium features, including promoting auctions. The integration ensures that users have a smooth purchasing experience, with multiple payment options available for acquiring coins.\nView Auction Likes: Users can see who has liked a specific auction, providing social proof and enhancing the auction's credibility. This feature not only encourages more interaction but also helps sellers gauge the popularity of their auction items.\nAuction View Count: Transparency and insights are key to understanding auction performance. The app displays the number of views each auction has received, giving sellers valuable feedback on their listing’s visibility. This metric helps sellers understand the level of interest in their auction and can inform future auction strategies.\nAdMob Integration for Monetization: AdMob-powered monetization system with banner, interstitial, and rewarded ads. Banner ads are seamlessly integrated within the app's UI, while interstitial ads are shown at key moments, such as after users create or manage auction bids, enhancing engagement without overuse. Rewarded ads offer users a chance to earn coins in exchange for viewing, with coin values adjustable by admins, ensuring flexibility in incentivizing app interactions. This feature aims to balance user engagement with revenue generation in a user-friendly manner.",
      "screenshots-of-the-app#Screenshots of the App": "",
      "get-started#Get Started": "Transform your auction experience with our Mobile Auction App.\nDownload the APK: https://cdn.tanna.app/biddo/app-release-v0.15.apkSupport & Documentation: Comprehensive support and detailed documentation to assist with installation and customization.Don't miss out on this opportunity to elevate your auction services. Get our Mobile Auction App today and start creating successful auctions effortlessly!"
    }
  },
  "/apps/web-app": {
    "title": "Web App",
    "data": {
      "test-for-free#Test for free": "You can test the web app for free by visiting the following link: Biddo Web App",
      "video-preview#Video Preview": "",
      "features#Features": "Create Auctions: Easily create auctions for a wide array of items including art, LEGO sets, cars, houses, and more.\nFlexible Bidding System: Users an place bids on auction items with the option for auction owners to accept or reject any offer, ensuring complete control over the transaction.\nUser-Friendly Interface: A sleek, intuitive interface designed to provide an exceptional user experience on both iOS and Android devices.\nSign In & Sign Up: Seamless registration and login using Firebase, supporting email and password, Apple, Google, and anonymous sign-in. Includes a \"Forgot Password\" feature.\nIntro Screen: Skippable introduction screen showcasing how the app works for new users.\nLocation Setting: Users can set precise auction locations using Google Maps for enhanced accuracy.\nFavorite Auctions: Save favorite auctions for quick access and tracking.\nAdvanced Search & Filter: Users can filter auctions by category, location, or price and search for auctions or other users by keywords.\nAuction Reporting: Users can report auctions, accounts, or bids if they encounter any issues.\nLast Seen Auctions: View a history of last seen auctions for easy reference.\nImage Upload: Users can upload images when creating an auction to provide detailed visuals of the items.\nPush Notifications: Customizable push notifications, allowing users to select which notifications they want to receive.\nMulti-Language Support: Supports multiple languages, including English, Romanian, French, German, Italian, Spanish, and Japanese.\nTheme Modes: Offers both light mode and dark mode themes for user preference.\nChat Functionality: Users can chat with each other, complete with an emoji plugin for enriched communication.\nProfile Management: Users can update their name and profile picture within the app and manage their personal information.\nAccount Management: Option for users to delete their account, including all associated data.\nFollow & Unfollow: Users can follow or unfollow others, receiving notifications when followed users create auctions.\nBlocking Users: Users can block others, preventing blocked accounts from placing bids on their auctions.\nAuction Management: Users can update or remove their auctions effortlessly.\nMap Screen with Auction Locator: Users can easily explore auctions happening near them by accessing a dedicated map screen. This feature displays all active auctions pinned to their specific locations, allowing users to discover items for sale in their vicinity or any other area of interest. This visual approach to browsing auctions provides a convenient way to find local deals or items in specific geographic locations.\nPersonalised Auction Recommendations: Enhance the user experience with tailored auction suggestions. The app analyzes users' favorite auctions and categories to recommend new auctions that align with their interests. This intelligent recommendation system ensures that users are always presented with auctions that they are most likely to find appealing, increasing engagement and the chances of successful bids.\nAuction Promotion with In-App Coins: Users can boost the visibility of their auctions by promoting them within the app. This functionality allows sellers to use in-app coins to highlight their auctions, giving them a better chance of attracting more bids. The promotion system is straightforward and efficient, helping users to make their auctions stand out in a competitive marketplace.\nStripe Integration for Coin Purchases: The app integrates seamlessly with Stripe, allowing users to purchase coins securely and conveniently. These coins can be used for various premium features, including promoting auctions. The integration ensures that users have a smooth purchasing experience.\nAuction View Count: Transparency and insights are key to understanding auction performance. The app displays the number of views each auction has received, giving sellers valuable feedback on their listing’s visibility. This metric helps sellers understand the level of interest in their auction and can inform future auction strategies.",
      "screenshots-of-the-app#Screenshots of the App": ""
    }
  },
  "/docs/admin-panel": {
    "title": "Index",
    "data": {
      "setup-admin-panel#Setup Admin Panel": "The Admin Panel is generated using AdminJS, a modern Admin Panel for Node.js with React. It allows you to build admin panels quickly and efficiently, with a focus on extensibility and flexibility. The Admin Panel is designed to be user-friendly and intuitive, providing a seamless experience for managing your application's data.In order to activate the Admin Panel generation, you need to add a few properties inside the .env file.\nADMIN_ENABLED=true\nADMIN_EMAIL=YOUR_DESIRED_EMAIL (e.g. test@test.com)\nADMIN_PASSWORD=YOUR_DESIRED_PASSWORD (e.g. password)\nADMIN_COOKIE_PASSWORD=THE_PASSWORD_FOR_THE_COOKIE (e.g. cookie_password)\nIf the ADMIN_ENABLED property is set to true, the Admin Panel will be generated automaticaly when you start the server and will be accessible at the /admin route. You can log in using the email and password specified in the .env file.\nFor example, if the server is running on http://localhost:7777, you can access the Admin Panel at http://localhost:7777/admin.",
      "functionalities#Functionalities": "The Admin Panel provides a range of functionalities to help you manage your application's data effectively. Some of the key features include:\nDashboard: An overview of key metrics and data visualizations to help you monitor your application's performance.\nResource Management: Manage your application's resources, including creating, updating, and deleting data entries.\nUser Management: Manage user accounts, including  updating user information, and deleting user accounts.\nNotifications: Manage the push notifications sent to users, including resending notifications and viewing notification history.\nPayments view: View the payments made by users, including payment details and transaction history.\nFilter and Search: Easily filter and search for specific data entries to quickly find the information you need."
    }
  },
  "/contact/contact": {
    "title": "Contact",
    "data": {
      "contact-me#Contact Me": "You can contact me by email at pascaionut94@gmail.com. I will be happy to answer any questions you may have."
    }
  },
  "/docs/admin-panel/screenshots": {
    "title": "Screenshots",
    "data": {
      "screenshots-of-the-admin-panel#Screenshots of the Admin Panel": ""
    }
  },
  "/buy": {
    "title": "Buy Biddo Mobile Application & NodeJS Backend",
    "data": {
      "": "Thank you for your interest in purchasing the Biddo mobile application and NodeJS backend.You can buy the full source code from the following links:\nCode Market\nCodeCanyon"
    }
  },
  "/docs/admin-panel/settings": {
    "title": "Settings",
    "data": {
      "settings-you-can-change#Settings you can change": "On opening the admin panel, if you select the settings tab you will see only one record. This record is the settings record. You can change the following settings:",
      "general-settings#General settings": "Default Currency: This is the default currency that will be used in the app. You can change this to any currency you want.\nAuction Active Time In Hours: This is the time in hours that an auction will be active for. After this time, no bids can be placed on the auction.\nMax Allowed Distance Between Users In KM: This is the maximum distance between two users in kilometers. If the distance between two users is greater than this value, one cannot bid on the other's auction.\nMax Product Price: This is the maximum price that an auction can be listed for. If a user tries to list a product for a price greater than this value, the product will not be listed.\nPromotion Coins Cost: This is the cost in coins for promoting an auction. If a user wants to promote an auction, they will have to pay this amount of coins.\nDefault Product Image Url: If no image is uploaded for a auction, this image will be used as the default image for the auction.\nFree Auctions Count: This is the number of free auctions that a user can list. After this number of free auctions, the user will have to pay coins to list an auction.\nFree Bids Count: This is the number of free bids that a user can place. After this number of free bids, the user will have to pay coins to place a bid.\nAuctions Coins Cost: This is the cost in coins for listing an auction. If a user wants to list an auction, they will have to pay this amount of coins.\nBids Coins Cost: This is the cost in coins for placing a bid. If a user wants to place a bid, they will have to pay this amount of coins.\nAutomatically Accept Bid On Auction Close: This is a boolean value that determines if the highest bid on an auction will be automatically accepted when the auction closes.",
      "mobile-app-only-settings#Mobile App Only Settings": "**Confidentiality Link **: This is the link to the confidentiality policy of the app. This link will be shown in the mobile app.\nRevenue Cat Android Key: This is the key for the revenue cat android sdk. This key is used to track in app purchases in the app.\nRevenue Cat iOS Key: This is the key for the revenue cat iOS sdk. This key is used to track in app purchases in the app.\nAds enabled on Android: This is a boolean value that determines if ads are enabled on the android app.\nAds enabled on iOS: This is a boolean value that determines if ads are enabled on the iOS app.\nAndroid Ads Banner Id: This is the banner id for the ads on the android app.\nAndroid Ads Interstitial Id: This is the interstitial id for the ads on the android app.\nAndroid Ads Rewarded Id: This is the rewarded id for the ads on the android app.\nIos Ads Banner Id: This is the banner id for the ads on the iOS app.\nIos Ads Interstitial Id: This is the interstitial id for the ads on the iOS app.\nIos Ads Rewarded Id: This is the rewarded id for the ads on the iOS app.",
      "web-app-only-settings#Web App Only Settings": "Account Page Layout: This is the layout of the account page. You can choose between sidebar and tabs.\nProfile Page Layout: This is the layout of the profile page. You can choose between sidebar and tabs.\nApp name: This is the name of the app. This name will be shown in the title of the web app.\nGoogle Play Store Link: This is the link to the google play store page of the app. This link will be shown in the web app.\nApp Store Link: This is the link to the app store page of the app. This link will be shown in the web app.\nYou can update these settings from here:"
    }
  },
  "/docs": {
    "title": "Welcome to Biddo",
    "data": {
      "": "Usually, after you purchase this product, you will receive a zip file containing the following:",
      "biddo-docs-static#biddo-docs-static": "This is the static project documentation that can be ran locally, without having an internet connection",
      "biddo-docs-nextjs#biddo-docs-nextjs": "This is the documentation website that you are currently viewing. It is built using NextJS and can be deployed to Vercel.",
      "biddo_client#biddo_client": "This is the Flutter application of biddo. It is the client side of the Biddo app. In order for it to work properly, it requires a server to be running.You will see further details about how the application is structured and how to run it.",
      "biddo_server#biddo_server": "This is the NodeJS application of biddo. It is the server side of the Biddo app.You will see further details about how the server is structured and how to run it.",
      "biddo_web#biddo_web": "This is the NextJS application of biddo. It is the web side of the Biddo app. In order for it to work properly, it requires a server to be running.You will see further details about how the application is structured and how to run it."
    }
  },
  "/docs/mobile-app/architecture": {
    "title": "Architecture",
    "data": {
      "code-architecture#Code Architecture": "The codebase is organized in a way that makes it easy to understand and navigate. Here are some of the key components:\nCore: Inside the lib/core folder, you will find the core functionality of the app. This includes the state management, the API calls, the models and the services.\nlang: Inside the lib/lang folder, you will find the translations for the app. Each language has its own file.\nscreens: Inside the lib/screens folder, you will find the screens of the app. Each screen has its own folder with the components and styles. If the users navigates from a main screen to another screen, the new screen will be inside the main screen folder.\ntheme: Inside the lib/theme folder, you will find the theme of the app. This includes the colors, the fonts and the sizes for both the light and dark mode.\nutils: Inside the lib/utils folder, you will find the utility functions used across the app.\nwidgets: Inside the lib/widgets folder, you will find the widgets of the app. These are reusable components that can be used across the app.",
      "core#Core": "Inside the lib/core folder, you will find 3 main folders:\nmodels: The models are responsible for defining the structure of the data that is used in the app. Each model is defined in a separate file and is responsible for handling a specific set of data.\nrepositories: The sole purpose of a repository is to handle fetch requests to the API.\ncontrollers: The main purpose of a controller is to keep the state of the app. It is also responsible for handling the business logic of the app. If it needs data from the server, it usually imports a repository and fetches the data from there. The controllers are imported in the screens (not the repositories or the other way around). There is usually a controller for each model. There might be other controllers that keep state that is not related to a model.\nThe state of the application is kept using the GetX package. This package is used for state management, dependency injection and route management.\nInside the same folder, there is a getx.dart file that initializes the GetX package, together with all the repositories, controllers and services.",
      "lang#Lang": "Inside the lib/lang folder, you will find the translations for the app. Each language has its own file. The translations are used across the app to display the text in the correct language.The translations are defined in a JSON format. Each language has its own JSON file. The JSON file is structured in a way that makes it easy to add new translations or update existing ones.",
      "screens#Screens": "The application has 7 main screens:\nHome: The home screen is the first screen that the user sees when they open the app. It displays a list of the most recent auctions.\nFavourites: The favourites screen displays a list of the auctions that the user has favourited.\nCreate auction: The create auction screen allows the user to create a new auction.\nChat: The chat screen allows the user to chat with other users.\nSettings: The settings screen allows the user to change their settings.\nAuthenticate: The authenticate screen allows the user to sign in or sign up.\nAuction details: The auction details screen displays the details of an auction.\nEach of these screens have a dedicated folder inside the lib/screens folder. If inside a specific screen there are widgets that are only used in that screen, they will be inside the screen's folder, in another widgets folder. If a widget is used in multiple screens, it will be inside the lib/widgets folder.In other words, if you navigate further deep into screens, the structure of the folders will usually be in a similar manner (The nesting of the folders increases).",
      "theme#Theme": "Inside the lib/theme folder, there are 2 important files: dark.dart and light.dart. These files define the colors, fonts and sizes for both the light and dark mode. The theme is used across the app to style the components.The application has custom colors and font styles. The custom styles are defined in the extensions/base.dart file. This extension is created only to make it easier to use the custom styles across the app. An example of how to use the custom styles is shown below:\nText(\n  'Hello World',\n  style: style: Theme.of(context).extension<CustomThemeFields>()!.title,\n)"
    }
  },
  "/docs/mobile-app/deploy/android": {
    "title": "Android",
    "data": {
      "publish-mobile-app-to-google-play-store#Publish Mobile App to Google Play Store": "Follow the official Flutter guidelines to publish the app to Play Store.Guidelines: https://docs.flutter.dev/deployment/android",
      "summary-of-steps-you-need-to-follow#Summary of steps you need to follow": "In order to publish the app to the Play Store, you need to have a Google Play Developer account. If you don't have one, you can create it here\nAfter you have created the account, you need to create a new application in the Play Console\nYou need to generate a signing key and configure the app to use it\nYou can generate a signing key by opening a terminal inside the root of the project and using the following command:\nkeytool -genkey -v -keystore keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias key\nYou will be asked to provide some information about the key, such as the password, the name, the organization, etc.\nMake sure to remember the password, as you will need it later\nA file will be generated in the root of the app and you need to move it to the android/app folder, live in the following image.\nYou will need to create a key.properties file in the android folder with the following content:\nstorePassword=YOUR_PASSWORD_HERE\nkeyPassword=YOUR_PASSWORD_HERE\nkeyAlias=upload\nstoreFile=../app/keystore.jks\nOpen a terminal in the root of the project and run the following command:\nflutter build appbundle\nThis will generate the  build/app/outputs/bundle/release/app-release.aab file. This is the file that you will upload to the Play Store.\nBefire creating a new release, you need to complete the Play Console setup, found in the Dashboard section of the Play Console.\nInside the Google Play Console, you need to create a new Closed testing release, upload the app-release.aab file and fill in the required information about the app."
    }
  },
  "/docs/mobile-app/deploy/env": {
    "title": "Env",
    "data": {
      "update-environment-variables#Update environment variables": "Before deploying the Flutter app, make sure that you open the .env file from the app and update the SERVER_URL, WS_SERVER_URL, GOOGLE_MAPS_API_KEY, CONFIDENTIALITY_LINK, REVENUE_CAT_IOS_API_KEY and REVENUE_CAT_GOOGLE_API_KEY with the correct values.\nSERVER_URL is the URL of the server where the server is deployed\nWS_SERVER_URL is the URL of the server where the WebSocket server is deployed (e.g. if the server is deployed on http://my-server.com, the WebSocket server should be deployed on ws://my-server.com. The same applies if you're using only the IP)\nGOOGLE_MAPS_API_KEY is the API key that you get from the Google Cloud Platform. You can find more information about how to get the API key here\nCONFIDENTIALITY_LINK is the link to the privacy policy of the app\nREVENUE_CAT_IOS_API_KEY is the API key that you get from the RevenueCat dashboard for iOS\nREVENUE_CAT_GOOGLE_API_KEY is the API key that you get from the RevenueCat dashboard for Android"
    }
  },
  "/docs/mobile-app/deploy/ios": {
    "title": "iOS",
    "data": {
      "publish-to-app-store#Publish to App Store": "Follow the official Flutter guidelines to publish the app to App Store.Guidelines: https://flutter.dev/docs/deployment/ios"
    }
  },
  "/docs/mobile-app/admob": {
    "title": "Admob",
    "data": {
      "setup-admob#Setup AdMob": "The AdMob integration in the Mobile Auction App allows you to monetize your application by displaying ads to users. AdMob offers a range of ad formats, including banner, interstitial, and rewarded ads, which can be seamlessly integrated into your app's UI. This feature aims to balance user engagement with revenue generation in a user-friendly manner.The first think that you need to do is to create an AdMob account and set up your app in the AdMob dashboard. Once you have created your AdMob account and set up your app, you will receive an AdMob App ID, which you will need to add to your app's configuration.The AdMob account can be created by visiting the AdMob website.The account creation step could take some time because you need to provide banking information, sign contracts, and so on.",
      "get-admob-app-id#Get AdMob App ID": "To get your AdMob App ID, follow these steps:\nLog in to your AdMob account.\nClick on the \"Apps\" tab in the sidebar.\nClick on the \"Add App\" button.\nSelect the platform for your app (Android or iOS).\nYou will need 2 application IDs: one for Android and one for iOS.This is how the AdMob App ID looks like:",
      "add-admob-app-id-to-your-app#Add AdMob App ID to your App": "For this step, you need to open the flutter app you got inside the zip file. You will need to add you AdMob application ids to\nboth the Android and iOS projects.",
      "android#Android": "Open the AndroidManifest.xml file located in android/app/src/main/AndroidManifest.xml.\nAdd the following meta-data tag inside the <application> tag:\n<meta-data\n    android:name=\"com.google.android.gms.ads.APPLICATION_ID\"\n    android:value=\"YOUR_ADMOB_APP_ID\"/>\nThere might already be a meta-data tag with the name com.google.android.gms.ads.APPLICATION_ID. If so, you can replace the value with your AdMob App ID.",
      "ios#iOS": "Open the Info.plist file located in ios/Runner/Info.plist.\nAdd the following key-value pair:\n<key>GADApplicationIdentifier</key>\n<string>YOUR_ADMOB_APP_ID</string>\nThere might already be a key-value pair with the key GADApplicationIdentifier. If so, you can replace the value with your AdMob App ID.",
      "test-admob-ads#Test AdMob Ads": "To test AdMob ads in your app, you can use test ad units provided by Google. These test ad units will display test ads instead of real ads, allowing you to verify that the AdMob integration is working correctly.The application should run test ads by default, after you have done the previous steps.For whenever you want to go live with your own ads, you will need to create your own ad units inside the AdMob dashboard.For a more detailed guide on how to set up your ad units, you can refer to this guide.After you have your ad units, you can use the Admin Panel to add them to your app. Remember that the Admin Panel will only work if you have the NodeJS server running.\nFrom the same Admin Panel, you can either enable or disable the ads inside the app or change the coins reward for the rewarded ads."
    }
  },
  "/docs/mobile-app/deploy/secure-maps": {
    "title": "Secure Maps",
    "data": {
      "secure-your-api-key#Secure your API key": "If you are using an API key that can be accessed from anywhere, you can skip this step. However, if you have restricted the API key to be used only from a specific IP address, you need to secure the API key for the mobile app.We'll secure the key for the Android app, but similar same steps can be applied to the iOS app.On the Google Cloud API Key platoform, you have the option to restrict the API key to be used only from an android app. This is done by adding the package name and the SHA-1 certificate fingerprint of the app.The package name can be found in the android/app/build.gradle file. The android->namespace is the package name.The SHA-1 certificate fingerprint can be found by running the following command in the terminal:\nkeytool -list -v -keystore ~/.android/keystore.jks\nThis is how your API key should look like after you restrict it to be used only from an Android app:"
    }
  },
  "/docs/mobile-app/environment": {
    "title": "Environment",
    "data": {
      "environment-variables#Environment variables": "Create a new file called .env in the root of the project. This file will contain all the environment variables that are used in the project.You can copy the content from the .env.example file and paste it into the .env file.\nSERVER_URL=http://localhost:7777\nWS_SERVER_URL=ws://localhost:7777\nCONFIDENTIALITY_LINK=\nGOOGLE_MAPS_API_KEY=\nREVENUE_CAT_IOS_API_KEY=\nREVENUE_CAT_GOOGLE_API_KEY=\nSERVER_URL - The URL of the server where the NodeJS server is running. This is used in the mobile app to connect to the server.WS_SERVER_URL - The URL of the WebSocket server where the NodeJS server is running. This is used in the mobile app to connect to the server. Usually, this is the same as the SERVER_URL, but instead of the \"http(s)\" protocol, it uses the \"ws(s)\" protocol.CONFIDENTIALITY_LINK - The link to the confidentiality policy of the application. This is used in the mobile app to show the confidentiality policy. It should be a link to a webpage where the confidentiality policy is described. (After you setup the web app, you will already have a \"terms\" page that you can use here).GOOGLE_MAPS_API_KEY - The API key for Google Maps. (You will find out what value to add here in a later section)REVENUE_CAT_IOS_API_KEY - The API key for RevenueCat for iOS.(You will find out what value to add here in a later section)REVENUE_CAT_GOOGLE_API_KEY - The API key for RevenueCat for Google. (You will find out what value to add here in a later section)"
    }
  },
  "/docs/mobile-app/revenue-cat": {
    "title": "Index",
    "data": {
      "lets-enable-revenuecat-in-your-app#Let's enable RevenueCat in your app": "Make sure you have an account on RevenueCat and you have created an app in the dashboard. (Don't forget to place a valid Service Account Credentials JSON file with proper permissions when creating the project. See more information here).We'll enable the users to buy coins from the app, and we'll use the RevenueCat SDK to handle the in-app purchases.The users will have 3 options to buy coins:\n50 coins\n200 coins\n500 coins\nMake sure that you have followed Deploy section before continuing with this tutorial, as you will need to devine some \"In-App Purchases\" in both App Store and Goole Play Store.You can always follow alone the steps from the official documentation if you want to have a deeper understanding of the RevenueCat SDK.",
      "add-google-play-in-app-products#Add Google Play In-app products": "Go to the Google Play Console and select your app.\nGo to Monetize -> Products -> Add in-app products.\nAdd the following products:\n50 coins\n200 coins\n500 coins\nIn order to keep thinks simpler, make sure you are using consisting naming for the product IDs. For example, you can use coins_50, coins_200, coins_500.\nHere is an example of how the products should look like:",
      "add-app-store-in-app-products#Add App Store In-app products": "Go to the App Store Connect and select your app.\nGo to In-App Purchases -> + -> Consumable.\nAdd the following products:\n50 coins\n200 coins\n500 coins\nIn order to keep thinks simpler, make sure you are using consisting naming for the product IDs. For example, you can use coins_50, coins_200, coins_500.\nHere is an example of how the products should look like:\nIn order to test the in-app purchases using an iOS simulator, you need to enable StoreKit. You can do this by following the steps from this tutorial.",
      "add-revenuecat-products#Add RevenueCat Products": "Go to the RevenueCat Dashboard and select your project.\nGo to Products tab and add the 6 products  (3 for iOS and 3 for Android) with the same IDs as the ones you have defined in the App Store and Google Play Store.\nHere is an example of how the products should look like:"
    }
  },
  "/docs/mobile-app/google-maps-integration": {
    "title": "Google Maps Integration",
    "data": {
      "google-maps-integration#Google Maps integration": "You should already have an API key from the NodeJS Server - Google Maps Integration\nAdd the key to the .env file in the root of the project\nGOOGLE_MAPS_API_KEY=YOUR_API_KEY",
      "pay-attention#Pay attention": "If inside the Google Clous Storage you have limited the API key to be used only from a specific IP address, you should create a new API key and use it in the .env file.We'll cover how to secure the Google Maps API key for the mobile app in the Deploy section."
    }
  },
  "/docs/mobile-app/revenue-cat/client": {
    "title": "Client",
    "data": {
      "mobile-app-configuration#Mobile app configuration": "The mobile app should only require two API Keys that are found inside the RevenueCat dashboard.\nGo to the RevenueCat dashboard and select your app.\nThere should already be two API keys (one for iOS and one for Android) that you can use in the mobile app. (If not, you can create them by going to the API Keys tab and clicking on the + New button)\nCopy the API keys and add them to the mobile app, inside the .env file.\nREVENUE_CAT_IOS_API_KEY=YOUR_IOS_API_KEY\nREVENUE_CAT_GOOGLE_API_KEY=YOUR_ANDROID_API_KEY",
      "make-sure-in-app-purchases-are-enabled-on-ios#Make sure In-App Purchases are enabled on iOS": "You need to open the ios/Runner.xcworkspace file in Xcode and enable In-App Purchases for the app.\nThis should normally be enough to have the mobile app configured to work with RevenueCat, as it will automatically fetch the products from the server and display them in the app.Now, let's see how we can configure the server to work with RevenueCat.",
      "testing#Testing": "If you want to test the payment flow in a sandbox mode (debug), please follow the steps from the official documentation."
    }
  },
  "/docs/mobile-app/firebase-integration": {
    "title": "Firebase Integration",
    "data": {
      "firebase-integration#Firebase integration": "",
      "create-firebase-project#Create Firebase project": "Navigate to the Firebase Console and create a new project",
      "add-android-to-the-project#Add Android to the project": "Make sure you are using the correct package name. You can find the package name in the android/app/build.gradle file\nMake sure you download the google-services.json file and place it in the android/app directory\nIf you're having issue while trying to login using Google on Android, make sure you have the SHA-1 key added to the Android Firebase project.\nYou can generate and see the SHA-1 key by running the following command in the terminal:\nkeytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android",
      "add-ios-to-the-project#Add iOS to the project": "At the next step, make sure you download the GoogleService-Info.plist file and place it in the ios/Runner directory\nMake sure you have these two files inside the project",
      "configure-ios-notifications#Configure iOS notifications": "Follow the steps from the Firebase documentation to configure iOS notifications",
      "enable-firebase-authentication#Enable Firebase authentication": "We will enable the following authentication methods:\nYou just need to follow the steps from the Firebase Console, for each of them.\nIn order for the Apple Sign In to work, you need to add the Sign in with Apple capability to your project, from xcode. Select the Signing & Capabilities tab, and add \"Sign In With Apple\" as a new Capability then select a team on the Code Signing section.\nThis will generate and configure an App ID in the \"Certificates, Identifiers & Profiles\" section of the Apple Developer portal.",
      "enable-inside-project#Enable inside project": "After you done all the steps above, you need to open a terminal inside the root directory of the mobile app and run the following commands, one after another:\nfirebase login\ndart pub global activate flutterfire_cli\nflutterfire configure\nMake sure you enable both android and ios when asked"
    }
  },
  "/docs/mobile-app/revenue-cat/server": {
    "title": "Server",
    "data": {
      "server-side-integration#Server Side Integration": "In order for a purchase to be considered successfully completed, the server needs to validate the purchase and update the user's coins in the database.For this to happen, we will configure a webhook on the RevenueCat dashboard that will send a POST request to our server every time a purchase is made.",
      "store-product-ids-in-the-env-file#Store product IDs in the .env file": "The server must know what products are available for purchase, so we need to store the product IDs in the .env file.\nPAYMENT_PRODUCT_50_COINS=biddo_app_coins_50\nPAYMENT_PRODUCT_200_COINS=biddo_app_coins_200\nPAYMENT_PRODUCT_500_COINS=biddo_app_coins_500\nThese product IDs are found in the RevenueCat dashboard, in the Products tab.Only cases for 50, 200, and 500 coins are handled. If you have more products, you also need to check the src/config.ts file, where the PAYMENT_PRODUCTS array is defined.These product IDs will be sent to the mobile app, in order for it to know what products are available for purchase.\nIf you have more products that offer the same amount of coins (e.g. 100 coins), you can add all the product IDs in the same value, separated by comma (,). For example:\nPAYMENT_PRODUCT_200_COINS=biddo_app_coins_200_ios,biddo_app_coins_200_android",
      "configure-revenuecat-webhook#Configure RevenueCat Webhook": "Go to the RevenueCat dashboard and select your app.\nGo to the Integrations tab and click on the + Add Integration button.\nSelect Webhooks from the list of integrations.\nYou will be asked to add a few details about the webhook:\nName: Give the webhook a name that will help you identify it later.\nURL: Add the URL of your server where the webhook will send the POST request.\nAuthorization: Add a secret key that will be used to authenticate the request on the server.\nEnvironment: Select the environment where the webhook will be active (Sandbox or Production).\nAn example of how the URL and the Authorization key should look like:\nURL: https://YOUR_SERVER_OR_YOUR_URL/payment/hook\nAuthorization: YOUR_DESIRED_SECRET_KEY (Make sure you copy this)\nIf you want to test the webhook locally, you can use a tool like ngrok to create a tunnel to your local server.\nThe YOUR_DESIRED_SECRET_KEY value needs to be copied and added to the server's .env file, as it will be used to authenticate the webhook requests.\nThis is how the field should be added to the .env file:\nPAYMENT_AUTH_KEY=YOUR_DESIRED_SECRET_KEY\nIf you want to test the payment flow, please also have a look at the following tutorial, on RevenueCat.On Android, your app will need to be accepted in the Play Store before you can test the in-app purchases. You can create a Closed testing track for this."
    }
  },
  "/docs/mobile-app/setup-prerequisites": {
    "title": "Setup Prerequisites",
    "data": {
      "setup-prerequisites#Setup Prerequisites": "",
      "install-java-jdk#Install Java Jdk": "Download and install the latest version of Java JDK from the official websiteThe Java version used when creating this app was: java 22.0.2 2024-07-16",
      "install-flutter#Install Flutter": "Download and install the latest version of Flutter from the official websiteIf you prefer video tutorials, you can check the following playlist for the full installation process:\nhttps://www.youtube.com/playlist?list=PLSzsOkUDsvdtl3Pw48-R8lcK2oYkk40cm",
      "install-android-studio-for-android-development#Install Android Studio (for Android development)": "Download and install the latest version of Android Studio from the official website"
    }
  },
  "/docs/mobile-app/running-in-dev": {
    "title": "Running in Dev",
    "data": {
      "running-in-development#Running in Development": "In order to run the flutter app in development mode, you need to have an emulator or a physical device connected to your computer.You just have to open a terminal inside the root directory of the project and run the following command:\nflutter run",
      "follow-video-tutorial-for-running-the-app-in-development-mode#Follow video tutorial for running the app in development mode": ""
    }
  },
  "/docs/server/architecture": {
    "title": "Architecture",
    "data": {
      "code-architecture#Code Architecture": "The server is built using the Express.js framework and the Sequelize ORM.The codebase is organized in a way that makes it easy to understand and navigate. Here are some of the key components:\nRoutes: The routes are defined in the src/api/routes directory. Each route is defined in a separate file and is responsible for handling a specific set of API endpoints.\nMiddlewares: The middlewares are defined in the src/api/middlewares directory. Each middleware is defined in a separate file and is responsible for handling a specific set of tasks.\nauth: The authentication middleware is responsible for verifying the user's identity and ensuring that the user is authorized to access the requested resource.\ncache: The cache middleware is responsible for caching the response of the API endpoints to improve performance.\nrate-limiter: The rate limiter middleware is responsible for limiting the number of requests that a user can make to the server in a given period of time.\nupload The upload middleware is responsible for handling file uploads.\nvalidate-requests: The validate requests middleware is responsible for validating the request body, query parameters, and headers.\nConstants: The constants are defined in the src/constants directory. We define all the constants that are used in the project in this directory.\nDatabase: The database migrations, seeds and setup are defined in the src/database directory. We use Sequelize to manage the database schema and migrations.\nPush Notifications: The push notifications are handled using the src/lib/notifications directory. We use Firebase to send push notifications to the users. Each notification is defined in a separate file.\nSocket.io: The real-time communication is handled using the src/ws directory. We use Socket.io to establish a real-time connection between the server and the client.\nModules: For each entity in the system, we define a separate module in the src/modules directory. Each module is responsible for handling the business logic related to that entity. Each of these modules contains 3 files:\ncontroller: The controller is responsible for handling the incoming requests and sending the response back to the client.\nrepository: The repository is responsible to interact with the database and perform CRUD operations.\nmodel: The model is responsible for defining the schema of the entity and interacting with the database.\nThe flow inside the server is as follows:\nThe request comes to the routes.\nThe routes call the middlewares.\nThe middlewares perform the necessary tasks.\nA controller is called to handle the request.\nThe controller interacts with the repository to perform CRUD operations.\nThe repository interacts with the database.\nThe response is sent back to the client from the controller"
    }
  },
  "/docs/server/google-bucket": {
    "title": "Google Bucket",
    "data": {
      "prerequisites#Prerequisites": "A Google Cloud Platform account\nA project on Google Cloud Platform (These 2 steps are covered in the Mobile App - Google Maps Integration)\nInstall GCloud and run auth command\nDownload GCloud https://cloud.google.com/sdk/\nOpen a terminal and run the following command\ngcloud auth application-default login --project=YOUR_PROJECT_ID",
      "create-a-bucket#Create a bucket": "Go to Google Cloud Platform on https://console.cloud.google.com/\nClick on console.\nSelect the project you want to use.\nIn the searchbar, search for \"Buckets\" and click on \"Buckets\".\nClick on \"Create Bucket\".\nAdd a new name and other required data for your bucket and click on \"Create\". (Make sure you select a region that is close to your server's location)\nYou should see a screen similar to this one\nGo to the PERMISSIONS tab and allow anyone to view the files from the bucket\nClick on GRANT ACCESS\nAdd allUsers as new principal\nAdd Storage Object Viewer as role\nThe bucket is now created and anyone can see the images uploaded there. Let's see how we can upload and delete files from the bucket.",
      "create-a-service-account#Create a service account": "In the Google Console platform, search for Service Accounts IAM\nClick on the \"Create Service Account\" button\nAdd a name and description for your service account and click on \"Continue\"\nGrant the service account the Storage Admin role and click on \"Done\"\nClick on the service account you just created, got to the Keys tab and click on Add key with JSON format. This will download a JSON file with the credentials for your service account.\nCopy the content of the JSON file that was downloaded\nCreate a service-account.json file in the root of the server and paste the content of the JSON file inside it",
      "add-bucket-to-env#Add bucket to .env": "Add name of the bucket inside the .env file in the root of the server\nGCLOUD_STORAGE_BUCKET=YOUR_BUCKET_NAME"
    }
  },
  "/docs/server/deploy": {
    "title": "Deploy",
    "data": {
      "deploy-the-server#Deploy the server": "We are going to deploy the server to a virtual machine on Kamatera. This process should work on any other cloud provider as well. All you need to have is access to a virtual machine with a public IP address.We are taking into consideration that you already have a virtual machine running with Ubuntu.You also need to have access to a PostgreSQL database. If you don't have a PostgreSQL database, there are plenty of cloud providers that offer managed PostgreSQL databases.\n(One example is Render). If you don't want to use managed database, you can always follow the steps to install PostgreSQL on your virtual machine. A nice tutorial can be found here.",
      "prepare-the-virtual-machine#Prepare the virtual machine": "In order for the deployment script to work, you need to make sure that you have SSH access to the virtual machine.\nYou can say that you have SSH access to the machine, if you can connect to it by running the following command from a terminal:\nssh <user>@<ip_of_machine>\nMake sure that the database is accessible from the IP of the virtual machine.\nMake sure you have docker installed on the virtual machine. You can install docker by running the following command, while connected to the virtual machine:\nsudo apt install docker.io\nYou can also find here a tutorial on how you can install Docker.\nMake sure you have NodeJs installed on the virtual machine. You can install NodeJs by running the following command, while connected to the virtual machine:\nsudo apt install nodejs\nsudo apt install npm\nInstall and configure nginx if not already configured. We will start the server on port 7777 by default and we need to make sure that whenever the server is accessed on port 80, the requests are redirected to port 7777.\ninstall nginx by running the following command, while connected to the virtual machine:\nsudo apt install nginx\nopen the nginx configuration file by running the following command:\nsudo nano /etc/nginx/sites-available/default\nadd a reverse proxy configuration to the nginx configuration file:\nserver {\n    listen 80;\n    server_name <your-server-domain-or-ip>;\n    location / {\n        proxy_pass http://localhost:7777;\n        proxy_http_version 1.1;\n        proxy_set_header Upgrade $http_upgrade;\n        proxy_set_header Connection 'upgrade';\n        proxy_set_header Host $host;\n        proxy_cache_bypass $http_upgrade;\n    }\n}\ntest if the nginx configuration is correct by running the following command:\nsudo nginx -t\nrestart the nginx service by running the following command:\nsudo systemctl restart nginx",
      "publish-the-server#Publish the server": "Create a new file inside the scripts directory called deploy.sh and copy the content from the scripts/deploy_example.sh file.\nmake sure that you replace the REMOTE_USER, REMOTE_IP and REMOTE_DIR with the correct values.\nREMOTE_USER is the user that you use to connect to the virtual machine.\nREMOTE_IP is the IP of the virtual machine.\nREMOTE_DIR is the directory where you want to deploy the server. (e.g. ~/biddo)\nmake sure you give execute permissions to the script by running the following command from a terminal in the root of the server:\nchmod +x ./scripts/deploy.sh\nCreate a new file inside the root of the server called ecosystem.config.cjs and copy the content from the ecosystem.config.example.cjs\nmake sure that you replace the values from the env object with the correct values. (These are the database credentials that you use to connect to the PostgreSQL database)\nThis file is used by PM2 to start the server. You can find more information about the ecosystem file here\nOpen a terminal in the root of the server and run the following command to deploy the server:\nnpm run publish\nCheck if the server is running by accessing the IP of the virtual machine in the browser. You should see a message similar to API HTTP SERVER 1.0.0.\nYou can also connect to the server using SSH and check the status of the docker container by running the following command:\ndocker ps -a\nYou should see a similar output as the following:\n!!Note!! If you did not implement the Integrate Google Cloud Storage tutorial, make sure that the server has enough access to store the files in the filesystem. If you implemented the tutorial, make sure that the server has access to the Google Cloud Storage bucket.\nSee server logs\nYou need to take the container ID and run connect to it, by running the following command:\ndocker exec -it <container-id> sh\nYou can see the logs of the server by running the following command:\npm2 logs\nYou can also see the logs of the server by running the following command:\ndocker logs <container-id>\nYou can find the container id by running the docker ps -a command.\nCongratulations! You have successfully deployed the server to a virtual machine.",
      "add-ssl-certificate#Add SSL certificate": "In order to secure the communication between the server and the clients, you need to add an SSL certificate to the server. We are going to use Let's Encrypt to generate the SSL certificate.First of all, you need to make sure that you have a bought domain. You can buy a domain from Namecheap, GoDaddy, Google Domains, etc.There is a short tutorial on how to integrate Let's Encryps here"
    }
  },
  "/docs/server/google-maps": {
    "title": "Google Maps",
    "data": {
      "google-maps-integration#Google Maps integration": "Go to Google Cloud Platform on https://console.cloud.google.com/\nClick on console.\nSelect your Firebase Project\nSearch for Google Maps API\nEnable Google Maps API and get the API key\nAdd the key to the .env file in the root of the project\nGOOGLE_MAPS_API_KEY=YOUR_API_KEY",
      "secure-your-api-key#Secure your API key": "If you are just playing around in development mode, you can skip this, but if you are deploying the server to production, you should restrict the API key.Normally, the API key that is provided inside the Google Clous Platform is not restricted by any means. You can restrict the API key to only be used by your IP or the IP of the machine in which your server is running to.Furtheremore, only a small list of services are used in the app, so you can restrict the API key to only allow those services:\nGeocoding API\nGeolocation API\nMaps JavaScript API\nMaps Static API\nPlaces API"
    }
  },
  "/docs/server/running-in-dev": {
    "title": "Running in Dev",
    "data": {
      "running-in-development-with-docker#Running in Development with Docker": "",
      "start-the-server#Start the server": "Make sure you install the necessary NPM packages by running the following command in the root directory of the project:\nnpm install\nIn order to run the application in development mode, you need to open a terminal inside the root directory of the project and run the following command:\ndocker-compose up\nThis command will start the server and the database in Docker containers. The server will be running on port 7777.If the server is ran the first time, the available migrations will be automatically executed and populate the database with the necessary data.On a successful start, you should see the following message in the terminal:\nServer listen on : 7777",
      "access-the-server#Access the server": "You can access the server by opening the following URL in your browser:\nhttp://localhost:7777\nYou should see the following message in your browser:",
      "follow-video-tutorial-for-running-the-server-in-development-mode#Follow video tutorial for running the server in development mode": "",
      "connect-postgresql-gui-client#Connect PostgreSQL GUI client": "(In this demo, we are using DataGrip as the PostgreSQL GUI client)\nOpen DataGrip and click on the + icon to add a new data source.\nSelect PostgreSQL from the list of data sources.\nFill in the necessary information (Data taken from the .env file):\nHost: localhost\nPort: 6543\nDatabase: biddo-dev\nUser: biddo\nPassword: biddo\nYou should be able to have available the following tables in the database:",
      "stop-the-server#Stop the server": "In order to stop the server, you need to hit Ctrl + C in the terminal where the server is running. This will stop the server and the database containers.If you want to remove the containers, you can run the following command:\ndocker-compose down\nIf you want to remove the containers and the volumes (together with all the data), you can run the following command:\ndocker-compose down -v",
      "running-in-development-without-docker#Running in development without Docker": "If you do not want to use Docker, you can run the server without it, but you must make sure that you have a PostgreSQL database available to connect to.If you have a database set up on a remote server, you can connect to it by changing the required environment variables in the .env file.If you would like to manually create a PostgreSQL database on your machine, you can follow the steps in the following PostgreSQL installation guide.The env variables that need to be changed are:\nPOSTGRES_SERVER=YOUR_SERVER\nPOSTGRES_PORT_EXTERNAL=6543\nPOSTGRES_USER=YOUR_USER\nPOSTGRES_PASSWORD=YOUR_PASSWORD\nPOSTGRES_DB=YOUR_DB\nAfter you have set up the database, you can run the following commands in the root directory of the project:\nnpm install\nnpm run dev\nThis will start the server in development mode without Docker. The server will be running on port 7777."
    }
  },
  "/docs/server/setup-prerequisites": {
    "title": "Setup Prerequisites",
    "data": {
      "setup-prerequisites#Setup Prerequisites": "",
      "install-nodejs#Install NodeJS": "Download and install the latest stable version of NodeJS from the official website",
      "install-yarn#Install Yarn": "Download and install the latest version of Yarn from the official websiteNode: You can also use npm to install the dependencies. If you prefere npm instead of yarn, you can skip this ste.",
      "install-docker#Install Docker": "Note: If you do not want to run the server locally using Docker, you can skip this step. There are more information about how to run the app without Docker in the \"Running in Development\" section.Download and install the latest version of Docker from the official website",
      "install-postgresql#Install PostgreSQL": "Download and install the latest version of PostgreSQL from the official website",
      "optional-install-a-postgresql-gui-client#(Optional) Install a PostgreSQL GUI client": "You have multiple options:\nDownload and install the latest version of DataGrip from the official website\nDownload and install the latest version of pgAdmin from the official website (Free)\nDownload and install the latest version of DBeaver from the official website (Community Version)\nDownload and install the latest version of TablePlus from the official website",
      "install-the-necessary-dependencies#Install the necessary dependencies": "In order to install the necessary dependencies, you need to open a terminal inside the root directory of the project and run the following command:\nyarn install"
    }
  },
  "/docs/server/environment": {
    "title": "Environment",
    "data": {
      "environment-variables#Environment variables": "Create a new file called .env in the root of the project. This file will contain all the environment variables that are used in the project.You can copy the content from the .env.example file and paste it into the .env file.\nAPP_ENV=development\nNODE_ENV=development\nPORT=7777\nNODE_DEBUGGER_PORT=9229\nAPP_VERSION=1.0\n# Postgres\nPOSTGRES_SERVER=biddo_postgres\nPOSTGRES_PORT_EXTERNAL=6543\nPOSTGRES_USER=biddo\nPOSTGRES_PASSWORD=biddo\nPOSTGRES_DB=biddo-dev\nPOSTGRES_CONNECTION_MAX_POOL=90\nSEQUELIZE_DEBUG=0\nPOSTGRES_HOST=biddo_postgres\nIn the .env.example file, there might be more variables than described above. We will cover them all throughout the documentation.\n  Make sure that POSTGRES_SERVER is correct.\nWhen you are running the project in development mode, you will use the database that is running in the Docker container. The POSTGRES_SERVER and POSTGRES_HOST should be the same as the service name in the docker-compose.yml file.When you are going to run the project in production mode, you will need to change the POSTGRES_SERVER and POSTGRES_HOST to the IP address of the server where the database is running (We'll cover this in a later section).IMPORTANTCreate a ecosystem.config.cjs file in the root of the project and copy the content from ecosystem.config.example.cjs inside of it. This file will contains credentials for your production server. You don't need to add the credentials now, but you will need to add them when you deploy the project to a production server."
    }
  },
  "/docs/server/tutorials/new-module": {
    "title": "New Module",
    "data": {
      "add-a-new-module#Add a new module": "We will be adding a comments module to the project. This module will allow users to add comments to an auction.",
      "add-the-database-table#Add the database table": "If you are already running the server, make sure you stop it before proceeding with the next steps, as the server will detect any change inside the code and it will try to apply the changes to the database. A migration is always ran only once.\nIf you are ever in a situation in which a database migration already ran, but you need it to run it again, you can remove the migration straight from the database. The migrations that ran are stored in the sequelize_migrations table. You can remove the migration from the table and run the server again. The server will detect that the migration is missing and it will run it again.\nBefore adding the new module, we need to make sure that a database table is created for the module. To create a new table, we need to create a new migration file in the migrations directory. In order to autimatically generate a migration file, we need to open a terminal in the project directory and run the following command:\nnpm run migration:create add-comments\nThis command will create a new migration file in the migrations directory. The migration file will contain only the skeleton of the migration. we need to add the actual migration code to the file.You will notice that the file has two functions: up and down. Each of the functions has a try/catch statement, place in which we need to add the actual migration code. Inside the up function we will add the code that will create the comments table, and inside the down function we will add the code that will drop the comments table.\nexport async function up({\n  context: queryInterface,\n}: {\n  context: sequelize.QueryInterface\n}) {\n  const transaction = await queryInterface.sequelize.transaction()\n  try {\n    await queryInterface.createTable(\n      DATABASE_MODELS.COMMENTS,\n      {\n        id: {\n          type: DataTypes.UUID,\n          defaultValue: sequelize.literal('gen_random_uuid()'),\n          primaryKey: true,\n        },\n        accountId: {\n          allowNull: false,\n          type: DataTypes.UUID,\n          references: {\n            model: DATABASE_MODELS.ACCOUNTS,\n            key: 'id',\n          },\n        },\n        auctionId: {\n          type: DataTypes.UUID,\n          references: {\n            model: DATABASE_MODELS.AUCTIONS,\n            key: 'id',\n          },\n        },\n        comment: {\n          type: DataTypes.TEXT,\n          allowNull: false,\n        },\n        createdAt: {\n          allowNull: false,\n          type: DataTypes.DATE,\n        },\n        updatedAt: {\n          allowNull: false,\n          type: DataTypes.DATE,\n        },\n      },\n      { transaction }\n    )\n    await transaction.commit()\n  } catch (error) {\n    console.error(error)\n    await transaction.rollback()\n    throw error\n  }\n}\nexport async function down({\n  context: queryInterface,\n}: {\n  context: sequelize.QueryInterface\n}) {\n  const transaction = await queryInterface.sequelize.transaction()\n  try {\n    await queryInterface.dropTable(DATABASE_MODELS.COMMENTS, { transaction })\n    await transaction.commit()\n  } catch (error) {\n    await transaction.rollback()\n    throw error\n  }\n}\nYou can see below an image with the migration file opened in VSCode:\nYou will notice the DATABASE_MODELS object in the migration file. This object contains the names of the tables in the database. You can find the definition of this object in the src/constants/model-names.ts file. Make sure to add the name of the new table to the DATABASE_MODELS object, like this:\nThe new table will be automatically added to the database when you run the server with the docker-compose up command.",
      "add-the-module-to-the-project#Add the module to the project": "To add a new module to the project, we need to create a new directory in the modules directory. The directory name should be the name of the module you want to create. For example, if we are creating a comments module, we need to create a comments directory in the modules directory.Inside the new directory, we will create 3 files:\ncontroller.ts: This file will contain the controller logic for the module\nmodel.ts: This file will contain the model definition for the module\nrepository.ts: This file will contain the repository logic for the module\nHere is the content we need to add in each of the files:controller.ts\nimport { Request, Response } from 'express'\nimport { GENERAL } from '../../constants/errors.js'\nimport { CommentsRepository } from './repository.js'\nexport class CommentsController {\n  public static async getForAuction(req: Request, res: Response) {\n    const { auctionId } = req.params\n    try {\n      const comments = await CommentsRepository.getForAuction(auctionId)\n      res.status(200).send(comments)\n    } catch (error) {\n      console.error(error)\n      res.status(500).send({ error: GENERAL.SOMETHING_WENT_WRONG })\n    }\n  }\n  public static async create(req: Request, res: Response) {\n    const { account } = res.locals\n    const { auctionId, comment } = req.body\n    try {\n      if (!auctionId || !comment) {\n        return res.status(400).send({ error: GENERAL.BAD_REQUEST })\n      }\n      const newComment = await CommentsRepository.create({\n        accountId: account.id,\n        auctionId,\n        comment,\n      })\n      res.status(201).send(newComment)\n    } catch (error) {\n      console.error(error)\n      res.status(500).send({ error: GENERAL.SOMETHING_WENT_WRONG })\n    }\n  }\n  public static async update(req: Request, res: Response) {\n    const { account } = res.locals\n    const { id } = req.params\n    const { comment } = req.body\n    try {\n      if (!comment) {\n        return res.status(400).send({ error: GENERAL.BAD_REQUEST })\n      }\n      const existingComment = await CommentsRepository.getOneById(id)\n      if (!existingComment) {\n        return res.status(404).send({ error: GENERAL.NOT_FOUND })\n      }\n      if (existingComment.accountId !== account.id) {\n        return res.status(403).send({ error: GENERAL.FORBIDDEN })\n      }\n      const updatedComment = await CommentsRepository.update(\n        { where: { id } },\n        { comment }\n      )\n      res.status(200).send(updatedComment)\n    } catch (error) {\n      console.error(error)\n      res.status(500).send({\n        error: GENERAL.SOMETHING_WENT_WRONG,\n      })\n    }\n  }\n  public static async delete(req: Request, res: Response) {\n    const { account } = res.locals\n    const { id } = req.params\n    try {\n      const existingComment = await CommentsRepository.getOneById(id)\n      if (!existingComment) {\n        return res.status(404).send({ error: GENERAL.NOT_FOUND })\n      }\n      if (existingComment.accountId !== account.id) {\n        return res.status(403).send({ error: GENERAL.FORBIDDEN })\n      }\n      await CommentsRepository.deleteById(id)\n      res.status(204).send()\n    } catch (error) {\n      console.error(error)\n      res.status(500).send({\n        error: GENERAL.SOMETHING_WENT_WRONG,\n      })\n    }\n  }\n}\nmodel.ts\nimport { DataTypes, Model } from 'sequelize'\nimport { getModelConfig } from '../../utils/db.js'\nimport { DATABASE_MODELS } from '../../constants/model-names.js'\nimport sequelize from 'sequelize'\nimport { Auction } from '../auctions/model.js'\nimport { Account } from '../accounts/model.js'\nexport class Comment extends Model {\n  declare id: string\n  declare auctionId: string\n  declare accountId: string\n  declare comment: string\n  declare readonly createdAt: Date\n  declare readonly updatedAt: Date\n  static initModel = initModel\n  static initAssociations = initAssociations\n}\nfunction initModel(): void {\n  const modelConfig = getModelConfig(DATABASE_MODELS.COMMENTS)\n  Comment.init(\n    {\n      id: {\n        type: DataTypes.UUID,\n        defaultValue: sequelize.literal('gen_random_uuid()'),\n        primaryKey: true,\n      },\n      accountId: {\n        allowNull: false,\n        type: DataTypes.UUID,\n        references: {\n          model: DATABASE_MODELS.ACCOUNTS,\n          key: 'id',\n        },\n      },\n      auctionId: {\n        type: DataTypes.UUID,\n        references: {\n          model: DATABASE_MODELS.AUCTIONS,\n          key: 'id',\n        },\n      },\n      comment: {\n        type: DataTypes.TEXT,\n        allowNull: false,\n      },\n      createdAt: {\n        allowNull: false,\n        type: DataTypes.DATE,\n      },\n      updatedAt: {\n        allowNull: false,\n        type: DataTypes.DATE,\n      },\n    },\n    modelConfig\n  )\n}\nfunction initAssociations() {\n  Comment.belongsTo(Auction, {\n    foreignKey: 'auctionId',\n    onDelete: 'cascade',\n  })\n  Comment.belongsTo(Account, {\n    foreignKey: 'accountId',\n    onDelete: 'cascade',\n  })\n}\nrepository.ts\nimport { GenericRepository } from '../../lib/base-repository'\nimport { Account } from '../accounts/model'\nimport { Comment } from './model'\nclass CommentsRepository extends GenericRepository<Comment> {\n  constructor() {\n    super(Comment)\n  }\n  public async getForAuction(auctionId: string) {\n    return Comment.findAll({\n      where: { auctionId },\n      include: [\n        {\n          model: Account,\n          attributes: ['id', 'name', 'email', 'picture'],\n        },\n      ],\n    })\n  }\n}\nconst commentsRepositoryInstance = new CommentsRepository()\nObject.freeze(commentsRepositoryInstance)\nexport { commentsRepositoryInstance as CommentsRepository }\nNotice that the CommentsRepository extends the GenericRepository, which already comes with the basic CRUD operations. The GenericRepository is a class that contains the basic CRUD operations for a model. You can find the definition of the GenericRepository in the src/lib/base-repository.ts file.After we have created the files, there are a few more this we need to do before the new module is exposed from the server.\nThe model needs to be added inside the sequelize instance. To do this, we need to import the model in the src/database/index.ts file and add it to the models object.\nWe need to create a new route and expose the controller methods. Create a new file called comments.ts inside the src/api/routes directory. The file should contain the following code:\nimport { Router } from 'express'\nimport { Authenticator } from '../middlewares/auth.js'\nimport { HttpRateLimiter } from '../middlewares/rate-limiter.js'\nimport { CommentsController } from '../../modules/comments/controller.js'\nconst commentsRouter = Router()\ncommentsRouter.use(await Authenticator.authenticateHttp())\ncommentsRouter.use(HttpRateLimiter.limitRequestsForUser)\ncommentsRouter.get('/:auctionId', CommentsController.getForAuction)\ncommentsRouter.post('/', CommentsController.create)\ncommentsRouter.put('/:id', CommentsController.update)\ncommentsRouter.delete('/:id', CommentsController.delete)\nexport { commentsRouter }\nWe need to import this new route inside the src/index file and add the following line of code, near the other route imports:\napp.use('/comments', commentsRouter)\nThis is it. The new module is now exposed from the server. You can test the new module by using Postman or any other API testing tool, after you start the server with the docker-compose up command."
    }
  },
  "/docs/web/architecture": {
    "title": "Architecture",
    "data": {
      "code-architecture#Code Architecture": "The web application is a NextJS application, using app directory. If you want to learn more about NextJS, you can visit the official documentation. Specific documentation about app router can be found here.Similar with the NodeJS server, the web application is written in Typescript. You can see below the structure of the web application:For state management, MobX is used. You can find more about MobX here.\nAs you can notice from the image above, the web application is structured in the following way:\npublic - contains the public assets of the application. (images, icons etc.)\napp - contains the main pages of the application. We will go into more details about the pages...\ncomponents - contains the reusable components of the application.\ncore - you will find here the models, repositories and the controllers of the application. These are the \"smart\" entities of the application that fetch data from the server or push changes to the server.\nhooks - generic reusable hooks that can be used in the application.\nmiddlewares - contains the middlewares that are used in the application.\nutils - contains the utility functions that are used in the application.\nLet's deep further into the structure of the application.\nInside the app directory, you will find a root folder called [lang]. This is the internationalization folder of the application. Inside this folder, you will find a different folder for each page available inside the application.One thing to note here is that if there is a component that needs to be used only inside a specific page, it will be placed inside the page folder. If the component is used in multiple pages, it will be placed inside the components folder from the root of the app. Basically, if you navigate to a page folder, you could find another components folder, that are used only in that specific page.\nWhenever we have nested pages (like the \"auctions/recommendations\" page), we will have a folder for each nested page. Inside the nested page folder, you will find the components that are used only in that specific page, like in the above example.\nInside the same app directory, you will find a few more folders:\ncss - contains simple CSS styles of the application.\ni18n - contains the translations of the application.\nscss - contains SCSS styles of the application. There would be a different file for each page of the application. (Some JSX styles might be found through the application components, but the main styles are found here)\nThe components folder contains the reusable components of the application. These components are used in multiple pages of the application and they are separated in different folders based on their functionality or location they are used in the application.\nAs mentioned above, the core folder contains the models, repositories and the controllers of the application. The role of these entities are the following:\ndomain - The models of the application. These are the entities that are used in the application. For example, a user, an auction, a category etc. These entities are used in the application to represent the data that is fetched from the server and they do not contain any logic.\nrepositories - The repositories are responsible for fetching the data from the server. They contain the logic of fetching the data from the server and sending it back to the application. They do not contain any logic related to the business rules of the application. The repositories are not used directly in the React components of the application.\ncontrollers - The controllers are responsible for handling the business logic of the application. They contain the logic of the application and they are responsible for handling the data that is fetched from the server and sending it back to the application. The controllers are using the repositories to fetch the data from the server. They can be used inside the React components of the application.\nstore - MobX store, used for state management. This is reactive state management library that makes it simple to connect the reactive data of your application with the UI. Inside the React component, data from the store can be used directly, without the need to pass it through props. Whenever the data from the store is updated, the react component that uses that data will be re-rendered."
    }
  },
  "/docs/web/environment": {
    "title": "Environment",
    "data": {
      "environment-variables#Environment variables": "Create a new file called .env.development in the root of the project. This file will contain all the environment variables that are used in the project.You can copy the content from the .env.example file and paste it into the .env.development file.\nNEXT_PUBLIC_SERVER_URL=http://localhost:7777\nNEXT_PUBLIC_SERVER_WS_URL=ws://localhost:7777\nNEXT_PUBLIC_FACEBOOK_APP_ID=\nGOOGLE_MAPS_API_KEY=\nNEXT_PUBLIC_STRIPE_PUBLIC_KEY=\nNEXT_PUBLIC_SERVER_URL - The URL of the server where the NodeJS server is running. This is used in the mobile app to connect to the server.NEXT_PUBLIC_SERVER_WS_URL - The URL of the WebSocket server where the NodeJS server is running. This is used in the mobile app to connect to the server. Usually, this is the same as the SERVER_URL, but instead of the \"http(s)\" protocol, it uses the \"ws(s)\" protocol.NEXT_PUBLIC_FACEBOOK_APP_ID - The Facebook App ID. This is only used whenever a user wants to share an auction/profile to Facebook. You can find the App ID in the Facebook Developer Console.GOOGLE_MAPS_API_KEY - The API key for Google Maps. (You will find out what value to add here in a later section)NEXT_PUBLIC_STRIPE_PUBLIC_KEY - The public key for Stripe. (You will find out what value to add here in a later section)"
    }
  },
  "/docs/web/deploy": {
    "title": "Deploy",
    "data": {
      "deployment-of-the-nextjs-app#Deployment of the NextJS app": "You need to have the vercel CLI installed. You can learn more about this here.Make sure you have the server deployed as well, because once you deploy the NextJS app to vercel, you will need to provide a public accesible URL for the serverAfter you have a public accessible URL for the server, make sure to create a .env.production file in the root directory of the project and add copy the contents of the .env.development file to the .env.production file.You will need to change the NEXT_PUBLIC_SERVER_URL and the NEXT_PUBLIC_SERVER_WS_URL.After installing the vercel CLI, you can deploy the app by running the following command inside the root directory of the project:\nvercel\nor, (if you want to deploy the app to production)\nvercel --prod\nThis will automatically deploy the app to the vercel platform and give you a URL where you can access the app.P.S: Do not forget to check if the deployed website has access to google maps API. It is recommended to use a google maps api key that is restricted to run only on your custom domain, so that nobody can steal it from your website and use it for their own purposes."
    }
  },
  "/docs/web/firebase-integration": {
    "title": "Firebase Integration",
    "data": {
      "firebase-integration#Firebase Integration": "Make sure that inside the Firebase Console project settings, you have enabled the Web SDK.\nAfter the Web SDK is enabled, you should see something like this:\nNotice the firebaseConfig object.\nIn the root of the project, inside the src folder, there already exists a file called firebase.example.ts.\nYou need to create a new file called firebase.ts (in the same src folder) and copy the content from firebase.example.ts to firebase.ts.\nInside the firebase.ts file, you need to replace the firebaseConfig object with the one from the Firebase Console.\nYour file should look something like this:"
    }
  },
  "/docs/web/running-in-dev": {
    "title": "Running in Dev",
    "data": {
      "running-the-nextjs-app-in-development#Running the NextJS app in development": "In order to run the NextJS app in development mode, you need to have Node.js installed on your computer.You just have to open a terminal inside the root directory of the project and run the following command:\nnpm i\nnpm run dev\nor\nyarn dev",
      "follow-video-tutorial-for-running-the-app-in-development-mode#Follow video tutorial for running the app in development mode": ""
    }
  },
  "/docs/web/publish": {
    "title": "Publish",
    "data": {
      "publish-the-web-app#Publish the Web app": "The Web app is a NextJS application that can be published on any hosting service that supports NodeJS applications.Vercel is a great option for hosting the Web app, as it is the company that created NextJS and it has a great integration with the framework.You can publish your Web app on Vercel by following these steps:\nInstall the Vercel CLI, following the steps from the official documentation.\nOpen a terminal inside the root of the Web app and run the following command:\nvercel\nThis will automatically publish your application on vercel.",
      "changes-to-the-nodejs-server#Changes to the NodeJS server": "After you publish the Web app, a domain will be automatically assigned. You need to allow the NodeJS server to accept requests from this domain.Inside the NodeJS server, open the src/config.ts file. Inside this config file, you will find a ALLOW_ORIGIN property. You need to add the domain that was assigned by Vercel to this property.If you have a custom domain for your Web app, you need to add that domain to the ALLOW_ORIGIN property.\nDo not forget to update the WEB_APP_URL inside the .env file in the NodeJS server with the new domain.",
      "firebase-changes#Firebase changes": "Take into account that Firebase will not work with the new domain that was assigned by Vercel. You need to add the new domain to the Firebase console, in the Authentication section."
    }
  },
  "/docs/web/setup-prerequisites": {
    "title": "Setup Prerequisites",
    "data": {
      "setup-prerequisites#Setup Prerequisites": "You should already have all the prerequisites installed from the previous sections. If you don't, you just need to install NodeJS.",
      "install-nodejs#Install NodeJS": "Download and install the latest stable version of NodeJS from the official websiteMake sure you are able to run the NodeJS server before continuing with the next steps for the web app."
    }
  },
  "/": {
    "title": "Welcome to Biddo",
    "data": {
      "": "Introducing our state-of-the-art Mobile Auction App, meticulously crafted with Flutter and powered by a robust NodeJS server. This dynamic application offers a seamless, user-friendly platform for creating and participating in auctions, providing an engaging and secure environment for all your auction needs.\nMobile app\nWeb app"
    }
  },
  "/docs/mobile-app/name-version-splash": {
    "title": "Name Version Splash",
    "data": {
      "update-the-name-version-and-splash-screen#Update the name, version, and splash screen": "",
      "update-the-name#Update the name": "Open a terminal inside the root directory of the mobile app.\nRun the following command to update the name of the mobile app:\nflutter pub get\nChange the android package name of the application by executing the following command:\nflutter pub run change_app_package_name:main com.new_name\nYou also need to go to the android/app/src/main/AndroidManifest.xml file and change the package name to the new name of the application.\n<application\n        android:label=\"Biddo\"\nYou also need to go to the android/app/proguard-rules.pro file and change the package name to the new name of the application.\nIn order to update the iOS package name of the application, you need to open the project in Xcode. (You can download Xcode from the official website)\nOpen iox folder of the project in Xcode.\nYou can double-click on the Runner.xcworkspace file to open the project in Xcode.\nGo to Runner -> Build Settings -> Packaging -> Product Bundle Identifier and change the name of the application.\nGo to Runner -> General -> Identity -> Display Name and change the name of the application.\nMake sure you check the ios -> Runner -> Info.plist file and change the CFBundleDisplayName.",
      "update-the-version#Update the version": "Open the pubspec.yaml file inside the root directory of the mobile app.\nUpdate the version of the mobile app by changing the version number in the following line:\nversion: 0.0.1+1\nRun the following command to update the version of the mobile app:\nflutter pub get\nor\nflutter run",
      "update-the-splash-screen#Update the splash screen": "Open the pubspec.yaml file inside the root directory of the mobile app.\nYou can notice that there is a flutter_native_splash section in the file. This section is used to configure the splash screen of the mobile app.\nYou will need two images for the splash screen. One that is special for android12 and one for the rest.\nAfter you replace those two images, you need to run the following command to update the splash screen of the mobile app:\ndart run flutter_native_splash:create",
      "update-the-launcher-icon#Update the launcher icon": "Open the pubspec.yaml file inside the root directory of the mobile app.\nYou can notice that there is a flutter_launcher_icons section in the file. This section is used to configure the launcher icon of the mobile app.\nYou will need an image for the launcher icon.\nAfter you replace the image, you need to run the following command to update the launcher icon of the mobile app:\nflutter pub run flutter_launcher_icons"
    }
  },
  "/docs/web/push-notifications": {
    "title": "Push Notifications",
    "data": {
      "web-push-notifications#Web Push Notifications": "The push notifications that are send on the web, need 2 vapid keys, that are going to be used by the web-push library to send the notifications.In order to generate these keys, you need to open a terminal on your computer and run the following commands:Install web-push globally\nnpm install web-push -g\nGenerate the keys\nweb-push generate-vapid-keys --json\nThis will output a JSON object with the public and private keys. You need to copy these keys and use them in the NodeJS server.\nThe result will look like this:\n{\n  \"publicKey\":\"\",\n  \"privateKey\":\"I0_d0vnesxbBSUmlDdOKibGo6vEXRO-Vu88QlSlm5j0\"\n}",
      "use-the-keys-inside-the-nodejs-server#Use the keys inside the NodeJS server": "Open the .env file in the root of the NodeJS server and add the following keys:\nVAPID_PUBLIC_KEY=\nVAPID_PRIVATE_KEY=I0_d0vnesxbBSUmlDdOKibGo6vEXRO-Vu88QlSlm5j0\nSUPPORT_EMAIL=test@test.com  - the VAPID server contact information\nIf you do not have the .env file, please follow the documentation from the NodeJS Server.In order for the push notifications that are sent to the users to point to the correct page, the NodeJS server needs to know the URL of the Web Application, in order to build the exact URL of the page where the user should be redirected when clicking on the notification.You need to add one more information inside the .env file, in the NodeJS server:\nWEB_APP_URL=http://localhost:3000\nThe URL should be the one where the Web Application is hosted. If you are running the Web Application on your local machine, the URL should be http://localhost:3000.\nIf you are running the Web Application on a remote machine, the URL should be the server's IP address or domain name.",
      "use-the-keys-inside-the-web-application#Use the keys inside the web application": "If inside the server .env file, you added both the private key and the publick key,inside the Web Application you only need to add the public key.\nOpen the .env file in the root of the Web Application and add the following key:\nVAPID_PUBLIC_KEY=\nMake sure that the public key is the same in both the server and the web application and that they are the ones you have generated."
    }
  },
  "/terms/cookies": {
    "title": "Cookies",
    "data": {
      "cookies-policy#Cookies Policy": "What Are Cookies?\nCookies are small text files that are stored on your device (computer, tablet, or mobile) when you visit a website or use an application. They help us to recognize your device and remember your preferences.\nHow We Use Cookies\nEssential Cookies: These cookies are necessary for the App to function correctly and enable you to use its features.\nPerformance Cookies: These cookies collect information about how you use the App, allowing us to improve its performance and user experience.\nFunctionality Cookies: These cookies allow the App to remember your preferences and provide enhanced, personalized features.\nAnalytics Cookies: We use analytics cookies to understand how users engage with the App and to gather statistical data.\nYour Choices Regarding Cookies\nManaging Cookies: You can manage your cookie preferences through your device settings. However, please note that disabling cookies may affect the functionality of the App.\nThird-Party Cookies: Some cookies may be set by third-party services that appear on our App. We do not control these cookies, and you should check the third-party websites for more information about their cookies.\nChanges to Cookies Policy\nWe may update this Cookies Policy from time to time. We will notify you of any changes by posting the new Cookies Policy on this page."
    }
  },
  "/terms": {
    "title": "Terms of service",
    "data": {
      "": "Welcome to Biddo. Please read these Terms of Service (\"Terms\") carefully before using our mobile application (\"App\").By accessing or using the App, you agree to be bound by these Terms. If you disagree with any part of the Terms, you may not access the App.\nUse of the App\nAccount Registration: You may be required to register an account to access certain features. You agree to provide accurate and complete information and keep your account information updated.\nAccount Security: You are responsible for maintaining the confidentiality of your account login information and are fully responsible for all activities that occur under your account.\nProhibited Activities: You agree not to engage in any illegal activities, violate any laws, or use the App for any unauthorized or unlawful purposes.\nAuctions and Bidding\nCreating Auctions: Users can create auctions for various items, including but not limited to art, LEGO sets, cars, and houses.\nBidding: Users can place bids on items in an auction. The auction owner has the discretion to accept or reject any bid.\nTransactions: All transactions are conducted at the users' own risk. We do not guarantee the authenticity, quality, or legality of the items listed.\nUser Conduct\nContent: Users are responsible for the content they post. You agree not to post any content that is offensive, defamatory, or violates any third- party rights.\nInteractions: Users can report other users, auctions, or bids that they believe violate these Terms. We reserve the right to take appropriate action, including suspending or terminating accounts.\nIntellectual Property\nOwnership: All content, trademarks, logos, and intellectual property rights related to the App are owned by the Company or its licensors.\nLicense: We grant you a limited, non-exclusive, non-transferable license to use the App for personal, non-commercial purposes.\nTermination\nWe reserve the right to terminate or suspend your account and access to the App at our sole discretion, without notice and liability, for any reason, including if you breach these Terms.\nDisclaimers\nNo Warranty: The App is provided \"as is\" and \"as available\" without any warranties of any kind, express or implied.\nLimitation of Liability: In no event shall the Company be liable for any indirect, incidental, special, consequential, or punitive damages, or any loss of profits or revenues.\nGoverning Law\nThese Terms shall be governed and construed in accordance with the laws of any state, without regard to its conflict of law provisions.\nChanges to Terms\nWe reserve the right to modify or replace these Terms at any time. Your continued use of the App after any changes constitutes acceptance of the new Terms.\nThis App is private property and it cannot be re-distributed or used for commercial purposes without our consent or permission. You can use this application for commercial purposes if you buy it.By using our App, you agree to the collection and use of your information in accordance with this Privacy and Cookies Policy. Please ensure that you read and understand these policies fully. If you do not agree with any part of these policies, you should not use the App."
    }
  },
  "/docs/web/stripe": {
    "title": "Stripe",
    "data": {
      "stripe-integration#Stripe Integration": "",
      "step-1-create-a-stripe-account#Step 1: Create a Stripe Account": "If you don't already have a Stripe account, you can create one here.After you have created the account, you will be redirected to the dashboard.You are going to be asked to complete your business profile, in order to be able to receive payments, but you can skip this step if you only want to test how the implementation works.",
      "step-2-create-products#Step 2: Create products": "In order to create products, you need to go to the Product catalog section in the Stripe dashboard.You will be able to see a \"Create product\" button, that will allow you to create a new product.We will create 3 products, that will represent the amount of coins that the user can buy in the application:\n50 coins\n200 coins\n500 coins\nMake sure that the products have the \"One-off\" payment type. You can set any price you want for the products.In a visual way, this is how the process should look like:\nStripe dashboard with no products inside the product catalog\nClick on the \"Create product\" button and add a product details\nAfter you have created the products, you should see them in the product catalog",
      "step-3-integrate-inside-the-nodejs-server#Step 3: Integrate inside the NodeJS server": "After we have the products created, we need to get the Stripe secrey key and the product keys and add them inside the .env file in the NodeJS server.You can find the secret key in the Stripe dashboard, in the Developers section. (Developers -> API keys from the header)\nThe product keys can be found in the product details, in the Stripe dashboard.Let's see how it should look like:\nFind the secret key\nYou will be redirected to the API keys section, where you can find the secret key.\nFind the product keys\nMake sure that you have the product ids from all the products that you have created.After you have the keys, you need to add them inside the .env file in the NodeJS server.\nSTRIPE_SECRET_KEY=sk_test_51JG\nSTRIPE_PRODUCT_50_COINS=price_1JG\nSTRIPE_PRODUCT_200_COINS=price_1JG\nSTRIPE_PRODUCT_500_COINS=price_1JG",
      "step-4-integrate-inside-the-web-application#Step 4: Integrate inside the Web Application": "Inside the Web Application, you need to add the Stripe public key inside the .env file.You can find the public key in the Stripe dashboard, in the Developers section. (Developers -> API keys from the header).It should be above the secret key (Publishable key).Add this inside the .env file in the root of the Web Application:\nNEXT_PUBLIC_STRIPE_PUBLIC_KEY=pk_test_51JG",
      "step-5-add-stripe-webhook#Step 5: Add Stripe Webhook": "In order to receive the payment status, you need to add a webhook inside the Stripe dashboard. This webhook will send a POST request to the server every time a payment is made.You can add a webhook by going to the Developers section in the Stripe dashboard and clicking on the \"Webhooks\" section.You will be able to see a \"Add endpoint\" button, that will allow you to add a new webhook.You need to add the URL of the server, followed by /payment/stripe-webhook.For example, if the server is running on http://localhost:7777, the webhook URL should be http://localhost:7777/payment/stripe-webhook.The problem when using localhost is that Stripe will not be able to send the POST request to the server, because it is running on your local machine.One option is to use a service like ngrok to create a tunnel to your local machine.The official option of testing the webhook is using the Stripe CLI. You can find more information about this here.For demo purposes, I will be using ngrok to create a tunnel to my local machine. This will provide me with a public URL that I can use to test the webhook.\nCreate a new webhook\nChoose what events to be send through the webhook. The NodeJS server only handles the \"checkout.session.completed\" event, so you can select only this event.\nAfter the webhook is created, you need to add the \"Signing secret\" of this webhook inside the .env file in the NodeJS server.\nThis is what you need to add inside the .env file in the NodeJS server:\nSTRIPE_WEBHOOK_SIGNING_SECRET=your_signing_secret\nDo not forget that if you remove a webhook and create a new one, you need to update the signing secret inside the .env file.",
      "step-6-test-the-integration#Step 6: Test the integration": "Make sure that every time you change the .env file, you restart the server.The integration should work by default now. You can test it by going to the application and trying to buy coins.If you're testing the integration, you can use the test card number 4242 4242 4242 4242 with any expiration date and CVC.If you want to receive payments inside a production environment, you need to complete the business profile in the Stripe dashboard.When going in production, do not forget to create another webhook for the production server and update the .env accordingly."
    }
  },
  "/terms/privacy": {
    "title": "Privacy",
    "data": {
      "privacy-policy#Privacy Policy": "Information We Collect\nPersonal Information: We may collect personally identifiable information such as your name, email address, and phone number when you register for an account or use certain features of the App.\nUsage Data: We automatically collect information about how you interact with the App, including your IP address, device information, and usage patterns.\nLocation Data: With your consent, we may collect and use your precise location data to provide location-based services.\nHow We Use Your Information\nTo Provide Services: We use your information to operate, maintain, and improve the App.\nCommunication: We may use your information to communicate with you, including sending updates, security alerts, and support messages.\nPersonalization: We use your information to personalize your experience and deliver content and features that match your interests.\nHow We Share Your Information\nService Providers: We may share your information with third-party service providers who perform services on our behalf.\nLegal Requirements: We may disclose your information if required by law or in response to valid requests by public authorities.\nBusiness Transfers: If we are involved in a merger, acquisition, or asset sale, your information may be transferred as part of that transaction.\nSecurity\nWe implement reasonable security measures to protect your information from unauthorized access, use, or disclosure. However, no method of transmission over the Internet or electronic storage is completely secure.\nYour Rights\nAccess and Correction: You have the right to access and correct your personal information.\nDeletion: You may request that we delete your personal information, subject to certain legal obligations.\nOpt-Out: You can opt-out of receiving promotional communications from us by following the unsubscribe instructions in those communications.\nChildren's Privacy\nOur App is not intended for children under the age of 13. We do not knowingly collect personally identifiable information from children under 13.\nChanges to Privacy Policy\nWe may update this Privacy Policy from time to time. We will notify you of any changes by posting the new Privacy Policy on this page."
    }
  },
  "/docs/server/firebase-integration": {
    "title": "Firebase Integration",
    "data": {
      "firebase-integration#Firebase integration": "In order to allow the server to communicate with the mobile app, you need to integrate Firebase into the mobile app.",
      "generate-firebase-service-account-key#Generate Firebase service account key": "Go to the Firebase Console.\nClick on the gear icon and select Project settings.\nGo to the Service accounts tab and click on Generate new private key.\nA file will be downloaded. Copy the content of that file and save it in the src/service-account/firebase.ts file.\nMake sure to add the following content to the src/service-account/firebase.ts file:\nexport const FIREBASE_CREDENTIALS = {\n  ...\n}"
    }
  }
}
