Dashboard Temp Share Shortlinks Frames API

HTMLify

yelpcamp.html
Views: 16 | Author: cody
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
<!DOCTYPE html>
<html lang="en" dir="ltr" data-cast-api-enabled="true">
  <head>
    <!-- META -->
    <meta charset="UTF-8">
    <meta http-equiv="Content-Language" content="en">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <!-- Primary Meta Tags -->
    <title>YelpCamp Project Walkthrough</title>
    <meta name="title" content="YelpCamp Project Walkthrough">
    <meta name="author" content="Jacob Grisham">
    <meta name="keywords" content="Jacob,Grisham,Jacob Grisham,YelpCamp,Yelp,Camp">
    <meta name="description" content="Walkthrough of my project YelpCamp. YelpCamp is a monolithic MVC full-stack web app built with Node.js, Express.js, MongoDB, EJS, Bootstrap, and hosted on Heroku, Cloudflare, and MongoDB Atlas with continuous delivery with Circle CI. The main features include the ability to create campground listings, leave comments, and review campgrounds.">

    <!-- Open Graph / Facebook -->
    <meta property="og:locale" content="en_US">
    <meta property="og:type" content="website">
    <meta property="og:url" content="https://www.jacobgrisham.com/">
    <meta property="og:title" content="YelpCamp Project Walkthrough">
    <meta property="og:site_name" content="Jacob Grisham Professional Portfolio">
    <meta property="og:image" content="https://www.jacobgrisham.com/img/thumbnail.png">
    <meta property="og:image:secure_url" content="https://www.jacobgrisham.com/img/thumbnail.png">
    <meta property="og:image:type" content="image/png">
    <meta property="og:image:height" content="630">
    <meta property="og:image:width" content="1200">
    <meta property="og:image:alt" content="YelpCamp">
    <meta property="og:description" content="Walkthrough of my project YelpCamp. YelpCamp is a monolithic MVC full-stack web app built with Node.js, Express.js, MongoDB, EJS, Bootstrap, and hosted on Heroku, Cloudflare, and MongoDB Atlas with continuous delivery with Circle CI. The main features include the ability to create campground listings, leave comments, and review campgrounds." name="description">
    <meta property="fb:app_id" content="2733409333567092">

    <!-- Twitter Meta Tags -->
    <meta property="twitter:card" content="summary_large_image">
    <meta property="twitter:url" content="https://www.jacobgrisham.com/">
    <meta property="twitter:title" content="YelpCamp Project Walkthrough">
    <meta property="twitter:description" content="Walkthrough of my project YelpCamp. YelpCamp is a monolithic MVC full-stack web app built with Node.js, Express.js, MongoDB, EJS, Bootstrap, and hosted on Heroku, Cloudflare, and MongoDB Atlas with continuous delivery with Circle CI. The main features include the ability to create campground listings, leave comments, and review campgrounds.">
    <meta property="twitter:image" content="https://www.jacobgrisham.com/img/thumbnail.png">

    <!-- SEO -->
    <link rel="canonical" href="https://www.jacobgrisham.com/pages/projects/yelpcamp.html">

    <!-- FONTS -->
    <link href="https://fonts.googleapis.com/css2?&family=Montserrat:wght@100;200;300&family=Nunito+Sans:wght@200;300;400&family=PT+Mono&display=swap" rel="stylesheet">

    <!-- CSS -->
    <link rel="stylesheet" href="../css/style.css">
    <!-- Include this second link for production -->
    <link rel="text/css" href="../css/style.css">

    <!-- FAVICON -->
    <link rel="icon" href="../favicon.ico" type="image/x-icon">
    <link rel="shortcut icon" href="../favicon.ico">
    <link rel="apple-touch-icon" sizes="180x180" href="../favicon_io/apple-touch-icon.png">
    <link rel="icon" type="image/png" sizes="32x32" href="../favicon_io/favicon-32x32.png">
    <link rel="icon" type="image/png" sizes="16x16" href="../favicon_io/favicon-16x16.png">
    <link rel="manifest" href="../site.webmanifest">
    </head>
  <body class="projects-body">
    <!-- Loader -->
    <div class="laptop loader">
      <svg class="laptop__svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 79.375 79.375" height="300" width="300">
        <g transform="translate(-2.22 3.222)">
          <g transform="translate(-335.788 -22.347) scale(.39771)">
            <rect fill="#b3b3b3" width="137.583" height="89.958" x="880.884" y="99.204" ry="2.022"/>
            <rect y="100.527" x="882.207" height="87.313" width="134.938" ry="2.134" rx="0"/>
            <path d="M886.175 104.496h127v79.375h-127z" fill="#4d4d4d"/>
            <rect fill="#333" width="29.788" height="70.68" x="891.36" y="113.22" ry="0" rx="0"/>
          </g>
          <path d="M16.674 20.813h50.597v.317H16.674zM30.53 24.5h36.617v15.488H30.529zm0-1.555h9.184V24.5H30.53z" fill="#1a1a1a"/>
          <path d="M30.53 22.69h9.183v.255H30.53z" fill="#003380"/>
          <rect fill="#2c5aa0" width="6.399" height=".455" x="32.113" y="23.546" ry=".227"/>
          <path d="M30.534 41.82h36.645v8.972H30.534zm-.005-1.557h9.184v1.555H30.53z" fill="#1a1a1a"/>
          <path d="M30.53 40.007h9.183v.256H30.53z" fill="#003380"/>
          <rect fill="#2c5aa0" ry=".227" y="40.793" x="32.089" height=".455" width="6.399"/>
          <g transform="translate(-19.725 -1.116) scale(.39771)" fill="#ccc">
            <rect ry=".767" y="62.346" x="99.493" height="1.535" width="14.902"/>
            <rect width="14.902" height="1.535" x="103.298" y="65.818" ry=".767"/>
            <rect width="16.379" height="1.535" x="106.895" y="69.291" ry=".767"/>
            <rect width="11.497" height="1.535" x="106.959" y="72.763" ry=".767"/>
            <rect ry=".767" y="76.235" x="107.055" height="1.535" width="11.497"/>
            <rect ry=".767" y="79.707" x="106.927" height="1.535" width="11.497"/>
            <rect ry=".767" y="83.179" x="102.833" height="1.535" width="16.379"/>
            <rect ry=".767" y="86.651" x="102.746" height="1.535" width="13.001"/>
            <rect ry=".767" y="90.123" x="106.991" height="1.535" width="16.379"/>
            <rect ry=".767" y="93.595" x="107.338" height="1.535" width="9.882"/>
            <rect ry=".767" y="97.067" x="100.024" height="1.535" width="16.379"/>
            <rect ry=".767" y="100.539" x="100.196" height="1.535" width="12.74"/>
            <rect ry=".767" y="104.011" x="100.379" height="1.535" width="12.44"/>
          </g>
          <g transform="translate(-411.355 -23.965) scale(.39771)">
            <rect fill="#ccc" ry=".887" y="193.745" x="1056.522" height="4.151" width="166.317"/>
            <path fill="#999" d="M1222.19 197.896h-165.048l4.029 2.723h156.468z"/>
          </g>
          <rect fill="#b3b3b3" ry=".4" y="53.067" x="38.233" height=".801" width="7.35"/>
          <rect fill="#999" ry=".4" y="43.091" x="31.651" height=".801" width="10.779"/>
          <rect fill="#999" width="10.779" height=".801" x="31.651" y="45.052" ry=".4"/>
          <rect fill="#999" width="10.779" height=".801" x="31.651" y="47.013" ry=".4"/>
          <rect fill="#999" width="10.779" height=".801" x="31.651" y="48.975" ry=".4"/>
          <rect fill="#999" ry=".051" y="49.718" x="43.875" height=".103" width="1.511"/>
          <rect fill="#999" width="5.07" height=".801" x="43.661" y="43.181" ry=".4"/>
          <rect fill="#999" width="13.784" height=".801" x="43.683" y="45.152" ry=".4"/>
          <rect fill="#999" width="10.779" height=".801" x="43.703" y="46.958" ry=".4"/>
          <rect fill="#c83737" width="4.572" height=".61" x="31.725" y="25.832" ry=".305"/>
          <rect fill="#fd5" width="8.157" height=".61" x="37.883" y="25.823" ry=".305"/>
          <rect fill="#fd5" ry=".305" y="27.46" x="37.922" height=".61" width="10.535"/>
          <rect fill="#fd5" ry=".305" y="29.214" x="37.922" height=".61" width="6.053"/>
          <rect fill="#999" width="10.779" height=".801" x="31.751" y="30.95" ry=".4"/>
          <rect fill="#ccc" ry=".325" y="32.771" x="31.771" height=".649" width="3.93"/>
          <rect fill="#c83737" ry=".305" y="32.771" x="36.627" height=".61" width="4.572"/>
          <rect fill="#5fbcd3" width="6.053" height=".61" x="42.045" y="32.731" ry=".305"/>
          <rect fill="#ccc" width="3.93" height=".649" x="48.951" y="32.672" ry=".325"/>
          <rect class="code" id="code-8" fill="#fd5" width="6.053" height=".61" x="35.771" y="34.449" ry=".305" />
          <rect class="code" id="code-7" fill="#5fbcd3" ry=".305" y="34.5" x="42.27" height=".61" width="9.509" />
          <rect class="code" id="code-6" fill="#ccc" ry=".325" y="36.08" x="38.948" height=".649" width="3.93" />
          <rect class="code" id="code-5" fill="#37c871" ry=".325" y="36.08" x="44.106" height=".649" width="2.847" />
          <rect class="code" id="code-4" fill="#37c871" ry=".325" y="36.131" x="47.923" height=".649" width="2.692" />
          <rect class="code" id="code-3" fill="#5fbcd3" ry=".325" y="36.131" x="51.585" height=".649" width="6.097" />
          <rect class="code" id="code-2" fill="#ccc" width="3.93" height=".649" x="35.904" y="37.834" ry=".325" />
          <rect class="code" id="code-1" fill="#c83737" width="7.203" height=".61" x="41.102" y="37.905" ry=".305" />
        </g>
      </svg>
    </div>

    <div class="projects-body__focus-container">
      <!-- HEADER -->
      <section>
        <h1 class="projects-body__main-heading">YelpCamp Project Walkthrough</h1>
        <h2 class="blog-body__sub-heading">March - June 2020</h2>
    
        <h2 class="projects-body__heading">Source Code
          <span>
            <a href="https://github.com/JacobGrisham/YelpCamp" aria-label="link to YelpCamp source code" target="_blank" rel="noopener noreferrer">
              <svg class="skills-box__header-icon">
                <use xlink:href="../img/sprite.svg#icon-github"></use>
              </svg>
            </a>
          </span>
        </h2>

        <div>
          <img src="../img/YelpCampMetaImage-min.png" class="projects-body__image lax"></img>
        </div>
      </section>
  
      <!-- ABOUT -->
      <section>
        <h2 class="projects-body__heading">About</h2>
        <p>First full-stack web application. Fundamentally, it's review website for campsites. The main features are login, sign-up, Admin role, Google Maps API, and Create, Edit, Update, Delete (CRUD) for campgrounds, comments, and reviews. Create routes have authentication. Edit, Update, and Delete routes have authentication and authorization. The basic foundation was built in the capstone project from the Udemy course <i>The Web Developer Bootcamp</i>. The core of the application was built from March - June 2020, with sporadic updates up until April 2022.</p>
      </section>
  
      <!-- PRODUCT FEATURES AND SPECIFICATIONS -->
      <section>
        <h2 class="projects-body__heading">Product Features and Specifications</h2>
        <ul class="projects-body__list">
          <li>Account creation, including a secret Admin role</li>
          <li>Users can upload data on campgrounds, edit the data they uploaded, but only the data they uploaded and no one elses.</li>
          <li>Users can leave as many comments as they want in the comment section on each campground page</li>
          <li>Each user can leave up to one review for each campground between 1 and 5 stars</li>
          <li>Google Maps embedded on each campground page</li>
          <li>Google Ads on each campground page to pay for the Google Maps</li>
        </ul>
      </section>
  
      <!-- TECHONOLOGIES -->
      <section class="technologies">
        <h2 class="projects-body__heading technologies__header">Technologies</h2>
        <div class="skills-box__no-shadow">
          <h4 class="skills-box__header">
            <svg class="skills-box__header-icon">
              <use xlink:href="../img/sprite.svg#icon-embed2"></use>
            </svg>
            Front-End
          </h4>
          <ul class="skills-box__list">
            <li class="skills-box__item">
              <svg class="skills-box__icon">
                <use xlink:href="../img/sprite.svg#icon-html5"></use>
              </svg>
              HTML5
            </li>
            <li class="skills-box__item">
              <svg class="skills-box__icon">
                <use xlink:href="../img/sprite.svg#icon-css3"></use>
              </svg>
              CSS3
            </li>
            <li class="skills-box__item">
              <svg class="skills-box__icon">
                <use xlink:href="../img/sprite.svg#icon-bootstrap"></use>
              </svg>
              Boostrap
            </li>
            <li class="skills-box__item">
              <svg class="skills-box__icon">
                <use xlink:href="../img/sprite.svg#icon-javascript"></use>
              </svg>
              Javascript ES6+
            </li>
          </ul>
        </div>
    
        <!-- BACK-END -->
        <div class="skills-box__no-shadow">
          <h4 class="skills-box__header">
            <svg class="skills-box__header-icon">
              <use xlink:href="../img/sprite.svg#icon-terminal"></use>
            </svg>
            Back-End
          </h4>
          <ul class="skills-box__list">
            <li class="skills-box__item">
              <svg class="skills-box__icon">
                <use xlink:href="../img/sprite.svg#icon-node-dot-js"></use>
              </svg>
              Node.js w/ Express.js and EJS
            </li>
          </ul>
        </div>
    
        <!-- Testing -->
        <div class="skills-box__no-shadow">
          <h4 class="skills-box__header">
            <svg class="skills-box__header-icon">
              <use xlink:href="../img/sprite.svg#icon-lab"></use>
            </svg>
            Testing
          </h4>
          <ul class="skills-box__list">
            <li class="skills-box__item">
              <svg class="skills-box__icon">
                <use xlink:href="../img/sprite.svg#icon-jest"></use>
              </svg>
              Jest
            </li>
            <li class="skills-box__item">
              <svg class="skills-box__icon">
                <use xlink:href="../img/sprite.svg#icon-lighthouse"></use>
              </svg>
              Google Lighthouse
            </li>
          </ul>
        </div>
    
        <!-- DATABASE -->
        <div class="skills-box__no-shadow">
          <h4 class="skills-box__header">
            <svg class="skills-box__header-icon">
              <use xlink:href="../img/sprite.svg#icon-database"></use>
            </svg>
            Database
          </h4>
          <ul class="skills-box__list">
            <li class="skills-box__item">
              <svg class="skills-box__icon">
                <use xlink:href="../img/sprite.svg#icon-mongodb"></use>
              </svg>
              MongoDB
            </li>
          </ul>
        </div>

        <!-- DEVELOPMENT -->
        <div class="skills-box__no-shadow">
          <h4 class="skills-box__header">
            <svg class="skills-box__header-icon">
              <use xlink:href="../img/sprite.svg#icon-cogs"></use>
            </svg>
            Development
          </h4>
          <ul class="skills-box__list">
            <li class="skills-box__item">
              <svg class="skills-box__icon">
                <use xlink:href="../img/sprite.svg#icon-git"></use>
              </svg>
              Git
            </li>
            <li class="skills-box__item">
              <svg class="skills-box__icon">
                <use xlink:href="../img/sprite.svg#icon-github"></use>
              </svg>
              GitHub
            </li>
            <li class="skills-box__item">
              <svg class="skills-box__icon">
                <use xlink:href="../img/sprite.svg#icon-codacy"></use>
              </svg>
              Codacy
            </li>
            <li class="skills-box__item">
              <svg class="skills-box__icon">
                <use xlink:href="../img/sprite.svg#icon-codeclimate"></use>
              </svg>
              CodeClimate
            </li>
          </ul>
        </div>
    
        <!-- PRODUCTION -->
        <div class="skills-box__no-shadow">
          <h4 class="skills-box__header">
            <svg class="skills-box__header-icon">
              <use xlink:href="../img/sprite.svg#icon-cloud-upload"></use>
            </svg>
            Production
          </h4>
          <ul class="skills-box__list">
            <li class="skills-box__item">
              <svg class="skills-box__icon">
                <use xlink:href="../img/sprite.svg#icon-heroku"></use>
              </svg>
              Heroku
            </li>
            <li class="skills-box__item">
              <svg class="skills-box__icon">
                <use xlink:href="../img/sprite.svg#icon-cloudflare"></use>
              </svg>
              Cloudflare
            </li>
            <li class="skills-box__item">
              <svg class="skills-box__icon">
                <use xlink:href="../img/sprite.svg#icon-mongodb"></use>
              </svg>
              MongoDB Atlas
            </li>
            <li class="skills-box__item">
              <svg class="skills-box__icon">
                <use xlink:href="../img/sprite.svg#icon-sentry"></use>
              </svg>
              Sentry
            </li>
            <li class="skills-box__item">
              <svg class="skills-box__icon">
                <use xlink:href="../img/sprite.svg#icon-circleci"></use>
              </svg>
              CircleCI
            </li>
            <li class="skills-box__item">
              <svg class="skills-box__icon">
                <use xlink:href="../img/sprite.svg#icon-google-domains"></use>
              </svg>
              Google Domains
            </li>
            <li class="skills-box__item">
              <svg class="skills-box__icon">
                <use xlink:href="../img/sprite.svg#icon-google-analytics"></use>
              </svg>
              Google Analytics
            </li>
            <li class="skills-box__item">
              <svg class="skills-box__icon">
                <use xlink:href="../img/sprite.svg#icon-google-ads"></use>
              </svg>
              Google Ads
            </li>
          </ul>
        </div>
      </section>

      <!-- UX/UI MOCKS AND GRAPHIC DESIGN -->
      <section>
        <h2 class="projects-body__heading">UX/UI Mocks and Graphic Design</h2>
        <p class="projects-body__paragraph-spacing-below">Create and Update forms have both client-side and server-side validation for a better user experience</p>

        <p class="projects-body__paragraph-spacing-below">Leveraged the Boostrap Design System</p>

        <p>Used Inkscape to create SVG illustrations from scratch to gain a deeper understanding of SVG. I don't plan on creating SVG graphics from scratch often, but now that I know how to do it, I can easily edit existing SVGs. If I'm unable to find an open-source SVG, now I can always create one exactly as needed. When I was younger, I used to draw all the time, so creating my own SVGs in Inkscape was actually pretty fun to explore. I had some formal training in both private institutions and in public education, specifically in high school, and it was fun to see how the same principles applied to a medium I never tried before: graphic design.</p>
      </section>

      <!-- DESIGN AND ARCHITECTURE -->
      <section>
        <h2 class="projects-body__heading">Design and Architecture</h2>
        <h3>Code Architecture</h3>
        <p class="projects-body__paragraph-spacing-below">Used a Model-View-Controller (MVC) Monolithic Architecture since it's the most simple architecture to gain an introduction to full-stack web development. Building a MVC Monolith allows one to gain a perspective on the range of achitectures, particularly the lower-end of the range. The Monolith Architecture falls short in scalability and separation of front-end and back-end. The MVC Architecture falls short when the application begins to grow in complexity with the addition of services that could stand on thier own. The MVC Architecture is perhaps best used for simple proof-of-concept projects, like this one. However, for any projects that serve real business needs, I would opt to use an event-driven serverless architecture.</p>

        <div>
          <img src="../img/YelpCamp-Code-Architecture.drawio.svg" alt="YelpCamp Code Architecture Diagram" class="projects-body__image projects-body__paragraph-spacing-below lax"></img>
        </div>

        <p class="projects-body__paragraph-spacing-below"><span class="projects-body__bold-text">Model</span>: NoSQL database for the flexibility compared to a SQL database, MongoDB in particular because of its prevalence in the industry.</p>

        <p class="projects-body__paragraph-spacing-below"><span class="projects-body__bold-text">View</span>: Chose Embedded Javascript Templates (EJS) as the front-end templating language for more DRY code compared to plain HTML and for dynamic user-experiences. This is a simple templating language, similar to Jinja for Python. Both however fall short on front-end scalability, modularity, and performance compared to a framework like React. Working with simple templating languges helps to remind me the benefits of working with a framework like React.Chose Bootstrap 5 as the CSS framework to keep the UI simple and quick to build. Since the website takes a performance hit for loading Bootstrap, took full advantage of advanced Bootstrap features such as custom validation for all forms and animated form input for the login and register pages.</p>

        <p class="projects-body__paragraph-spacing-below"><span class="projects-body__bold-text">Controller</span>: Chose Node.js as the backend programming language for its rich ecosystem and community support. For example,leveraged PassportJs for the authentication and authorization since it's a common out-of-the-box solution. Create routes have authentication. Update, and Delete routes have authentication and authorization. Chose Express.js as the Node.js application framework since it's a lightweight framework, which is ideal for gaining an understanding of how to build the backend from scratch. Compared to a framework like Nest.js or even Django, Express.js doesn't have many features out of the box.</p>

        <h3>Database Schema</h3>
        <div>
          <img src="../img/YelpCamp-Database-Schema.drawio.svg" alt="YelpCamp Database Schema" class="projects-body__image--smaller projects-body__paragraph-spacing-below lax"></img>
        </div>

        <h3>Tests</h3>
        <p class="projects-body__paragraph-spacing-below">The integration tests using <a href="https://jestjs.io/" class="curriculum__link" target="_blank" rel="noopener noreferrer">Jest</a>. The test suite checks for the creation of data, the functionality of the schema, and the functionality of the validation. The tests are iterated over each of the models: campgrounds, comments, reviews, users. Integration-tests achieved 94% test coverage. Refactored code using automated code review tools such as Code Climate and Codacy to increase code quality grade from a ‘D’ to a ‘B’. Optimized performance, security, and accessibility using Google Lighthouse to increase score from 80 to 100</p>

        <h3>Production System Architecture</h3>
        <p class="projects-body__paragraph-spacing-below">Heroku as the cloud hosting provider to gain experience with PaaS. In November 2022, Heroku ended support of the free tier. When I <em>was</em> using the free tier, it caused the application to sleep after 30 minutes of inactivity, and I kept the application awake from 6:00 a.m. to 11:59 p.m. PST with <a href="https://kaffeine.herokuapp.com/" class="curriculum__link" target="_blank" rel="noopener noreferrer">Kaffeine</a>. Cloudflare as the Content Delivery Network to serve users outside of the U.S. with faster load times and for the free SSL certificate, which is needed for domain forwarding to https://www.yelpcamp.app. Cloudflare also offers improved security and performance over the defaults in Google Domains. Used CircleCI for Continuous Delivery and Deploymemnt and reduced the runtime by 50% through caching optimzations</p>

        <div>
          <img src="../img/YelpCamp-Production-Architecture.drawio.svg" alt="YelpCamp Production System Architecture Diagram" class="projects-body__image projects-body__paragraph-spacing-below lax"></img>
        </div>

        <h3>Production Scalability and Load limitations</h3>
        <p>The production server is hosted on Heroku Basic Dyno Tier, which has a limit of 512MB of RAM, no horizontal scaling, no autoscaling, and the server is not dedicated. If I needed to scale up due to an overloaded server, I would have to upgrade a Standard 1x Dyno for horizontal scaling. However, the web traffic has yet to reach a sustained usage of 50% server capacity. The production database is hosted on MongoDB Atlas Shared Plan M0 Cluster Tier, which has a limit of 512MB of storage. Considering that the current usage as of February 2023 is only 400KB, the website could expand up to 1280 times its current size. Given that the site went live in June of 2020, the current rate of data storage is 12.5KB/month. The database is the least likely bottleneck in this production system.</p>
      </section>

      <!-- PRODUCTION METRICS -->
      <section>
        <h2>Production System Cost</h2>
        <ul class="projects-body__list">
          <li>Heroku Basic Dyno Tier: $7/month</li>
          <li>MongoDB Atlas Shared Plan M0 Cluster Tier: free</li>
          <li>Cloudflare Free Tier: free</li>
          <li>Google Domain for yelpcamp.app: $14/year</li>
          <li>GitHub Free Tier: free</li>
        </ul>
        <h2 class="projects-body__heading">Production Metrics</h2>
        <ul class="projects-body__list">
          <li><span class="projects-body__bold-text">Traffic</span>: 800+ total website visits and 5000+ total pageviews since launch. Approximately 100 monthly active users (MAU) and 93 accounts created worldwide. Increased peak MAU by 400% and median MAU by 100%.</li>
          <li><span class="projects-body__bold-text">Search Engine Optimization (SEO)</span>: Achieved Google PageRank #8 for the search term “yelpcamp”</li>
          <li><span class="projects-body__bold-text">Site Reliability</span>: 70% uptime service-level indicator (SLI)</li>
          <li><span class="projects-body__bold-text">Security</span>: Mozzila Observatory</li>
          <li><span class="projects-body__bold-text">Performance</span>: from Google Lighthouse</li>
          <li><span class="projects-body__bold-text">Accessibility</span>: from Google Lighthouse</li>
          <li><span class="projects-body__bold-text">Cross-Browser Compatibility</span>: from LambdaTest</li>
        </ul>
      </section>

      <!-- LESSONS LEARNED -->
      <section>
        <h2 class="projects-body__heading">Lessons Learned</h2>
        <ul class="projects-body__list">
          <li>First full-stack web application</li>
          <li>Introduction to Express.js</li>
          <li>Introduction to MongoDB database design</li>
          <li>Introduction to Bootstrap</li>
          <li>Git for version control to learn version control</li>
          <li>Site is hosted on Heroku to learn how to deploy applications</li>
          <li>Optimizing performance, security, and accessibility using Google Lighthouse</li>
          <li>Integration testing with Jest</li>
          <li>Automating code review with Codacy and CodeClimate</li>
          <li>Continuous Integration and Continuous Deployment with CircleCI</li>
          <li>Deploying app to Heroku and Database to MongoDB Atlas</li>
          <li>Cloudflare as a Content Delivery Network in conjunction with custom Google Domain and Heroku</li>
          <li>Scalable Vector Graphic (SVG) illustration with Inkscape</li>
          <li>Gaining exposure to cloud-based IDE development using GoormIDE</li>
        </ul>
      </section>
    </div>

    <!-- FOOTER -->
    <footer class="footer">
      <p class="footer__fun-note">Made with<svg class="footer__icon"><use xlink:href="../img/sprite.svg#icon-heart"></use></svg>in SF</p>
      <p>Copyright &copy; <time id="date"></time> by Jacob Grisham</p>
    </footer>

  <!-- JAVASCRIPT -->
  <!-- Global site tag (gtag.js) - Google Analytics -->
  <script async src="https://www.googletagmanager.com/gtag/js?id=G-SV51NLJS21"></script>
  <script type="text/javascript" src="../js/common.js"></script>
  </body>
</html>