{"id":42562909,"url":"https://github.com/dladden/bourbon-tour-agency-react","last_synced_at":"2026-01-28T20:36:20.290Z","repository":{"id":249558271,"uuid":"553859887","full_name":"dladden/bourbon-tour-agency-react","owner":"dladden","description":"React Web Application","archived":false,"fork":false,"pushed_at":"2026-01-02T05:00:24.000Z","size":46867,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-07T20:53:23.747Z","etag":null,"topics":["airtable","auth0","netlify","reactjs","stripe"],"latest_commit_sha":null,"homepage":"https://shelbybourbontours.com","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dladden.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-10-18T22:18:25.000Z","updated_at":"2026-01-02T05:00:28.000Z","dependencies_parsed_at":"2025-03-14T00:36:53.659Z","dependency_job_id":null,"html_url":"https://github.com/dladden/bourbon-tour-agency-react","commit_stats":null,"previous_names":["dladden/bourbon-tour-agency-react"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dladden/bourbon-tour-agency-react","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dladden%2Fbourbon-tour-agency-react","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dladden%2Fbourbon-tour-agency-react/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dladden%2Fbourbon-tour-agency-react/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dladden%2Fbourbon-tour-agency-react/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dladden","download_url":"https://codeload.github.com/dladden/bourbon-tour-agency-react/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dladden%2Fbourbon-tour-agency-react/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28851002,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-28T15:15:36.453Z","status":"ssl_error","status_checked_at":"2026-01-28T15:15:13.020Z","response_time":57,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["airtable","auth0","netlify","reactjs","stripe"],"created_at":"2026-01-28T20:36:18.600Z","updated_at":"2026-01-28T20:36:20.284Z","avatar_url":"https://github.com/dladden.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# \u003ccenter\u003e React Static Web Application \u003c/center\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"src/assets/readme-logo.png\" alt=\"Alt Text\" width=\"200\"/\u003e\n\u003c/p\u003e\n\n## Disclaimer\n\nPlease visit [bourbon-tour-agency-react-public](https://github.com/dladden/bourbon-tour-agency-react-public) for cloning. Thank you.\nPlease read the license agreement carefully before proceeding.\n\n## Important Notice\n\nBefore using any part of this repository, please ensure you have thoroughly read and understood the [License](LICENSE.md) provided. By accessing or using this repository, you agree to comply with the terms and conditions set forth in the license. Failure to adhere to these terms may result in legal action.\n\nFor a similar setup that you can clone and use for any purpose, please visit the following link: [bourbon-tour-agency-react-public\n](https://github.com/dladden/bourbon-tour-agency-react-public).\n\n# About this Application:\n\n#### Static Web Application Built/Managed For A Touring Company. This application is designed to be responsive on the web and mobile devices. Multiple contexts are used in this project. Context eliminates nested components by giving components hooks that can be called upon without passing down the props. Additionally, Styled-components are used in this project to manage the CSS quickly. Styled components leverage a mixture of JavaScript and CSS using a technique called CSS-in-JS for user Authentication Auth0 is used. Auth0 is a flexible, drop-in solution to add authentication and authorization services to your applications. It is a single sign-on (SSO) solution for web applications. To create a secure checkout, a PrivateRoute is created where a Stripe component is embedded. Stripe is a payment services provider that lets merchants accept credit and debit cards or other payments.\n\n## Support\n\nFind the App Useful? [Visit My Site](https://www.denysladden.com/)\n\n## Initial Set Up\n\n#### Run The App Locally\n\n```sh\nnpm run install-dependencies\n```\n\n- rename .env.temp to .env\n\n```sh\nnpm start\n```\n\n- visit url http://localhost:3000/\n\n#### Setup React App\n\n- create \u003cb\u003eclient\u003c/b\u003e folder\n- open terminal\n\n```sh\ncd client\n```\n\n```sh\nnpx create-react-app .\n```\n\n```sh\nnpm start\n```\n\n- set editor/browser side by side\n- copy/paste assets from complete project# Jobify\n\n#### Static Page Application with API\n\n#### Run The App Locally\n\n```sh\nnpm run install-dependencies\n```\n\n- rename .env.temp to .env\n- setup values for - MONGO_URL, JWT_SECRET, JWT_LIFETIME\n\n```sh\nnpm start\n```\n\n- visit url http://localhost:3000/\n\n# Table Of Contents\n\n## - [React](#react)\n\n## - [React Router](#router)\n\n## - [Design: UI/UX](#ux)\n\n## - [Auth0](#auth)\n\n## - [Stripe](#stripe)\n\n## - [SEO](#seo)\n\n## - [Database](#data)\n\n## - [Screen Captures](#media)\n\n## - [Helpful Links](#links)\n\n## - [Project Dependencies](#dep)\n\n\u003ca id=\"react\"\u003e\u003c/a\u003e\n\n# React\n\nReact is an excellent choice for building static web applications due to its speed, efficiency, and extensive ecosystem. By breaking down the UI into reusable components and using a virtual DOM, React allows for the creation of complex and interactive UIs with improved performance. Its popularity and large community also provide developers with plenty of resources and third-party libraries to help speed up development and add additional functionality to their app. Overall, React's strengths make it a great option for building static web applications.\n\n## React Components: https://17.reactjs.org/\n\n### React Context API\n\nMultiple context are used in this project. Context eliminates nested components by\ngiving components hooks which can be called upon without passing down the props.\nContext creates avaivality through the whole application for components.\nhttps://reactjs.org/docs/context.html\n\n### useReducer\n\nuseReducer is another hook used for the modern state management in React.\nReducers Specify how the apps state changes in response to action sent to the store. It\nis a function that accepts (state, action) as argument and then returns the next state of\nthe application. This concept was introduced in Redux first and then it is adapted by\nReact as well. Typically, reducer is a function which accepts two arguments - state and action. Based on the action provided, reducer will perform some operations on a state and returns a new updated state. In context of React, useReducer also performs similar state management. You can read more about useReducer in detail in the documentation: https://reactjs.org/docs/hooks-reference.html#usereducer\n\n\u003ca id=\"router\"\u003e\u003c/a\u003e\n\n### Rect Routing\n\nIn a typical website all requests are sent to the server and server continuously\nresponds. In a react.js application using ReactDom a simple response can be a full JS\nbundle. It is dispatched after a request and houses all the components, react Router\nthen injects these components bypassing the server request. React Router eliminates\nserver requests by intercepting them when possible and developing needed\ncomponents for the page that the user requested. This makes for lightning fast website\nas the React js bundle has all that is needed dynamically. Great article on this can be found here: https://www.freecodecamp.org/news/how-to-use-react-router-version-6/#:~:text=To%20install%20React%20Router%2C%20all,%2Drouter%2Ddom%406%20\n\n## Protect a route\n\nProtect a route component using the withAuthenticationRequired higher order\ncomponent. Visits to this route when unauthenticated will redirect the user to the\nlogin page and back to this page after login.\n\nReact Access Restrictions\nhttps://reactjs.org/docs/accessibility.html\n\nThe Complete Guide to React User Authentication with Auth\nhttps://auth0.com/blog/complete-guide-to-react-user-authentication/\n\n### Dispatching\n\nDispatching is a fundamental part of Redux, which is a predictable state container for JavaScript applications. When an action is dispatched in a React-Redux application, it is sent to the Redux store, which updates the application state based on the action type and payload. This allows for a centralized and predictable way of managing state in a React application, making it easier to reason about and debug. What Even Is A Dispatch Function?: https://dev.to/dustinmyers/what-even-is-a-dispatch-function-27ma\n\n### Code Examples\n\n#### useEffect\n\nuseEffect is a powerful feature in React that allows developers to handle side effects in functional components. It enables data fetching, DOM manipulation, and other side effects that would otherwise be possible only in class components. The dependency array in useEffect provides granular control over when the effect runs, improving performance and avoiding unnecessary renders.\n\n### useEffect: Dependency Array vs No Dependency Array\n\n`useEffect(() =\u003e {\nperformSideEffect();\n}, []);`\n\n`useEffect(() =\u003e {\nperformSideEffect();\n});`\n\n- Giving it an empty array acts like componentDidMount as in, it only runs\n  once.\n\n- Giving it no second argument acts as\n  both componentDidMount and componentDidUpdate, as in it runs first on mount\n  and then on every re-render.\n- Giving it an array as second argument with any value inside, eg ,\n  [variable1] will only execute the code inside your useEffect hook ONCE on mount, as\n  well as whenever that particular variable (variable1) changes.\n  You can read more about the second argument as well as more on how hooks actually\n  work on the official docs at https://reactjs.org/docs/hooks-effect.html\n\n\u003ca id=\"ux\"\u003e\u003c/a\u003e\n\n# UI/UX\n\n### STYLING:\n\nStyled-components is a library built for React and React Native developers. It allows\nyou to use component-level styles in your applications. Styled-components leverage a\nmixture of JavaScript and CSS using a technique called CSS-in-JS. Styled-components\nis a good development experience (at least for me), and that’s the whole point of it. If\nyou find other ways of styling a react component to be unintuitive, styled-\ncomponents can be a good alternative for you\n\nStyled-Components (lets you write actual CSS in your JavaScript):\nhttps://styled-components.com/\n\nBasics of Styled-Components\nhttps://styled-components.com/docs/basics\n\nNetlify Redirects and Rewrites\nhttps://docs.netlify.com/routing/redirects/\n\n\u003ca id=\"auth\"\u003e\u003c/a\u003e\n\n## Auth\n\nAuth0 is a flexible, drop-in solution to add authentication and authorization services\nto your applications. It is single sign on (SSO) solution for web applications. Rather\nthan having depend on the login in options for any given application, you can have\nAuth0 be your front end and handle logins for you. Auth0 can be great if a web\napplication does not have some of the features that you want for security such as like\n2FA.\n\nMoreover, it allows you to eliminate the need for users to have a dozen separate sets\nof credentials for a dozen different web portals. User just use their single Auth0 login\nfor every application.\n\nIt works by integrating with the web application itself. Auth0 ensures that your login\nis correct, then it will pass a token to the web app saying \"User user234 has been\nauthenticated”. Allow user access to the application. The web app is configured to\nacknowledge this token as legitimate therefore user234 is allowed access to the\napplication.\n\n## Auth0 Quick-Starts \u0026 Tutorials:\n\nAuthentication and user Login:\nhttps://auth0.com/docs/quickstart/spa/react\n\nAuth0 React SDK for Single Page Apps\nhttps://auth0.com/docs/libraries/auth0-react\n\nReact: Login\nhttps://auth0.com/docs/quickstart/spa/react/01-login\n\nHow Auth0 and Netlify work together:\nhttps://www.netlify.com/integrations/auth0/\n\n### Change storage options\n\nThe Auth0 SPA SDK stores tokens in memory by default. However, this does not\nprovide persistence across page refreshes and browser tabs. Instead, you can opt-in to\nstore tokens in local storage by setting the cacheLocation property\nto localstorage when initializing the SDK. This can help to mitigate some of the\neffects of browser privacy technology that prevents access to the Auth0 session\ncookie by storing Access Tokens for longer\n\n## Authenticating Social Connections on Auth\n\nWhat is SAML?\nSecurity Assertion Markup Language 2.0 is a version of the SAML standard for\nexchanging authentication and authorization identities between security domains.\nSAML is used to provide federated authentication, as a digital passport. If I want to\nprovide a service lots of different people can use, I need to be able to know who they\nare, especially if I am storing things for them. The traditional way to solve this is\ncreating an account for each user with a username and password. This can be a pain to\nmanage, is annoying for users to have a million different accounts, and can be a\nsecurity hole. It can also be difficult to work into low-level services that operate\nbelow the user level.\n\nHow SAML Authentication Works, and Why It’s Still Relevant for Enterprise\nCustomers?\nSAML 2.0 (Security Assertion Markup Language) is an open standard created to\nprovide cross-domain single sign-on (SSO). In other words, it allows a user to\nauthenticate in a system and gain access to another system by providing proof of their\nauthentication.\n\n\u003ca id=\"stripe\"\u003e\u003c/a\u003e\n\n# Stripe\n\nStripe is a payment services provider that lets merchants accept credit and debit cards\nor other payments. It is used by some of the world’s largest companies, including\nAmazon and Shopify. To better understand what Stripe is, you should first know\nwhat a payment gateway is. On an e-commerce site or mobile app, you take the\ncustomer’s billing information and pass it along to a payment gateway. A payment\ngateway is an intermediary between the credit/debit card companies and the business\naccount. The payment gateway confirms that the charge can be made for the given\ncard information and sends the charge details to the business account. The same\ncharge details are also passed to the app making the payment request. Stripe is one of\nthe prime payment gateways. It enables businesses and individuals to accept payments\nusing their rich API and robust platform.\n\n## Netlify and Stripe\n\nTo make a secure connection and not just use your own API this project utilizes\nnetlify functions to set up a netlify server which will handle the secure checkout with\nStripe. Netlify function behaves as a middle man connection for security purposes.\n\n## Stripe Custom Payment Flow\n\nStripe allows you to embed a custom payment form in your website or application.\nThe client- and server-side code builds a checkout form with elements to complete a\npayment using various payment methods. https://stripe.com/docs/payments/quickstart\n\n## Stripe Quick-Starts \u0026 Tutorials:\n\nStripe.js Reference: https://stripe.com/docs/js\n\n\u003ca id=\"seo\"\u003e\u003c/a\u003e\n\n# SEO: About Search Engine Optimization\n\nIn this project react-helmet-async is used for SEO optimization.\n\nSEO: SSR Server Side Rendering vs Pre-rendering\nFor the longest time, I did not understand the term Static Application since in my\nslim knowledge of web development server is the main output of any application\ndelivered on the web. However, Static application is simply application which is not\nreliant on connection to an online server or database. These apps built in this way are\ndownloaded once, usually periodically updated, and are able to function offline only\nwith the device on which they are installed. What does this have todo with SEO?\nWeb pages are crawled by google this is where the ranking is determined. Server-side\nrendering means that a website’s JavaScript is rendered on the website’s server. To use\nthe furniture example again, this would be like ordering furniture that arrives at your\nhouse fully assembled. Sending fully-rendered pages to search engine bots also means\nthat you’re not risking the “partial indexing” that can happen with client-side\nrendered content. When Google and other search engine bots try to access your page,\ninstead of having to wait for rendering resources to become available before seeing\nyour full page, they’ll get the fully-rendered page right from the get-go. So, SSR\ncompiles and renders pages on the server on-demand when the page is requested,\nhowever another option is pre-rendering which compiles and renders pages on the\nserver at build time/when deployed. The mandatory server for a universal app can be\na deterrent for some and may be overkill for a small application. This is why pre-\nrendering can be a really nice alternative. But the real solution is NextJS. Beyond pre-\nrendering it offers many other features such as their image tag and a file-based router.\nIf you ever want to switch from SSG to ISR or SSR, it's a mere matter of adding some\ndata-fetching routes and specifying some params.\n\n\u003ca id=\"data\"\u003e\u003c/a\u003e\n\n# The Database:\n\n### This Application uses Serverless Functions to fetch the data from a non-relational data base. Here is an example of the functions at use to fetch this data: https://github.com/dladden/sereverless-functions-react\n\nTo fetch data from Airtable using Netlify functions, use the Airtable API to query the relevant data, and then use Netlify's serverless functions to retrieve and process the data. To get started, you'll need to create a new Netlify function and set up the Airtable API credentials. Once you have that set up, you can use the axios package to make a GET request to the Airtable API and retrieve the data. After that, you can process the data however you like and return it to the client. Make sure to handle any errors that may occur during the process and include appropriate error handling in your code.\n\nThis Project uses theses fields:\n\n- name - name of the tour\n- dist - distillery\n- price - price of the tour\n- available - checkmark for if the tour is available\n- best_sell - best sellers\n- images - tour images\n- featured - tours listed on the home page\n- category - category of each listing ie: tour, stay, food, event\n- trans - transportation for the tours\n- stars - review based on 0.5 rating\n- spec_res - special reservation checkmark for any listings that require reservation outside of the site\n- tour_url - url to tour listing on facebook\n- rev_url - url to where the reviews came from in this case facebook\n- guest - limit of guests per tour\n\nExample of the Fields in the Database:\n\n| name      | dist                  | price | available | best_sell | images      | featured |\n| --------- | --------------------- | ----- | --------- | --------- | ----------- | -------- |\n| Best Tour | Makers Mark, Jim Beam | 40000 | ✓         | ✓         | image01.png | ✓        |\n\n\u003ca id=\"media\"\u003e\u003c/a\u003e\n\n# Screen Captures\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"src/assets/example01.webp\" alt=\"Alt Text\" width=\"800\"/\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"src/assets/example02.jpg\" alt=\"Alt Text\" width=\"800\"/\u003e\n\u003c/p\u003e\n\n\u003ca id=\"links\"\u003e\u003c/a\u003e\n\n# Helpful Links:\n\nIntl.NumberFormat\nhttps://developer.mozilla.org/en-\nUS/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat\n\nMaking Asynchronous HTTP Requests in JavaScript with Axios:\nhttps://stackabuse.com/making-asynchronous-http-requests-in-javascript-with-axios/\n\nComponents and Props\nhttps://reactjs.org/docs/components-and-props.html\n\nConditional Rendering\nhttps://beta.reactjs.org/learn/conditional-rendering\n\nConditional Rendering (docs)\nhttps://reactjs.org/docs/conditional-rendering.html\n\nJavaScript Sorting Arrays\nhttps://www.w3schools.com/js/js_array_sort.asp\n\nReact ES6 Spread Operator\nhttps://www.w3schools.com/react/react_es6_spread.asp\n\nSorting in React JS\nhttps://owlcation.com/stem/creating-a-sortable-list-in-react-js\n\nWhat is a DNS CNAME record?\nhttps://www.cloudflare.com/learning/dns/dns-records/dns-cname-record/\n\nUsing Netlify lambda functions to send emails\nhttps://dev.to/char_bone/using-netlify-lambda-functions-to-send-emails-from-a-\ngatsbyjs-site-3pnb\n\nSecuring Netlify Functions with serverless-jwt and Auth\nhttps://sandrino.dev/blog/securing-netlify-functions-with-serverless-jwt\n\nReact SEO\nhttps://www.youtube.com/watch?v=wWeG8rWkMsM\n\n\u003ca id=\"dep\"\u003e\u003c/a\u003e\n\n# Dependencies \u0026 Synk Advisor Ratings:\n\nreact-helmet-async\nhttps://www.npmjs.com/package/react-helmet-async\n\nSynk Advisor: react-helmet-async\nhttps://snyk.io/advisor/npm-package/react-helmet-async\n\nreact-slideshow-image v4.1.\nhttps://www.npmjs.com/package/react-slideshow-image\n\nSynk Advisor: react-slideshow-image\nhttps://snyk.io/advisor/npm-package/react-slideshow-image\n\nreact-select\nhttps://www.npmjs.com/package/react-select\n\nSynk Advisor: react-select\nhttps://snyk.io/advisor/npm-package/react-select\n\nREACT DATE PICKER:\nhttps://www.npmjs.com/package/react-datepicker\n\nSynk Advisor: react-calendar\nhttps://snyk.io/advisor/npm-package/react-calendar\n\nReact Router Hash Link\nhttps://www.npmjs.com/package/react-router-hash-link\n\nSynk Advisor: react-router-hash-link\nhttps://snyk.io/advisor/npm-package/react-router-hash-link\n\nreact-google-recaptcha\nhttps://www.npmjs.com/package/react-google-recaptcha\n\nSynk Advisor: react-google-recaptcha\nhttps://snyk.io/advisor/npm-package/react-google-recaptcha\n\ndisable-react-devtools\nhttps://www.npmjs.com/package/@fvilers/disable-react-devtools\n\nSynk Advisor: disable-react-devtools\nhttps://snyk.io/advisor/npm-package/disable-react-devtools\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdladden%2Fbourbon-tour-agency-react","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdladden%2Fbourbon-tour-agency-react","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdladden%2Fbourbon-tour-agency-react/lists"}