<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Node.js Archives - SoftUni Global</title>
	<atom:link href="https://softuni.org/tag/node-js/feed/" rel="self" type="application/rss+xml" />
	<link>https://softuni.org/tag/node-js/</link>
	<description>Learn Programming and Start a Developer Job</description>
	<lastBuildDate>Thu, 30 Jun 2022 12:06:56 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://softuni.org/wp-content/uploads/2022/04/cropped-SoftUni-Global-Logo-Square-notext-32x32.png</url>
	<title>Node.js Archives - SoftUni Global</title>
	<link>https://softuni.org/tag/node-js/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>URL Shortener Project &#8211; Adding Views, Layout + CSS Styling [Part 2]</title>
		<link>https://softuni.org/project-tutorials/url-shortener-project-adding-views-layout-css-styling/</link>
					<comments>https://softuni.org/project-tutorials/url-shortener-project-adding-views-layout-css-styling/#respond</comments>
		
		<dc:creator><![CDATA[Aleksandar Peev]]></dc:creator>
		<pubDate>Fri, 18 Feb 2022 06:00:00 +0000</pubDate>
				<category><![CDATA[Step-by-Step Project Tutorials]]></category>
		<category><![CDATA[control systems]]></category>
		<category><![CDATA[express]]></category>
		<category><![CDATA[Express.js]]></category>
		<category><![CDATA[Kanban Boards]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[node]]></category>
		<category><![CDATA[Node.js]]></category>
		<category><![CDATA[part 2]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[pug]]></category>
		<category><![CDATA[software development]]></category>
		<category><![CDATA[software engineering]]></category>
		<category><![CDATA[step-by-step]]></category>
		<guid isPermaLink="false">https://softuni.org/?p=12378</guid>

					<description><![CDATA[<p>In our second part of the URL Shortener series, we continue with developing our project. We will create all the views, CSS, and layout page for the project.</p>
<p>The post <a href="https://softuni.org/project-tutorials/url-shortener-project-adding-views-layout-css-styling/">URL Shortener Project &#8211; Adding Views, Layout + CSS Styling [Part 2]</a> appeared first on <a href="https://softuni.org">SoftUni Global</a>.</p>
]]></description>
										<content:encoded><![CDATA[		<div data-elementor-type="wp-post" data-elementor-id="12378" class="elementor elementor-12378" data-elementor-post-type="post">
						<section class="elementor-section elementor-top-section elementor-element elementor-element-5d5405e elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="5d5405e" data-element_type="section">
						<div class="elementor-container elementor-column-gap-default">
					<div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-0d32134" data-id="0d32134" data-element_type="column">
			<div class="elementor-widget-wrap elementor-element-populated">
						<div class="elementor-element elementor-element-9216798 elementor-widget elementor-widget-text-editor" data-id="9216798" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>In the <strong>second part</strong> of the tutorial, we will create the <strong>user interface</strong> for our web application. This will include all the <strong>views</strong>, <strong>CSS</strong>, and the <strong>layout page</strong>. If you haven&#8217;t read our previous <strong>blog post</strong>, where we created our project, you can do it from <a href="https://softuni.org/project-tutorials/url-shortener-project-creating-the-app-structure/">here</a>.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-b058b4f elementor-widget elementor-widget-text-editor" data-id="b058b4f" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>We start with building the <strong>layout page</strong>. It allows us to define a common <strong>site template</strong> that can be <strong>inherited</strong> in multiple <strong>views</strong> to provide a <strong>consistent look</strong> and feel in multiple pages of an application. The <strong>layout view</strong> eliminates <strong>duplicate coding</strong> and <strong>enhances development</strong> speed and easy maintenance.</p><ul><li>Inside the views folder, we create a <strong>layout.pug</strong>.</li></ul>								</div>
				</div>
				<div class="elementor-element elementor-element-e972c9d elementor-widget elementor-widget-heading" data-id="e972c9d" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h2 class="elementor-heading-title elementor-size-default">layout.pug</h2>				</div>
				</div>
				<div class="elementor-element elementor-element-2dd9888 elementor-widget elementor-widget-code-highlight" data-id="2dd9888" data-element_type="widget" data-widget_type="code-highlight.default">
				<div class="elementor-widget-container">
							<div class="prismjs-default copy-to-clipboard ">
			<pre data-line="" class="highlight-height language-javascript line-numbers">
				<code readonly="true" class="language-javascript">
					<xmp><!DOCTYPE html>
html(lang='en')
  head
    block head
    link(rel='stylesheet', href='/styles.css')
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
  body
    header
      a(href='/') Home
      span  | 
      a(href='/urls') Short URLs
      span  | 
      a(href='/add-url') Add URL

    main
      block content
    
    footer
      div © 2022 - URL Shortener</xmp>
				</code>
			</pre>
		</div>
						</div>
				</div>
				<div class="elementor-element elementor-element-dc9cfa9 elementor-widget elementor-widget-text-editor" data-id="dc9cfa9" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<ul><li>In the <strong>head section</strong>, we import the <strong>.css file</strong> that will include our styling. We will create it later inside the public folder.</li><li>For the body part, we have a <strong>header</strong> with the <strong>navigation</strong> of our application. Each <strong>anchor tag</strong> will lead us to another route.</li><li>In the main block is the <strong>block content</strong> that every time will re-render differently depending on our <strong>route</strong>.</li><li>We will create a <strong>styles.css</strong> in our <strong>public folder</strong> that we made in our previous part.</li></ul><div id="malwarebytes-root"> </div>								</div>
				</div>
				<div class="elementor-element elementor-element-7c67021 elementor-widget elementor-widget-heading" data-id="7c67021" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h2 class="elementor-heading-title elementor-size-default">styles.css</h2>				</div>
				</div>
				<div class="elementor-element elementor-element-76f3707 elementor-widget elementor-widget-code-highlight" data-id="76f3707" data-element_type="widget" data-widget_type="code-highlight.default">
				<div class="elementor-widget-container">
							<div class="prismjs-default copy-to-clipboard ">
			<pre data-line="" class="highlight-height language-css line-numbers">
				<code readonly="true" class="language-css">
					<xmp>body {
  font-family: Arial, Helvetica, sans-serif;
}

header, footer {
  background:rgb(212, 233, 164);
  padding: 8px;
  border-radius: 3px; 
}

footer {
  margin-top: 15px;
}

main {
  margin-left: 10px;
}


table {
  width: 100%;
  border-collapse: collapse;
  background-color: #f5fff5;
}

table th, table td {
  border: 1px solid #ddd;
}

table th {
  padding: 12px 8px;
  text-align: left;
  background-color: rgb(107, 182, 109);
  color: white;    
}

table td {
  padding: 8px;
  overflow-wrap: anywhere;
}

table tr:nth-child(even) {
  background-color: #dff0de;
}

table tr:hover {
  background-color: rgb(198, 207, 180);
}


form table {
  width: 100%;
  max-width: 600px;
}

form table td:nth-child(1) {
  width: 10%;
  white-space: nowrap;
}

main form input {
  width: 100%;
  min-width: 100px;
  box-sizing: border-box;
}
</xmp>
				</code>
			</pre>
		</div>
						</div>
				</div>
				<div class="elementor-element elementor-element-8d64e71 elementor-widget elementor-widget-text-editor" data-id="8d64e71" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<ul><li>If we want to add more pages, we need to set up the <strong>routes</strong> in our <strong>controller</strong>. As we did in the previous part, we create different <strong>functions</strong> for each  <strong>route</strong>. In the <strong>mvc-controller.js</strong>, we  will <strong>expand</strong> the <strong>functionality</strong> with new functions.</li></ul>								</div>
				</div>
				<div class="elementor-element elementor-element-c93bd3b elementor-widget elementor-widget-heading" data-id="c93bd3b" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h2 class="elementor-heading-title elementor-size-default">mvc-controller.js</h2>				</div>
				</div>
				<div class="elementor-element elementor-element-d243029 elementor-widget elementor-widget-code-highlight" data-id="d243029" data-element_type="widget" data-widget_type="code-highlight.default">
				<div class="elementor-widget-container">
							<div class="prismjs-default copy-to-clipboard ">
			<pre data-line="" class="highlight-height language-javascript line-numbers">
				<code readonly="true" class="language-javascript">
					<xmp>function setup(app, data) {
  app.get('/', function(req, res) {
        //  Same as before
  });

  app.get('/urls', function(req, res) {
    let model = { urls: data.urls };
    res.render('urls', model);
  });

  app.get('/add-url', function(req, res) {
    let model = { url: "", code: "newCode" };
    res.render('add-url', model);
  });

  app.post('/add-url', function(req, res) {
    res.redirect('/urls');
  });

}

function date2text(inputDate) {
  let date = inputDate.toISOString().split('.')[0];
  date = date.replace('T', ' ');
  return date;
}

module.exports = { setup };</xmp>
				</code>
			</pre>
		</div>
						</div>
				</div>
				<div class="elementor-element elementor-element-0b720f7 elementor-widget elementor-widget-text-editor" data-id="0b720f7" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<ul><li>With the <strong>first</strong> function, we will <strong>get</strong> the <strong>view</strong> with all the URLs. It will be the same as the home view functionality.</li><li>The <strong>second</strong> function will load the <strong>view</strong> for the create page. We will access it with the &#8220;<strong>/add-url</strong>&#8221; <strong>route</strong>.</li><li>The next <strong>third</strong> function will have the same <strong>route</strong> as the previous but with a <strong>different type</strong> of <strong>request</strong>. In the<em> app.get(&#8216;/add-url&#8217;, &#8230; )</em> we <strong>request</strong> the <strong>view</strong>, but with <em>app.post(&#8216;/add-url, &#8230;)</em> we will <strong>send data</strong> to the server. They are on the same <strong>route</strong>, but we <strong>send different types of requests</strong>.</li><li>We will add a helping function <strong>data2text()</strong> that will be outside of the <strong>setup()</strong> function. It will help us later.</li><li>What we need to do next is to <strong>create .pug</strong> view. First, we will add the <strong>urls.pug</strong> inside our <strong>views</strong> folder. We add the following <strong>code</strong> inside it:</li></ul>								</div>
				</div>
				<div class="elementor-element elementor-element-53a7244 elementor-widget elementor-widget-heading" data-id="53a7244" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h2 class="elementor-heading-title elementor-size-default">urls.pug</h2>				</div>
				</div>
				<div class="elementor-element elementor-element-f33f165 elementor-widget elementor-widget-code-highlight" data-id="f33f165" data-element_type="widget" data-widget_type="code-highlight.default">
				<div class="elementor-widget-container">
							<div class="prismjs-default copy-to-clipboard ">
			<pre data-line="" class="highlight-height language-javascript line-numbers">
				<code readonly="true" class="language-javascript">
					<xmp>extends layout.pug

block append head
  title='Short URLs'

block content
  h1 Short URLs
  table
    thead
      tr
        th Original URL
        th Short URL
        th Date Created
        th Visits
    tbody
      each url in urls
        tr
          td 
            a(href=`${url.url}` target="_blank") #{url.url}
          td
            a(href=`${url.shortUrl}` target="_blank") #{url.shortUrl}
          td #{url.dateCreated}
          td #{url.visits}</xmp>
				</code>
			</pre>
		</div>
						</div>
				</div>
				<div class="elementor-element elementor-element-bdfc1b3 elementor-widget elementor-widget-text-editor" data-id="bdfc1b3" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<ul><li>In this <strong>view</strong>, we will have an <strong>HTML</strong> <strong>table</strong> featuring all the records that we <strong>request</strong> from the server. They are bound to the <strong>urls</strong> variable. To <strong>access</strong> each element <strong>separately </strong>we need to <strong>iterate</strong> <strong>over</strong> the <strong>collection</strong> with a <strong>for-each loop</strong>. Each <strong>row</strong> will be with data for a <strong>specific record</strong>, and every cell with a value for a specific property of the object.</li></ul><p>If we <strong>start the project</strong> and go to the &#8216;<strong>/urls</strong>&#8216; <strong>route</strong>, this will visualize: </p>								</div>
				</div>
				<div class="elementor-element elementor-element-f63554d elementor-widget elementor-widget-text-editor" data-id="f63554d" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p><img fetchpriority="high" decoding="async" class="wp-image-12426 aligncenter" src="https://softuni.org/wp-content/uploads/2022/02/urls-view-300x119.png" alt="urls-view" width="487" height="193" srcset="https://softuni.org/wp-content/uploads/2022/02/urls-view-300x119.png 300w, https://softuni.org/wp-content/uploads/2022/02/urls-view-1024x405.png 1024w, https://softuni.org/wp-content/uploads/2022/02/urls-view-768x304.png 768w, https://softuni.org/wp-content/uploads/2022/02/urls-view-600x237.png 600w, https://softuni.org/wp-content/uploads/2022/02/urls-view.png 1186w" sizes="(max-width: 487px) 100vw, 487px" /></p>								</div>
				</div>
				<div class="elementor-element elementor-element-eccb188 elementor-widget elementor-widget-text-editor" data-id="eccb188" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<ul><li>In next part we will add the <strong>add-url.pug</strong> <strong>view</strong>. We add it inside the <strong>views</strong> folder.</li></ul>								</div>
				</div>
				<div class="elementor-element elementor-element-ff025eb elementor-widget elementor-widget-heading" data-id="ff025eb" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h2 class="elementor-heading-title elementor-size-default">add-url.pug</h2>				</div>
				</div>
				<div class="elementor-element elementor-element-0190a15 elementor-widget elementor-widget-code-highlight" data-id="0190a15" data-element_type="widget" data-widget_type="code-highlight.default">
				<div class="elementor-widget-container">
							<div class="prismjs-default copy-to-clipboard ">
			<pre data-line="" class="highlight-height language-javascript line-numbers">
				<code readonly="true" class="language-javascript">
					<xmp>extends layout.pug

block append head
  title='Add Short URL'

block content
  h1 Add Short URL
  form(method='POST' action='/add-url')
    table
      tr
        td
          label(for='url') URL: 
        td
          input#url(type='text', name='url', value=`${url}`)
      tr
        td
          label(for='code') Short Code: 
        td
          input#code(type='text', name='code', value=`${code}`)
      tr
        td(colspan="2")
          button(type='submit') Create</xmp>
				</code>
			</pre>
		</div>
						</div>
				</div>
				<div class="elementor-element elementor-element-abdff4c elementor-widget elementor-widget-text-editor" data-id="abdff4c" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<ul><li>In this <strong>view</strong>, we add a <strong>form</strong> that is with a <strong>POST</strong> <strong>method</strong>, and an <strong>action</strong> points to &#8216;<strong>/add-url</strong>&#8216;. To explain what this does, after pressing the <strong>submit button</strong>, the server will request the <em>app.post(&#8216;/add-url&#8217;, &#8230;)</em> function that we have typed inside our mvc-controller.  In the next parts, we will add the <strong>functionality</strong> that <strong>saves</strong> the <strong>record inside</strong> the <strong>database</strong>.</li><li>Inside the <strong>form</strong>, we have two <strong>input fields</strong>. Inside each <strong>field</strong>, the <strong>user</strong> will type the values for the <strong>URL</strong> he needs to <strong>create</strong>.</li><li>In the end, it is important for the button to be of type <strong>submit</strong>. This will <strong>submit</strong> the form to the <strong>server</strong>.</li></ul><p>If you have done everything correctly, going to the &#8216;<strong>/add-urls</strong>&#8216; route will display you this page:</p>								</div>
				</div>
				<div class="elementor-element elementor-element-c99c30e elementor-widget elementor-widget-text-editor" data-id="c99c30e" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p><img decoding="async" class=" wp-image-12427 aligncenter" src="https://softuni.org/wp-content/uploads/2022/02/add-url-view-300x228.png" alt="add-url-view" width="335" height="254" srcset="https://softuni.org/wp-content/uploads/2022/02/add-url-view-300x228.png 300w, https://softuni.org/wp-content/uploads/2022/02/add-url-view.png 531w" sizes="(max-width: 335px) 100vw, 335px" /></p>								</div>
				</div>
				<div class="elementor-element elementor-element-d810adb elementor-widget elementor-widget-text-editor" data-id="d810adb" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>After completing all the steps, your project will have a <strong>user interface</strong> that supports different <strong>types of screens</strong>. If we go to our two new routes &#8216;<strong>/urls</strong>&#8216;, and &#8216;<strong>/add-urls</strong>&#8216; you will access the two new pages that we have added. On the &#8216;<strong>/add-urls</strong>&#8216; route, if you <strong>submit</strong> the form with the required data, you will send a <strong>POST request</strong> to the <strong>server</strong>. In the next parts, we will be able to save this information on the <strong>server</strong> and display it inside the &#8216;<strong>/urls</strong>&#8216; <strong>route</strong>.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-88292b4 elementor-widget elementor-widget-video" data-id="88292b4" data-element_type="widget" data-settings="{&quot;youtube_url&quot;:&quot;https:\/\/youtu.be\/4jOZhNaJAl4&quot;,&quot;video_type&quot;:&quot;youtube&quot;,&quot;controls&quot;:&quot;yes&quot;}" data-widget_type="video.default">
				<div class="elementor-widget-container">
							<div class="elementor-wrapper elementor-open-inline">
			<div class="elementor-video"></div>		</div>
						</div>
				</div>
				<div class="elementor-element elementor-element-edfdd22 elementor-widget elementor-widget-text-editor" data-id="edfdd22" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<h2>Lesson Topics</h2><div><div><div>In this tutorial we cover the following topics:</div></div><ul><li><strong>Building the Layout Template in Pug</strong></li><li><strong>Adding CSS Styles</strong></li><li><strong>Implementing the &#8220;View Short URLs Table&#8221;</strong></li><li><strong>Styling the Table</strong></li><li><strong>Implementing the &#8220;Add URL&#8221; Form</strong></li><li><strong>CSS Styling for Small Screens</strong></li></ul></div>								</div>
				</div>
					</div>
		</div>
					</div>
		</section>
				<section class="elementor-section elementor-top-section elementor-element elementor-element-564ddaf elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="564ddaf" data-element_type="section">
						<div class="elementor-container elementor-column-gap-default">
					<div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-03f3f8d" data-id="03f3f8d" data-element_type="column">
			<div class="elementor-widget-wrap elementor-element-populated">
							</div>
		</div>
					</div>
		</section>
				<section class="elementor-section elementor-top-section elementor-element elementor-element-a0aff0b elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="a0aff0b" data-element_type="section">
						<div class="elementor-container elementor-column-gap-default">
					<div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-48c6c18" data-id="48c6c18" data-element_type="column">
			<div class="elementor-widget-wrap elementor-element-populated">
						<div class="elementor-element elementor-element-1495bc9 elementor-align-center elementor-widget elementor-widget-button" data-id="1495bc9" data-element_type="widget" data-widget_type="button.default">
				<div class="elementor-widget-container">
									<div class="elementor-button-wrapper">
					<a class="elementor-button elementor-button-link elementor-size-xl" href="https://replit.com/@nakov/URLShortener-Part-2">
						<span class="elementor-button-content-wrapper">
						<span class="elementor-button-icon">
				<svg aria-hidden="true" class="e-font-icon-svg e-fas-angle-right" viewBox="0 0 256 512" xmlns="http://www.w3.org/2000/svg"><path d="M224.3 273l-136 136c-9.4 9.4-24.6 9.4-33.9 0l-22.6-22.6c-9.4-9.4-9.4-24.6 0-33.9l96.4-96.4-96.4-96.4c-9.4-9.4-9.4-24.6 0-33.9L54.3 103c9.4-9.4 24.6-9.4 33.9 0l136 136c9.5 9.4 9.5 24.6.1 34z"></path></svg>			</span>
									<span class="elementor-button-text">Source code Part 2</span>
					</span>
					</a>
				</div>
								</div>
				</div>
				<div class="elementor-element elementor-element-f972417 elementor-widget elementor-widget-heading" data-id="f972417" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h2 class="elementor-heading-title elementor-size-default">Lesson Slides</h2>				</div>
				</div>
				<div class="elementor-element elementor-element-37e6760 elementor-widget elementor-widget-pdfjs_viewer" data-id="37e6760" data-element_type="widget" data-widget_type="pdfjs_viewer.default">
				<div class="elementor-widget-container">
					<iframe src="https://softuni.org/wp-content/plugins/pdf-viewer-for-elementor/assets/pdfjs/web/viewer.html?file=https://softuni.org/wp-content/uploads/2022/02/ShortURL-Project-Tutorial-Part-2-App-UI.pdf&amp;embedded=true" style="display: block; margin-left: auto; margin-right: auto; width: 100%; height: 800px;" frameborder="1" marginheight="0px" marginwidth="0px" allowfullscreen></iframe>				</div>
				</div>
					</div>
		</div>
					</div>
		</section>
				</div>
		<p>The post <a href="https://softuni.org/project-tutorials/url-shortener-project-adding-views-layout-css-styling/">URL Shortener Project &#8211; Adding Views, Layout + CSS Styling [Part 2]</a> appeared first on <a href="https://softuni.org">SoftUni Global</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://softuni.org/project-tutorials/url-shortener-project-adding-views-layout-css-styling/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>URL Shortener Project &#8211; Creating the App Structure [Part 1]</title>
		<link>https://softuni.org/project-tutorials/url-shortener-project-creating-the-app-structure/</link>
					<comments>https://softuni.org/project-tutorials/url-shortener-project-creating-the-app-structure/#respond</comments>
		
		<dc:creator><![CDATA[Aleksandar Peev]]></dc:creator>
		<pubDate>Thu, 10 Feb 2022 06:00:00 +0000</pubDate>
				<category><![CDATA[Step-by-Step Project Tutorials]]></category>
		<category><![CDATA[control systems]]></category>
		<category><![CDATA[express]]></category>
		<category><![CDATA[Express.js]]></category>
		<category><![CDATA[Kanban Boards]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[node]]></category>
		<category><![CDATA[Node.js]]></category>
		<category><![CDATA[part 1]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[pug]]></category>
		<category><![CDATA[software development]]></category>
		<category><![CDATA[software engineering]]></category>
		<category><![CDATA[step-by-step]]></category>
		<guid isPermaLink="false">https://softuni.org/?p=12280</guid>

					<description><![CDATA[<p>In this article of the Project Tutorial series, we will create a simple URL Shortener, using JavaScript, Node.js, Express.js and Pug</p>
<p>The post <a href="https://softuni.org/project-tutorials/url-shortener-project-creating-the-app-structure/">URL Shortener Project &#8211; Creating the App Structure [Part 1]</a> appeared first on <a href="https://softuni.org">SoftUni Global</a>.</p>
]]></description>
										<content:encoded><![CDATA[		<div data-elementor-type="wp-post" data-elementor-id="12280" class="elementor elementor-12280" data-elementor-post-type="post">
						<section class="elementor-section elementor-top-section elementor-element elementor-element-5d5405e elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="5d5405e" data-element_type="section">
						<div class="elementor-container elementor-column-gap-default">
					<div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-0d32134" data-id="0d32134" data-element_type="column">
			<div class="elementor-widget-wrap elementor-element-populated">
						<div class="elementor-element elementor-element-9216798 elementor-widget elementor-widget-text-editor" data-id="9216798" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>In this tutorial, we will create our <strong>URL Shortener</strong> using <strong>JavaScript</strong>. We will be using <strong>Expres.JS</strong> for creating the <strong>server-side web application</strong> and <strong>Pug</strong> as a <strong>template engine</strong>. This tutorial will be split into several parts, and in each part, we will further develop our project. In the end, we will have a fully working <strong>Multi Page Application</strong> (<strong>MPA</strong>).</p><p>After we <strong>initialize</strong> our project, we need to split our <strong>code logic</strong> into different folders. We create folders for:</p><ul><li><strong>data</strong></li><li><strong>controllers</strong></li><li><strong>views</strong></li><li><strong>public</strong></li></ul><p>In our main directory we have an <strong>index.js</strong> file that is automatically generated by <strong>repl.it</strong>. <span data-preserver-spaces="true">You don&#8217;t need to install manually any </span><strong><span data-preserver-spaces="true">libraries</span></strong><span data-preserver-spaces="true"> because they will be added </span><strong><span data-preserver-spaces="true">automatically</span></strong><span data-preserver-spaces="true"> when you start the project.</span></p><p>First, in our <strong>index.js</strong> we need to add the following code:</p><div id="malwarebytes-root"> </div>								</div>
				</div>
				<div class="elementor-element elementor-element-e972c9d elementor-widget elementor-widget-heading" data-id="e972c9d" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h2 class="elementor-heading-title elementor-size-default">index.js</h2>				</div>
				</div>
				<div class="elementor-element elementor-element-2dd9888 elementor-widget elementor-widget-code-highlight" data-id="2dd9888" data-element_type="widget" data-widget_type="code-highlight.default">
				<div class="elementor-widget-container">
							<div class="prismjs-default copy-to-clipboard ">
			<pre data-line="" class="highlight-height language-javascript line-numbers">
				<code readonly="true" class="language-javascript">
					<xmp>const express = require('express');
const app = express();
app.use(express.static('public'))
app.set('view engine', 'pug');

const data = require("./data/app-data");
data.seedSampleData();

const mvcController = require(
  "./controllers/mvc-controller");
mvcController.setup(app, data);

let port = process.argv[2];
if (!port) port = process.env['PORT'];
if (!port) port = 8080;

app.listen(port, () => {
  console.log(`App started. Listening at http://localhost:${port}`);
})
.on('error', function(err) {
  if (err.errno === 'EADDRINUSE')
    console.error(`Port ${port} busy.`);
  else 
    throw err;
});</xmp>
				</code>
			</pre>
		</div>
						</div>
				</div>
				<div class="elementor-element elementor-element-dc9cfa9 elementor-widget elementor-widget-text-editor" data-id="dc9cfa9" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<ul><li><span data-preserver-spaces="true">In the first row, we </span><strong><span data-preserver-spaces="true">import</span></strong><span data-preserver-spaces="true"> the <strong>E</strong></span><strong><span data-preserver-spaces="true">xpressJS</span></strong><span data-preserver-spaces="true"> </span><strong><span data-preserver-spaces="true">node module</span></strong><span data-preserver-spaces="true">. Then we bind it to a </span><strong><span data-preserver-spaces="true">constant</span></strong><span data-preserver-spaces="true"> and use it to make </span><strong><span data-preserver-spaces="true">static</span></strong><span data-preserver-spaces="true"> our public folder. Doing this will allow us to use the <strong>public</strong> folder from any part of our application.</span></li><li><span data-preserver-spaces="true">We will also set our </span><strong><span data-preserver-spaces="true">view engine</span></strong><span data-preserver-spaces="true"> to </span><strong><span data-preserver-spaces="true">pug</span></strong><span data-preserver-spaces="true">. This will render all <strong>.pug</strong> files we set as <strong>views</strong>.</span></li><li><span data-preserver-spaces="true">We define constant named <strong>data</strong> and invoke the function. <strong>seedSampleData()</strong> inside it. We will create them later. Every time our project is started this function will be <strong>initialized</strong>.</span></li><li><span data-preserver-spaces="true">Our next task is to tell the index.js that our <strong>MVC-controller</strong> exists and set up it.</span></li><li><span data-preserver-spaces="true">We set our virtual port for repl.it to <strong>8080</strong>, and tell the program to listen to this <strong>port</strong>.</span></li><li><span data-preserver-spaces="true">If there is an <strong>error</strong>, it will be automatically <strong>displayed</strong> on the server&#8217;s console.</span></li></ul><div id="malwarebytes-root"></div>								</div>
				</div>
				<div class="elementor-element elementor-element-1ddcbde elementor-widget elementor-widget-heading" data-id="1ddcbde" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h2 class="elementor-heading-title elementor-size-default">app-data.js</h2>				</div>
				</div>
				<div class="elementor-element elementor-element-8747339 elementor-widget elementor-widget-code-highlight" data-id="8747339" data-element_type="widget" data-widget_type="code-highlight.default">
				<div class="elementor-widget-container">
							<div class="prismjs-default copy-to-clipboard ">
			<pre data-line="" class="highlight-height language-javascript line-numbers">
				<code readonly="true" class="language-javascript">
					<xmp>let urls = [];

function seedSampleData() {
  urls.length = 0; // cleanup
  urls.push({
    url: "https://softuni.org",
    shortCode: "su",
    dateCreated: new Date("2022-02-19T16:41:56"),
    visits: 86
  });
  urls.push({
    url: "https://nakov.com",
    shortCode: "nak", 
    dateCreated: new Date("2022-02-17T14:41:33"), 
    visits: 160
  });
}

module.exports = {
  urls,
  seedSampleData
};</xmp>
				</code>
			</pre>
		</div>
						</div>
				</div>
				<div class="elementor-element elementor-element-4c6a3fa elementor-widget elementor-widget-text-editor" data-id="4c6a3fa" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<ul><li>In our <strong>data</strong> folder we create an <strong>app-data.js</strong> file. In it is we create our <strong>seed</strong> of <strong>data</strong>. We add an <strong>empty array</strong> that we fill with the <strong>seedSampleData()</strong> function.</li><li>In our function we have 2 different <strong>objects {}</strong> that we push into the <strong>urls</strong> array.</li><li>This is a <strong>temporary solution</strong> and in our next parts will be changed with a <strong>real database</strong>.</li></ul><div id="malwarebytes-root"></div>								</div>
				</div>
				<div class="elementor-element elementor-element-34726c4 elementor-widget elementor-widget-heading" data-id="34726c4" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h2 class="elementor-heading-title elementor-size-default">mvc-controller.js</h2>				</div>
				</div>
				<div class="elementor-element elementor-element-4054f70 elementor-widget elementor-widget-code-highlight" data-id="4054f70" data-element_type="widget" data-widget_type="code-highlight.default">
				<div class="elementor-widget-container">
							<div class="prismjs-default copy-to-clipboard ">
			<pre data-line="" class="highlight-height language-javascript line-numbers">
				<code readonly="true" class="language-javascript">
					<xmp>function setup(app, data) {
  app.get('/', function(req, res) {
    let visitors = 0;
    for (const url of data.urls) {
      console.log(url);
      visitors += url.visits;
    }
    let model = { urls: data.urls, visitors };
    res.render('home', model);
  });
}

module.exports = { setup };</xmp>
				</code>
			</pre>
		</div>
						</div>
				</div>
				<div class="elementor-element elementor-element-a842882 elementor-widget elementor-widget-text-editor" data-id="a842882" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<ul><li><span data-preserver-spaces="true">Inside our <strong>controller</strong> folder we create the  <strong>mvc-controller.js</strong> file. Inside it, we add the function </span><strong><span data-preserver-spaces="true">setup()</span></strong><span data-preserver-spaces="true"> that receives the <strong>app</strong> and <strong>data</strong>. </span></li><li><span data-preserver-spaces="true">When our server recieves a <strong>GET</strong> request with a <strong>URL</strong> that equals<strong> &#8216;/&#8217;</strong>, it will <strong>invoke</strong> the following function.</span></li><li><span data-preserver-spaces="true"> We <strong>iterate</strong> over the <strong>collection of data</strong> and bind it into the <strong>model </strong>variable. </span></li><li><span data-preserver-spaces="true">Then, we <strong>render</strong> the following view with the <strong>data</strong> attached to it. </span></li><li><span data-preserver-spaces="true">After we are done, we <strong>export</strong> the function so that the <strong>index.js</strong> can run it correctly.</span></li></ul>								</div>
				</div>
				<div class="elementor-element elementor-element-3c39e95 elementor-widget elementor-widget-heading" data-id="3c39e95" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h2 class="elementor-heading-title elementor-size-default">home.pug</h2>				</div>
				</div>
				<div class="elementor-element elementor-element-d245384 elementor-widget elementor-widget-code-highlight" data-id="d245384" data-element_type="widget" data-widget_type="code-highlight.default">
				<div class="elementor-widget-container">
							<div class="prismjs-default copy-to-clipboard ">
			<pre data-line="" class="highlight-height language-javascript line-numbers">
				<code readonly="true" class="language-javascript">
					<xmp>h1 URL Shortener
ul
  li Short URLs: <b>#{urls.length}</b>
  li URL visitors: <b>#{visitors}</b>    </xmp>
				</code>
			</pre>
		</div>
						</div>
				</div>
				<div class="elementor-element elementor-element-b1c3462 elementor-widget elementor-widget-text-editor" data-id="b1c3462" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<ul><li><span data-preserver-spaces="true">Finally, we create our <strong>home.pug</strong> view inside the <strong>views</strong> folder. That is the html <strong>page</strong> that will load when the user goes to the </span>&#8216;/&#8217; <span data-preserver-spaces="true"><strong>URL, that we </strong>defined in our controller.</span></li><li><span data-preserver-spaces="true">We have an <strong>unordered list( ul )</strong>, in which we have two <strong>rows( li )</strong>. The first is for the count of our <strong>URLs</strong>, and the next is the total sum of all visitors summed from all<strong> 2 records</strong>.</span></li><li><span data-preserver-spaces="true">If we want to print the data <strong>bound</strong> to the variable </span><strong><span data-preserver-spaces="true">visitors</span></strong><span data-preserver-spaces="true">, we must add hashtag <strong>#</strong> and braces<strong> { }</strong> around it so that our compiler knows that this isn&#8217;t a regular <strong>HTML</strong> text.</span></li></ul><div id="malwarebytes-root"></div>								</div>
				</div>
				<div class="elementor-element elementor-element-74febac elementor-widget elementor-widget-text-editor" data-id="74febac" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p><img decoding="async" class=" wp-image-12324 aligncenter" src="https://softuni.org/wp-content/uploads/2022/02/url-first-part-final-look-300x157.png" alt="url-first-part-final-look" width="332" height="174" srcset="https://softuni.org/wp-content/uploads/2022/02/url-first-part-final-look-300x157.png 300w, https://softuni.org/wp-content/uploads/2022/02/url-first-part-final-look.png 469w" sizes="(max-width: 332px) 100vw, 332px" />After completing all the steps you will have a simple working <strong>Multi Page Application</strong>. If you start your project, you will see that everything that we have done is working correctly. We are using the <strong>MVC architecture</strong>, and we have split the project into different folders and functions for better understanding. This way  you can clearly see where each part is located. Keep up with our parts and see how our project grows more.</p><div id="malwarebytes-root"></div>								</div>
				</div>
				<div class="elementor-element elementor-element-88292b4 elementor-widget elementor-widget-video" data-id="88292b4" data-element_type="widget" data-settings="{&quot;youtube_url&quot;:&quot;https:\/\/youtu.be\/P7-tvKIOwVs&quot;,&quot;video_type&quot;:&quot;youtube&quot;,&quot;controls&quot;:&quot;yes&quot;}" data-widget_type="video.default">
				<div class="elementor-widget-container">
							<div class="elementor-wrapper elementor-open-inline">
			<div class="elementor-video"></div>		</div>
						</div>
				</div>
				<div class="elementor-element elementor-element-edfdd22 elementor-widget elementor-widget-text-editor" data-id="edfdd22" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<h2>Lesson Topics</h2><div><div><div>In this tutorial we cover the following topics:</div></div><ul><li><strong>URL Shortener: App Walkthrough</strong></li><li><strong>Project Structure</strong></li><li><strong>Creating the App Structure</strong></li></ul></div>								</div>
				</div>
				<div class="elementor-element elementor-element-9fe4d6c elementor-widget elementor-widget-text-editor" data-id="9fe4d6c" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p style="text-align: left;">Remember that <strong>coding is a skill</strong>, which should be practiced. To learn to code, you should <strong>write code</strong> every day for a long time. Watching tutorials is not enough. <strong>You should code! </strong></p><p style="text-align: left;">We would love to hear from you, so leave a comment below saying what topics you would like to see next.</p><p style="text-align: left;">Register now and take your <strong>free resources</strong> right away! Become a member of the <strong>SoftUni Global Community </strong>and communicate with other <strong>students</strong> and <strong>mentors </strong>and get help for <strong>FREE</strong>.</p><p>After registering, you will get access to thе<strong> project code.</strong></p>								</div>
				</div>
					</div>
		</div>
					</div>
		</section>
				<section class="elementor-section elementor-top-section elementor-element elementor-element-187b057 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="187b057" data-element_type="section">
						<div class="elementor-container elementor-column-gap-default">
					<div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-a666564" data-id="a666564" data-element_type="column">
			<div class="elementor-widget-wrap elementor-element-populated">
							</div>
		</div>
					</div>
		</section>
				<section class="elementor-section elementor-top-section elementor-element elementor-element-a0aff0b elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="a0aff0b" data-element_type="section">
						<div class="elementor-container elementor-column-gap-default">
					<div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-48c6c18" data-id="48c6c18" data-element_type="column">
			<div class="elementor-widget-wrap elementor-element-populated">
						<div class="elementor-element elementor-element-1495bc9 elementor-align-center elementor-widget elementor-widget-button" data-id="1495bc9" data-element_type="widget" data-widget_type="button.default">
				<div class="elementor-widget-container">
									<div class="elementor-button-wrapper">
					<a class="elementor-button elementor-button-link elementor-size-xl" href="https://replit.com/@nakov/URLShortener-Part-1?v=1">
						<span class="elementor-button-content-wrapper">
									<span class="elementor-button-text">Source code Part 1</span>
					</span>
					</a>
				</div>
								</div>
				</div>
				<div class="elementor-element elementor-element-f972417 elementor-widget elementor-widget-heading" data-id="f972417" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h2 class="elementor-heading-title elementor-size-default">Lesson Slides</h2>				</div>
				</div>
				<div class="elementor-element elementor-element-37e6760 elementor-widget elementor-widget-pdfjs_viewer" data-id="37e6760" data-element_type="widget" data-widget_type="pdfjs_viewer.default">
				<div class="elementor-widget-container">
					<iframe src="https://softuni.org/wp-content/plugins/pdf-viewer-for-elementor/assets/pdfjs/web/viewer.html?file=https://softuni.org/wp-content/uploads/2022/02/ShortURL-Project-Tutorial-Part-1-App-Structure.pdf&amp;embedded=true" style="display: block; margin-left: auto; margin-right: auto; width: 100%; height: 800px;" frameborder="1" marginheight="0px" marginwidth="0px" allowfullscreen></iframe>				</div>
				</div>
					</div>
		</div>
					</div>
		</section>
				</div>
		<p>The post <a href="https://softuni.org/project-tutorials/url-shortener-project-creating-the-app-structure/">URL Shortener Project &#8211; Creating the App Structure [Part 1]</a> appeared first on <a href="https://softuni.org">SoftUni Global</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://softuni.org/project-tutorials/url-shortener-project-creating-the-app-structure/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/?utm_source=w3tc&utm_medium=footer_comment&utm_campaign=free_plugin

Page Caching using Disk: Enhanced 
Lazy Loading (feed)

Served from: softuni.org @ 2026-04-10 01:27:33 by W3 Total Cache
-->