One place for hosting & domains

      How To Build and Deploy a Flask Application Using Docker on Ubuntu 18.04


      O autor selecionou a Tech Education Fund para receber uma doação como parte do programa Write for DOnations.

      Introdução

      O Docker é um aplicativo de código aberto que permite que os administradores criem, gerenciem, implantem e repliquem aplicativos usando contêineres. Os contêineres podem ser considerados como um pacote que abriga dependências que um aplicativo precisa para executar no nível do sistema operacional. Isso significa que cada aplicativo implantado usando o Docker vive em um ambiente próprio e seus requisitos são tratados separadamente.

      O Flask é um microframework Web que é construído em Python. Ele é chamado de microframework porque não precisa de ferramentas específicas ou plugins para funcionar. O framework Flask é leve e flexível e, ainda sim, altamente estruturado, tornando-o preferido em relação a outros frameworks.

      Implantar um aplicativo Flask com o Docker permitirá que você replique o aplicativo em diferentes servidores com uma reconfiguração mínima.

      Neste tutorial, você criará um aplicativo Flask e irá implantá-lo com o Docker. Este tutorial também irá tratar sobre como atualizar um aplicativo após a implantação.

      Pré-requisitos

      Para seguir este tutorial, você precisará do seguinte:

      Passo 1 — Configurando o aplicativo Flask

      Para começar, você criará uma estrutura de diretórios que irá reter seu aplicativo Flask. Neste tutorial será criado um diretório chamado TestApp em /var/www, mas é possível modificar o comando para nomeá-lo como quiser.

      • sudo mkdir /var/www/TestApp

      Vá até o diretório TestApp recém-criado:

      Em seguida, crie a estrutura base da pasta para o aplicativo Flask:

      • sudo mkdir -p app/static app/templates

      A sinalização -p indica que o mkdir criará um diretório e todos os diretórios pais que não existam. Neste caso, o mkdir criará o diretório pai app enquanto cria os diretórios static e templates.

      O diretório app abrigará todos os arquivos relacionados ao aplicativo Flask como suas visualizações e blueprints (planos gráficos). As visualizações são o código que você escreve para responder aos pedidos para seu aplicativo. Os Blueprints criam componentes do aplicativo e oferecem suporte aos padrões comuns dentro de um aplicativo ou de vários aplicativos.

      O diretório static é onde estão os ativos como imagens, CSS e arquivos JavaScript. O diretório templates é onde você irá colocar os modelos HTML do seu projeto.

      Agora que a estrutura base de pasta está completa, crie os arquivos necessários para executar o aplicativo Flask. Primeiro, crie um arquivo __init__.py dentro do diretório app. Esse arquivo informa o programa interpretador do Python que o diretório app é um pacote e deve ser tratado como tal.

      Execute o comando a seguir para criar o arquivo:

      • sudo nano app/__init__.py

      Os pacotes no Python permitem que você agrupe os módulos em namespaces ou hierarquisas lógicos. Esta abordagem permite que o código seja dividido em blocos individuais e gerenciáveis que desempenham funções específicas.

      Em seguida, adicione código ao __init__.py que criará uma instância de Flask e importará a lógica do arquivo views.py, que você criará após salvar este arquivo. Adicione o código a seguir ao seu novo arquivo:

      /var/www/TestApp/__init__.py

      from flask import Flask
      app = Flask(__name__)
      from app import views
      

      Uma vez adicionado tal código, salve e feche o arquivo.

      Com o arquivo __init__.py criado, está tudo pronto para criar o arquivo views.py no diretório app. Este arquivo conterá a maior parte da lógica do seu aplicativo.

      Em seguida, adicione o código ao seu arquivo views.py. Esse código retornará a string hello world! para os usuários que visitarem sua Web page:

      /var/www/TestApp/app/views.py

      from app import app
      
      @app.route('/')
      def home():
         return "hello world!"
      

      A linha @app.route acima da função é chamada de decorador. Os decoradores modificam a função que as segue. Neste caso, os decoradores avisam ao Flask qual URL irá desencadear a função home(). O texto hello world retornado pela função home será exibido para o usuário no navegador.

      Com o arquivo views.py funcionando, estamos prontos para criar o arquivo uwsgi.ini. O arquivo terá as configurações uWSGI para o nosso aplicativo. A uWSGI é uma opção de implantação do Nginx que é um protocolo e um servidor do aplicativo ao mesmo tempo; o servidor do aplicativo pode atender os protocolos uWSGI, FastCGI e HTTP.

      Para criar esse arquivo, execute o seguinte comando:

      Em seguida, adicione o conteúdo seguinte ao seu arquivo para, assim, configurar o servidor do uWSGI:

      /var/www/TestApp/uwsgi.ini

      [uwsgi]
      module = main
      callable = app
      master = true
      

      Este código define o módulo que irá servir o aplicativo Flask. Neste caso, trata-se do arquivo main.py, referenciado aqui como main. A opção callable manda o uWSGI usar a instância app exportada pelo aplicativo principal. A opção master permite que seu aplicativo permaneça funcionando, de modo a reduzir o tempo de paralisação ao recarregar o aplicativo inteiro.

      Em seguida, crie o arquivo main.py, que é o ponto de entrada para o aplicativo. O ponto de entrada diz ao uWSGI como interagir com o aplicativo.

      Em seguida, copie e cole o seguinte no arquivo. Este código irá importar a instância Flask chamada app do pacote do aplicativo que foi criado anteriormente.

      /var/www/TestApp/main.py

      from app import app
      

      Por fim, crie um arquivo requirements.txt para especificar as dependências que o gerenciador de pacotes pip instalará para sua implantação do Docker:

      • sudo nano requirements.txt

      Adicione a seguinte linha para adicionar o Flask como uma dependência:

      /var/www/TestApp/app/requirements.txt

      Flask==1.0.2
      

      Isso especifica a versão do Flask a ser instalada. No momento em que este tutorial está sendo escrito, a versão 1.0.2 é a versão do Flask mais recente. Você pode verificar as atualizações no site oficial do Flask.

      Salve e feche o arquivo. Você configurou o aplicativo Flask com sucesso e está pronto para configurar o Docker.

      Passo 2 — Configurando o Docker

      Neste passo, serão criados dois arquivos, o Dockerfile e o start.sh, para criar sua implantação do Docker. O Dockerfile é um documento de texto que contém os comandos usados para montar a imagem. O arquivo start.sh é um script shell que irá construir uma imagem e criará um contêiner do Dockerfile.

      Primeiramente, crie o Dockerfile.

      Em seguida, adicione a configuração desejada ao Dockerfile. Estes comandos especificam como a imagem será construída e quais requisitos extras serão incluídos.

      /var/www/TestApp/Dockerfile

      FROM tiangolo/uwsgi-nginx-flask:python3.6-alpine3.7
      RUN apk --update add bash nano
      ENV STATIC_URL /static
      ENV STATIC_PATH /var/www/app/static
      COPY ./requirements.txt /var/www/requirements.txt
      RUN pip install -r /var/www/requirements.txt
      

      Neste exemplo, a imagem do Docker será construída a partir de uma imagem existente, a tiangolo/uwsgi-nginx-flask, que pode ser encontrada no DockerHub. Esta imagem do Docker em particular é uma boa escolha dentre as outras pois ela oferece suporte a uma ampla gama de versões do Python e imagens de SO.

      As duas primeiras linhas especificam a imagem pai que será usada para executar o aplicativo e instalar o processador de comando bash, assim como o editor de texto nano. O aplicativo também irá instalar o cliente git para extração e envio para as plataformas de hospedagem com controle de versão tais como GitHub, GitLab e Bitbucket. A ENV STATIC_URL/static é uma variável de ambiente específica para essa imagem do Docker. Ela define a pasta estática onde todos os ativos como imagens, arquivos CSS e arquivos JavaScript são atendidos.

      As duas últimas linhas irão copiar o arquivo requirements.txt para o contêiner, de modo a que ele possa ser executado e, em seguida, analisar o arquivo requirements.txt para instalar as dependências especificadas.

      Salve e feche o arquivo após adicionar sua configuração.

      Com seu Dockerfile funcionando, está quase tudo pronto para escrever seu script start.sh que construirá o contêiner do Docker. Antes de escrever o script start.sh, certifique-se primeiro de que você tenha uma porta aberta para usar na configuração. Para verificar se uma porta está livre, execute o seguinte comando:

      • sudo nc localhost 56733 < /dev/null; echo $?

      Se o resultado do comando acima for 1, então a porta está livre e pode ser usada. Caso contrário, será necessário escolher uma porta diferente para usar no seu arquivo de configuração start.sh.

      Assim que você tiver encontrado uma porta aberta para usar, crie o script start.sh:

      O script start.sh é um script shell que irá construir uma imagem do Dockerfile e criar um contêiner a partir da imagem do Docker resultante. Adicione sua configuração ao novo arquivo:

      /var/www/TestApp/start.sh

      #!/bin/bash
      app="docker.test"
      docker build -t ${app} .
      docker run -d -p 56733:80 
        --name=${app} 
        -v $PWD:/app ${app}
      

      A primeira linha é chamada de shebang. Ela especifica que este é um arquivo bash e ele será executado como comando. A linha seguinte especifica o nome que você quer dar à imagem e ao contêiner e salva o arquivo como uma variável chamada app. A próxima linha de comando manda o Docker construir uma imagem a partir do seu Dockerfile, localizado no diretório atual. Neste exemplo, a linha de código criará uma imagem chamada docker.test.

      As três últimas linhas criam um novo contêiner chamado docker.test que está exposto na porta 56733. Por fim, ele vincula o diretório atual ao diretório /var/www do contêiner.

      Você usará o sinalizador -d para iniciar um contêiner no modo daemon ou para iniciar como um processo em segundo plano. Incluirá o sinalizador -p para vincular uma porta no servidor a uma porta em particular no contêiner do Docker. Neste caso, você está ligando a porta 56733 à porta 80 no contêiner do Docker. O sinalizador -v especifica um volume do Docker para ser montado no contêiner e, neste caso, você estará montando o diretório de projeto inteiro na pasta /var/www no contêiner do Docker.

      Execute o script start.sh para criar a imagem do Docker e construir um contêiner a partir da imagem resultante:

      Assim que o script terminar de executar, use o comando a seguir para listar todos os contêineres em execução:

      Você receberá um resultado que mostra os contêineres:

      Output

      CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 58b05508f4dd docker.test "/entrypoint.sh /sta…" 12 seconds ago Up 3 seconds 443/tcp, 0.0.0.0:56733->80/tcp docker.test

      Você verá que o contêiner docker.test está em execução. Agora que ele está em execução, acesse o endereço IP na porta especificada no seu navegador: http://ip-address:56733

      Você verá uma página parecida com a que segue:

      A página principal

      Neste passo, seu aplicativo Flask foi implementado no Docker com sucesso. Em seguida, você usará modelos para mostrar o conteúdo aos usuários.

      Passo 3 — Servindo arquivos de modelos

      Os modelos são arquivos que mostram o conteúdo estático e dinâmico aos usuários que visitam seu aplicativo. Neste passo, você criará um modelo HTML para criar uma página inicial para o aplicativo.

      Comece criando um arquivo home.html no diretório app/template:

      • sudo nano app/templates/home.html

      Adicione o código ao seu template. Este código irá criar uma página HTML5 que contém um título e algum texto nele.

      /var/www/TestApp/app/templates/home.html

      
      <!doctype html>
      
      <html lang="en-us">   
        <head>
          <meta charset="utf-8">
          <meta http-equiv="x-ua-compatible" content="ie=edge">
          <title>Welcome home</title>
        </head>
      
        <body>
          <h1>Home Page</h1>
          <p>This is the home page of our application.</p>
        </body> 
      </html>
      

      Salve e feche o arquivo assim que tiver adicionado o seu modelo.

      Em seguida, modifique o arquivo app/views.py para atender o arquivo recém-criado:

      Primeiramente, adicione a seguinte linha no início do seu arquivo para importar o método render_template do Flask. Este método analisa um arquivo HTML para renderizar uma página da Web para o usuário.

      /var/www/TestApp/app/views.py

      from flask import render_template
      ...
      

      No final do arquivo, você também irá adicionar uma nova rota para renderizar o arquivo do modelo. Este código especifica que os usuários recebem o conteúdo do arquivo home.html sempre que visitam a rota /template em seu aplicativo.

      /var/www/TestApp/app/views.py

      ...
      
      @app.route('/template')
      def template():
          return render_template('home.html')
      

      O arquivo atualizado app/views.py se parecerá com isto:

      /var/www/TestApp/app/views.py

      from flask import render_template
      from app import app 
      
      @app.route('/')
      def home():
          return "Hello world!"
      
      @app.route('/template')
      def template():
          return render_template('home.html')
      

      Salve e feche o arquivo quando terminar.

      Para que estas alterações passar a vigorar, será necessário parar e reiniciar os contêineres do Docker. Execute o comando a seguir para criar o contêiner novamente:

      • sudo docker stop docker.test && sudo docker start docker.test

      Visite seu aplicativo em http://your-ip-address:56733/template para ver o novo modelo sendo mostrado.

      homepage

      Neste passo, você criou um arquivo modelo do Docker para atender os visitantes em seu aplicativo. No próximo passo, você verá como as alterações que você faz em seu aplicativo podem entrar em vigor sem a necessidade de reiniciar o contêiner do Docker.

      Passo 4 — Atualizando o aplicativo

      Às vezes, você terá que fazer alterações no aplicativo, seja instalando novos requisitos, atualizando o contêiner do Docker ou do HTML e as alterações de lógica. Nesta seção, você irá configurar o touch-reload para fazer essas alterações sem precisar reiniciar o contêiner do Docker.

      O autoreloading do Python monitora todo o sistema de arquivos quanto a alterações e atualiza o aplicativo quando detecta uma mudança. Desencorajamos o uso do autoreloading em produção porque ele pode se tornar um recurso intensivo rapidamente. Neste passo, você usará o touch-reload para monitorar as alterações em um arquivo em particular e recarregar quando o arquivo for atualizado ou substituído.

      Para implementar isso, abra seu arquivo uwsgi.ini:

      Em seguida, adicione a linha destacada ao final do arquivo:

      /var/www/TestApp/uwsgi.ini

      module = main
      callable = app
      master = true
      touch-reload = /app/uwsgi.ini
      

      Ela especifica um arquivo que será modificado para desencadear o recarregamento de um aplicativo inteiro. Uma vez feitas as mudanças, salve e feche o arquivo.

      Como uma demonstração, faça uma pequena alteração no seu aplicativo. Comece abrindo seu arquivo app/views.py:

      Substitua a string retornada pela função home:

      /var/www/TestApp/app/views.py

      from flask import render_template
      from app import app
      
      @app.route('/')
      def home():
          return "<b>There has been a change</b>"
      
      @app.route('/template')
      def template():
          return render_template('home.html')
      

      Salve e feche o arquivo após fazer uma mudança.

      Em seguida, se abrir a página inicial do seu aplicativo em http://ip-address:56733, você verá que as mudanças não estão refletidas. Isso acontece porque a condição para que o recarregamento ocorra é uma alteração feita ao arquivo uwsgi.ini. Para recarregar o aplicativo,utilize a opção touch para ativar a condição:

      Recarregue a homepage do aplicativo em seu navegador novamente. Você verá que o aplicativo incorporou as mudanças:

      Pagina inicial atualizada

      Neste passo, você configurou uma condição touch-reload para atualizar seu aplicativo após fazer alterações.

      Conclusão

      Neste tutorial, você criou e implantou um aplicativo Flask em um contêiner do Docker. Você também configurou o touch-reload para atualizar seu aplicativo sem a necessidade de reiniciar o contêiner.

      Com o seu novo aplicativo em Docker, agora é possível dimensionar com facilidade. Para aprender mais sobre como usar o Docker, verifique sua documentação oficial.



      Source link

      Want to Build a Website in 2020? Here’s Your Game Plan


      Feeling committed to making this year better than the last? You’ve probably got your personal goals all set for the new year: read more books, call your mom, eat less pizza, walk off that holiday pie.

      How’s this for a New Year’s Resolution: Build a successful website from the ground up. Sounds like a lofty goal, but trust us, kid — you’ve got the makings of a champion.

      via GIPHY

      Building an online presence is like running a marathon. Those exhausting 26.2 miles require long-time endurance built over months of training. Marathoners train one step at a time and complete one mile at a time.

      This guide is your training plan. 

      As your trusty web host and coach, we’re here to keep you on track as you build, grow, secure, and promote your new site. We’ve broken this website workout plan into goals and tasks to complete each quarter throughout 2020, but feel free to work at your own pace. You do the sweating, and we’ll be right beside you with step-by-step instructions, water cups, and cheese-tastic motivational signs.

      1. Build Your Website 
      2. Grow Your Website
      3. Secure Your Website
      4. Promote Your Website

      Sound good? Then tie up your Nikes, pull on your gym shorts, and let’s get to work.

      First Quarter: Build Your Website

      Step 1: Decide on Your Mission

      Ready to race right off the starting block into building your website? We love the enthusiasm. But before even reaching the starting line, you need to get in some warm-ups and conditioning to establish a solid foundation. Every good website begins with a thoughtful plan. Open a fresh new digital doc (or grab a pen and paper if you’d prefer to go old school) and complete the following exercises.

      Find Your Purpose

      Why do you want a website in the first place? What do you hope it will accomplish? Ask yourself, “What is the purpose of this website?”

      The possibilities are endless — but you need to spell out what you want and who your target audience is. Write down what you decide; you’ll use this purpose to guide everything else you do this year.

      Set Goals

      Time to dive deeper into the reflecting and set some specific goals for your website. Grab your pen (or ready your typing fingers) and, below your website’s purpose, jot down a few goals. There are lots of options.

      • Site revenue
      • Site Traffic
      • More customers in your physical store
      • More followers on social media platforms
      • Number of business contacts or leads from your site

      These goals should accomplish your website’s purpose and drive the rest of your plans.

      Don’t lose sight of your finish line — and don’t be afraid to adjust your goals over the coming months.

      Outline Your Content

      You probably shouldn’t bake a cake without a recipe. Likewise, you can’t build your website until you know what components you need to make it a success. So go ahead and outline your content to make sure you hit your goals. Consider these components:

      • Start with your website’s menu. What should its offerings include? And in what order? Rank what’s most important to you — and your goals — at the top.
      • Do you want to include a blog? This will be helpful for search engine optimization (SEO) — more on that in a minute — encourage engagement and community, build your reputation,  and establish you as an expert. If the blog is the cornerstone of your site, take some time to outline (or, for overachievers, write) your first few posts and plan some topics you might write about over the next year.
      • The “About Me” page is your place to tell your story and describe your business. Don’t skip out on this chance to connect with your customers.
      • Do you need a spot to describe the products or services you’re selling, either online or in your physical store? If your objective is to drum up business directly from the web page, this is essential. Think about categories and subcategories of products, and consider how you might describe or sell them to your website visitors.
      • What is included on the homepage? Your contact information? Maybe, although that could easily be its own page. A memorable photo? Definitely. Another homepage must-have? A call to action (CTA). Your CTA should invite visitors to do something: check out your offerings, sign up for your newsletter, or delve into your blog.

      Step 2: Choose a Domain and Platform

      Ready. Get set. We are inching closer to launching your website, but before we can get going, it first needs a name and a place to live.

      Pick a Domain Name

      Basically, a domain is what you type into the bar at the top of your browser to point to a specific website. For example, to find us a DreamHost, you type in dreamhost.com. A domain consists of two parts:

      1. The top-level domain (TLD) — In dreamhost.com, the “.com” part is our TLD. The more common TLDs include .com, .net, .org, .info. You can even choose something jazzier, like one of the new TLDs: .party, .site, .pizza, .limo, .store, and more. At least for now, though, .com is still the most common TLD.
      2. The second-level domain (SLD) — In our domain name, that’s “dreamhost.” This is the keyword that will serve as the address for your website. Make sure it is specific, descriptive, and memorable so that customers can easily find and remember it.

      Jot down a dream domain and see if it is available for purchase. If you can’t find (or afford) your first-choice domain name, we’ll help you find other great options.

      Pick a Hosting Plan

      If your domain name is your website’s address, hosting is the physical space (spoiler: a server) where your website lives. The hosting plan you choose for your website will impact many things — like how fast your site loads and what kind of maintenance you have to do.

      DreamHost offers several great options to cover a variety of web hosting needs (not that we are biased about this at all, ahem).

      For beginners, we recommend shared hosting. It is affordable, fast, and meets the needs of any basic website (and includes a free domain registration!). You can always upgrade as your website grows.

      Shared Hosting That Powers Your Purpose

      We make sure your website is fast, secure and always up so your visitors trust you. Plans start at $2.59/mo.

      Choose a Platform

      To build your website, you’ll need to pick a platform — and there’s no content management system (CMS) better, in our opinion, than WordPress. And 75 million websites agree with us. Like any powerful tool, there is a learning curve to WordPress, but the open-source software is free to use and pretty beginner-friendly.

      Step 3: Design and Launch

      OK — with a set of goals, a content outline, a domain, web hosting, and a platform picked for your new website, it is finally time to get building!

      Build Your WordPress Website

      Head over to DreamHost’s WordPress hosting page, pick the plan that’s right for you, install WordPress, configure your settings, and start building your website. Pull out the list of goals and content outline you made in step one, and use it to guide you in choosing a theme that matches your brand.

      Learn About Web Design Trends and Best Practices

      No, you don’t need to become an expert overnight. And never fear: those WordPress themes we just mentioned are beautiful and will save you from major design blunders. But here are a few basic pointers to keep in mind as you get started in designing your site.

        1. Keep things quick and straightforward — From homepage copy to navigation options, think short and sweet.
        2. Don’t fear the blank space — Don’t feel the need to fill every nook and cranny; elegant emptiness can go a long way.
        3. Keep your menu front and center — Keep it easy to find or risk losing visitors.
        4. Mind your typographyWhat you say matters as much as how you say it — and what it looks like.
        5. Pick a color scheme that matches your brand — Color communicates, so pick ones that fit the ethos of your website.
        6. Make it accessible — Expand your audience by making sure your website is usable by everyone, including individuals with disabilities.
        7. Use templates — When you sign up for a DreamHost plan, you’ll have the option to include WP Website Builder with your account. This tool makes it easy to use customizable and professional templates to design a beautiful, fully functional WordPress website. To prove just how versatile this tool is, we put together a tutorial series that demonstrates how you can use WP Website Builder templates to start fitness blogs, food blogs, photography blogs, real estate websites, and restaurant sites (to name a few)!

      If you lack the skills (or time to learn the skills) to design a website — and have some wiggle room in your budget — consider hiring a professional designer to help you customize your site’s look.

      Launch!

      Go ahead. Send your website out into the world. Take a quick victory lap — you’ve earned it! But don’t lose your momentum; the work has only started.

      Second Quarter: Grow Your Website

      So now you have a website. Yay!

      Time to beef it up with some strength training. That’s right. Once your site is up and running, turn your attention to attracting more visitors and bringing in some income.

      Step 4: Monetize Your Site

      Ready to bring in the big bucks with a blog or online store? Let’s get you set up.

      • Review your offerings — Take a look at the products and services you are selling. Is there anything else you can add, especially to entice back past customers? Have you thought about adding an online course or premium for-pay content to your blog?
      • Add some ads — Include a bit of subtle, tasteful advertising on your WordPress blog to bring in some additional revenue.

      • Affiliate marketing — Incorporating affiliate links on your blog or website is another way to add to your revenue stream. Basically, you’ll promote another brand’s product and provide links to their site. If your readers click and make a purchase, you’ll get a cut of the sale in thanks for your referral.
      • Investigate e-commerce solutions — How are you planning to sell and accept payment on your website? You’ll need to get that squared away before promoting your online store. If you’re using WordPress, we recommend Woocommerce (so much so, that we’ve even got hosting just for Woocommerce users). Study up on the world of e-commerce and pick an online payment gateway (watch out for sneaky transaction fees).

      Step 5: Adopt SEO Best Practices

      Once your site is built and prepped to be monetized, you are ready to reel in the traffic with SEO.

      SEO is a group of strategies website owners can (and should!) use to appear closer to the top of the results on search engines.

      Think about it: when you search for something on Google, you probably only scan the first few entries before clicking — and so will your clients. Since Google bases its results ranking on a variety of factors, it’s essential to do the following:

      • Brainstorm keywords relevant to your site — What search phrases do you think (or hope) would most likely lead readers to your website? Use Google’s Keyword Planner to research and discover new keywords.
      • Optimize your blog posts — Plan content around these keywords and make sure to use them in your posts and headings — but be careful and creative with your placement to avoid creating content that sounds forced. If you need help getting started, check out these SEO tools.
      • Keep it fresh — Regular updates and new content will give you a search-ranking boost. But don’t be afraid to freshen up and repurpose old content.
      • Create a sitemap — Sitemaps, which are basically a hierarchical list of all the pages and content on your site, help Google’s search engine crawlers see and connect the pages on your site, making it easier to present relevant information in search results.

      Step 6: Take Care of the Details

      Now that your site has been up and running for a while, it’s time for some spring cleaning. Let’s make sure your website is up to par and easy to access for all your potential customers.

      Clean and Polish

      Start with a few routine upkeep tasks, and set reminders to do them again in another six months:

      • Check for broken links.
      • Review and edit website copy and high-traffic blog posts.
      • Update contact information and your “About Me” section.
      • Test functionality of forms and checkout.
      • Think about your user experience. How can you make it better?
      • Review your hosting plan — are you ready for an upgrade?

      Go Mobile

      Take a look at how your site looks on the small screen. If your website isn’t optimized for mobile — that is, if it doesn’t look as good and load as fast on mobile devices as it does on a computer — you’re missing out. Responsive design matters in 2020.

      Many potential customers use phones or tablets in place of a home computer, and some shop on the go. Plus, your Google search rankings could hurt if your website isn’t mobile-friendly. Pull your website up on your smartphone, and make any necessary changes.

      Review Your Traffic

      If you haven’t already, install Google Analytics onto your WordPress website. Google Analytics is a plugin that tracks and analyzes key data about your website, including:

      • Page views — At a glance, this stat will reveal your most popular pages and posts in the past day, month, and year.
      • Unique visitors — Using IP addresses, Google Analytics will track how many unique visitors your site attracts.
      • Bounce rate — Sometimes visitors will click away from your site after viewing only one page; this stat will let you know how often that dreaded “bounce” happens.
      • Session duration — When someone visits your site, how long do they stick around? Check this number for the answer.
      • Traffic source — You might suddenly see an increase in traffic to a particular page, and Google Analytics will help you pinpoint what link is sending the visitors.

      Studying these statistics will help you find changes to make to draw more visitors and encourage them to stay longer (and hopefully make a purchase).

      Third Quarter: Secure Your Website

      Time to work on endurance: You want your website to stick around for the long haul. Now it’s time to beef up your security practices and protect your data.

      Step 7: Tighten Website Security

      When it comes to security, you can rest easy at night: you’re already on the right track to keeping your information and customer’s data safe with WordPress and DreamHost. But there are a few additional steps you can take to tighten up security.

      • Switch to HTTPS — The “S” in HTTPS stands for “secure,” and it is (surprise) the more secure version of HTTP, encrypting your data as it is transferred from your website to a user’s browser. Add that all-important “S” by getting an SSL/TLS certificate (offered for free with all DreamHost hosting plans).
      • Enable a firewall — You probably have a firewall on your computer, protecting you from unwanted attacks. And, if you’re one of our customers, lucky you: DreamHost includes a built-in Web Application Firewall (WAF) to offer your website similar protection.
      • Use two-factor authentication — This will require you to sign in to your site with a code that’s first sent to your mobile phone. While it can be a bit of a hassle on your end, this step goes a long way in keeping your site secure. Use a WordPress plugin like Two-Factor Authentication.
      • Add an SSL security certificate — At DreamHost, we want you and your website’s users to feel confident about their data and financial transactions. We also want you to be able to focus on building your website’s following — that’s why we offer SSL/TLS certificates free with all of our hosting plans!
      • Backup your site — Hackers gonna hack. Even with all your efforts to secure your site, security breaches and other disasters are still a possibility. So make sure to regularly backup your website. That way, if the unthinkable happens, you won’t lose all of your digital property.
      • Scan for malware — Hackers can really mess things up for your website by installing malware, which can mess with the code and steal secure data. Scan your site regularly to make sure it’s clean. DreamHost customers can sign up for DreamShield, an add-on that will automatically scan your site for malware.
      • Pick a strong password — Don’t make it easy for just anyone to walk into your digital front door; choose a password that is long, uncommon, and used only for your website.

      Step 8: Speed Things Up

      Nothing is more of a drag than a sluggish website. Keep your website up to speed by:

      • Installing a caching plugin for faster load times — The “cache” is where your computer stores recently used information, such as the files of a recently visited website. A caching WordPress plugin pulls data from the local cache instead of reloading it fully every time, thus speeding things up.
      • Optimizing your images — High-res photos can take an extra-long hot second to load, but there’s no need to sacrifice quality.
      • Testing your speed — Even if it seems like your page is loading normally, get in the habit of regularly testing your speed. Simply type your URL into Google’s PageSpeed insights for a quick analysis and tips to get a faster score.

      Step 9: Prepare for Trolls

      By the time you’ve reached this step, you’ve probably got fans. But as your site builds a community, it will also attract some of the slimier creatures lurking in the anonymity of the web: spammers, trolls, and cruel commentators. Keep these thoughts in mind as you deal with the underbelly of the web:

      • Don’t feed the trolls — This is rule No. 1 when it comes to trolls. Don’t engage; it will just feed the fire.
      • Understand the difference between trolling and disagreement — Not everyone who disagrees with you is a troll; usually, they are legitimate readers with a different viewpoint. Feel free to defend yourself and your arguments, and be open to changing your mind — and reminding aggressive commenters to play nice.
      • Establish a commenting policy — Spell out for your readers how you expect them to behave, what the consequences are for violations, and make clear that trolls are not invited to the party.
      • Block or delete — If a trolling post gets too out of hand, don’t be afraid to step in and shut it down.

      Fourth Quarter: Promote Your Website

      Congratulations! You’re officially three-quarters of the way through this marathon [splashes water on face]. Don’t lose that momentum; continue strong and steady to the finish line. Think of all the orange slices awaiting you. To get there, your next task is promotion.

      Step 10: Advertise

      You’ve got a great thing going, and it’s time to tell the world. Advertising, even for the beginner website owner, is a no-brainer that can be simple, effective, and affordable. Try your hand at two basic types of targeted advertising:

      Pay-Per-Click Advertising

      A good SEO strategy will organically move you to the top of the search results. With Pay-Per-Click (PPC) ads, you’ll take matters more into your own hands by paying to land atop the search engine result pages (SERPs). The best part? You only have to pay for premium placement if someone clicks on your link. You choose the keywords you want to bring up your ad, and you can set and limit your own budget.

      Social Media Advertising

      Facebook is a well-oiled, data-collecting machine, and you can use its power to target advertising directly to your ideal audience. You can create a Facebook ad that reaches users based on specific info such as age, gender, interests, etc. As with Google Adwords, you’ll set a budget and pay for clicks. Get on Instagram and leverage your feed and stories for some great free advertising for your brand. Follow this guide to narrow down which social media platform you should use for your business.

      Step 11: Market with Email

      Email is one of the best tools your e-commerce site has for finding new customers, bringing back previous ones, and maintaining relationships.

      Learn the Basics

      Study up on email marketing, a tried-and-true marketing method that involves collecting email addresses as a way to share content and build relationships with current and potential customers.

      Collect Email Addresses

      You can’t send any mail if you don’t know where it’s going. But don’t be spammy and shady about it; create opt-in forms directly on your site inviting visitors to subscribe. Try offering something in exchange for an email address, such as a discount off a first purchase or access to a free ebook.

      Create an Email Newsletter

      Email newsletters remain one of the best ways to connect with your customers, so create one and make it the center of your email marketing strategy. Use it as a way to showcase your voice and your brand, share news and upcoming events for your business, and introduce new products (but don’t be too pushy). Send it out regularly, loaded with fresh content, and then solicit feedback.

      Be Awesome on the Internet

      Join our monthly newsletter for tips and tricks to build your dream website!

      Bring Your Customers Back

      Beyond a newsletter, what other types of emails will engage your customers? Always send purchase receipts and make sure to welcome new subscribers. Consider reaching out to past customers to announce sales, share discounts, and invite them back to the fold.

      Step 12: Get Creative

      Now that you’ve covered your bases with advertising and email marketing, dig deeper and get a little creative in extending your website’s reach. Try out these promotion ideas:

      You’ve made it to the finish line! You’ve worked hard, and your website is certainly one to be proud of. Now, hit the showers, champ.

      And if you haven’t launched your site yet, we’re here for you. Start off on the right foot with DreamHost’s shared hosting plan. It’s the most affordable way to make all your website dreams come true — seriously, plans start at just $2.59/month — without sacrificing quality and performance. Create your website today!



      Source link

      How To Build an Inspirational Quote Application Using AdonisJs and MySQL


      The author selected the Tech Education Fund to receive a donation as part of the Write for DOnations program.

      Introduction

      AdonisJs is a Node.js web framework written in plain JavaScript that runs on all major operating systems. It uses the popular MVC (Model – View – Controller) design pattern and offers a stable ecosystem for writing server-side web applications. The framework features seamless authentication, SQL ORM (object-relational mapping), migrations, and database seeding. AdonisJs has a similar architecture to the PHP web application framework Laravel, including the same folder structure and several shared setup concepts.

      By default, AdonisJs uses the Edge template engine that is designed for intuitive use. Just like Laravel, AdonisJs ships with an ORM called Lucid that serves as an interface for communication between an application’s models and the database. With AdonisJs, developers can build a full-stack application where the back-end server will be responsible for applying the business logic, routing, and rendering all the pages for the application. It is also possible to create a web service API to return JSON responses from a controller; these web services can then be consumed using front-end frameworks such as Vue.js, React, and Angular.

      In this tutorial, you’ll build an application with AdonisJs using its CLI. You’ll create routes, controllers, models, and views within your application and you’ll carry out form validations. The example in this tutorial will be an inspirational quote application in which a user can sign up and log in to create an inspirational quote. This demo application will give you the opportunity to carry out CRUD (Create, Read, Update, and Delete) operations.

      Prerequisites

      Before you begin this guide, you will need the following:

      Note: This tutorial uses a macOS machine for development. If you’re using another operating system, you may need to use sudo for npm commands in the first steps.

      Step 1 — Installing the Adonis CLI

      In this section, you will install Adonis CLI and all its required packages on your local machine. The CLI will allow you to scaffold a new AdonisJs project as well as create and generate boilerplate for controllers, middlewares, and models in your application. You’ll also create your database for the project.

      Run the following command to install the AdonisJs CLI globally on your machine via npm:

      Once the installation process is complete, type the following command in the terminal to confirm the installation of AdonisJs and view the current version:

      You will see output showing the current version of AdonisJs:

      Output

      4.1.0

      With the successful installation of the AdonisJs CLI, you now have access to and can use the adonis command to create fresh installations of an AdonisJs project, manage your project, and generate relevant files such as the controllers, models, etc.

      Now, you can proceed to create a new AdonisJs project by using the adonis command as shown here:

      • adonis new adonis-quotes-app

      The preceding command will create an application named adonis-quotes-app in a new directory with the same name in your local project directory with the relevant AdonisJs MVC structure.

      Move into the new application folder:

      Then start your application by running:

      This will start the development server on the default port 3333 as specified inside the root .env file for your application. Navigate to http://localhost:3333 to view the welcome page of AdonisJs.

      Welcome page of AdonisJs

      Now you’ll complete the setup of your database. Here, you’ll install the mysql driver to connect to your MySQL server from your Node.js application via npm. To begin, go back to your terminal where the application is currently running, stop the process with CTRL + C and run the following command:

      Now that you have successfully installed the MySQL Node.js driver for this application, you need to create the application database and set up the appropriate connection to it.

      The latest version of MySQL that you have installed from the prerequisite tutorial uses a default authentication plugin named caching_sha2_password. This is currently not supported by Node.js drivers for MySQL. To avoid any database connection issue from your application, you will need to create a new MySQL user and use the currently supported authentication plugin—mysql_native_password.

      To begin, access the MySQL client using the root account:

      You will be prompted to enter your root account password set up during the MySQL installation.

      Next, create the user and password using the mysql_native_password plugin:

      • CREATE USER 'sammy'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';

      You will see the following output:

      Output

      Query OK, 0 rows affected (0.02 sec)

      Next, create a database for the application with:

      You will see the following output:

      Output

      Query OK, 1 row affected (0.03 sec)

      You’ve now successfully created the database for this application.

      Now, enable access to the created database for the new MySQL user. Run the following command to grant all privileges to the user in the database:

      • GRANT ALL PRIVILEGES ON adonis.* TO 'sammy'@'localhost';

      Reload the grant tables by running the following command to apply the changes that you just made:

      You will see the following output:

      Output

      Query OK, 0 rows affected (0.00 sec)

      Exit the MySQL client with:

      You’ve successfully installed the AdonisJs CLI, created a new AdonisJs project, and installed mysql via npm. You also created the database for this application and set up a MySQL user with the appropriate privileges to it. This is the basic setup for your application and in the next section you will begin to create the necessary views for your application.

      Step 2 — Using the Edge Templating Engine

      AdonisJs is shipped with its own template engine called Edge. It allows you to create a reusable HTML template and enables the introduction of front-end logic into your application with minimal code. Edge provides JavaScript developers with the tools while developing an application to build a component-based layout, write conditionals, use iterations, and create view layers to hold logic. All template files end with the .edge extension and are stored in the resources/views directory.

      The following are the views that your application will need to function properly:

      • Master Layout: With Edge, you can create a page that will contain the CSS, common JavaScript files, jQuery, and common parts of the user interface that will stay the same throughout the application—for example, the navigation bar, logo, header, etc. Once you’ve established the Master Layout page, other views (pages) in your application will inherit it.
      • Index view: This page will use the master layout to inherit common files and will also render contents for the homepage of the application.
      • Login page: This page will also use the master layout and render the form with the input fields for both username and password for users to log in.
      • Register page: Here, users will see a form to register and have their details persisted into the database.
      • Create quote page: Users will use this page to create an inspirational quote.
      • Edit quote page: Users will use this page to edit a quote.
      • View quote page: Users will use this page to view a particular quote.

      To begin, use the adonis command to create the master layout page by running the following command:

      • adonis make:view layouts/master

      You’ll see output similar to the following:

      Output

      ✔ create resources/views/layouts/master.edge

      This command will automatically create a master.edge file in your resources/views/layouts folder. Open the new file:

      • nano resources/views/layouts/master.edge

      Add the following code in it:

      /resources/views/layouts/master.edge

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <meta http-equiv="X-UA-Compatible" content="ie=edge">
          <title>adonis-quotes-app</title>
          {{ style('https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css') }}
          {{ style('style') }}
          {{ script('https://code.jquery.com/jquery-3.3.1.slim.min.js') }}
      </head>
      <body>
          <div class="container-fliud">
              @include('navbar')
              @!section('content')
          </div>
          {{ script('https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js') }}
      
      </body>
      </html>
      

      In this file, you include the CDN files for Bootstrap CSS, Bootstrap JavaScript, and jQuery. You add a global CSS file name of style.css and within the div you include a partial file named navbar. To reuse fragments of HTML code that you require across multiple pages in your application, like nav or footer, you can incorporate partials. These are smaller files containing the repeated code making it quicker to update code for these elements in one place rather than at every instance it occurs. The navbar contains markup for a Login and Register buttons, a logo, and a home link.

      With this in place, all the subsequent pages that will be created for this application can extend the master layout and have the navbar rendered without the need to write the content all over again. You’ll create this navbar file later in the tutorial.

      Finally, you define a section tag @!section() to include content from other pages and have them rendered by the master layout. For this to work as expected, all the new pages that will extend the master layout must also define a section tag with the same name (i.e., @section('content')).

      Save and exit the file once you’re finished editing it.

      Next, you will use the adonis command to create the navigation bar:

      You’ll see output similar to:

      Output

      ✔ create resources/views/navbar.edge

      Open the newly created file:

      • nano resources/views/navbar.edge

      Then add the following code to it:

      /resources/views/navbar.edge

      <nav class="navbar navbar-expand-lg navbar-dark text-white">
          <a class="navbar-brand" >LOGO</a>
          <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
              <span class="navbar-toggler-icon"></span>
          </button>
      
          <div class="collapse navbar-collapse" id="navbarNav">
              <ul class="navbar-nav">
                  <li class="nav-item active ">
                      <a class="btn text-white" href="/">Home</a>
                  </li>
              </ul>
          </div>
          <div class="navbar-right" id="navbarNav">
              @loggedIn
                  <ul class="navbar-nav">
                          <li>
                              <div class="text-right">
                                   <a href="{{route('create.quote')}}" class="btn btn-outline-primary">Create Quote</a>
                              </div>
                          </li>
      
                      <li class="nav-item dropdown">
                          <a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                             {{ auth.user.username}}
                          </a>
                          <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
                              <form method="POST" action="{{route('logout')}}">
                                  {{ csrfField() }}
                                    <button  type="submit" class="dropdown-item" href="">logout</button>
                              </form>
                          </div>
                      </li>
                  </ul>
              @else
                  <ul class="navbar-nav">
                      <li class="nav-item active pr-2">
                          <a href="{{route('login.create')}}" class="btn btn-outline-danger">
                            login
                          </a>
                      </li>
                      <li class="nav-item active pr-2">
                          <a href="{{route('register.create')}}" class="btn btn-outline-primary">
                              Register
                          </a>
                      </li>
                  </ul>
              @endloggedIn
          </div>
      </nav>
      

      In addition to defining the links to the homepage and a button to register and login, you add a @loggedIn tag. With this in place you can write a conditional statement around the authenticated user and display appropriate contents where necessary. For an authenticated user, the application will display their username and a button to create a new quote. If a user is not logged in, your application will display a button to either log in or register. This page will be included as a partial on every page as it was earlier in the master layout for this application.

      Save and exit the file.

      Now, you’ll create the index page that you’ll use for the application’s homepage. It will render and display the list of all inspirational quotes that users write:

      You will see an output similar to the following:

      Output

      ✔ create resources/views/index.edge

      The file created here will be located in resources/views/index.edge. Open the file:

      • nano resources/views/index.edge

      Then add the following code:

      /resources/views/index.edge

      @layout('layouts/master')
      @section('content')
      
      <div class="container">
          <div class="text-center">
              @if(flashMessage('successmessage'))
                  <span class="alert alert-success p-1">{{ flashMessage('successmessage') }}</span>
              @endif
          </div>
          <div class="row">
              @each(quote in quotes)
                  <div class="col-md-4 mb-4 quote-wrapper">
                      <a href="http://www.digitalocean.com/view-quote/{{quote.id}}" class="w-100">
                          <div class="card shadow-lg bg-dark text-white">
                              <div class="card-body">
                                  <blockquote class="blockquote mb-0">
                                      <p>{{quote.body}}</p>
                                      <footer class="blockquote-footer">
                                          <cite title="Source Title"> {{quote.username}}</cite>
                                      </footer>
                                  </blockquote>
                                  @if(auth.user.id == quote.user_id)
                                    <div>
                                      <a  href="http://www.digitalocean.com/edit-quote/{{quote.id}}" class="btn btn-primary">edit</a>
                                      <a href="http://www.digitalocean.com/delete-quote/{{quote.id}}" class="btn btn-danger">delete</a>
                                    </div>
                                  @endif
                              </div>
                          </div>
                      </a>
                  </div>
              @else
               <div class="col-md-12 empty-quote text-center">
                      <p>No inspirational quote has been created</p>
               </div>
              @endeach
          </div>
      </div>
      @endsection
      

      Here, you indicate that this view will use the master layout by extending it. This page can now have access to all the libraries, stylesheets, and the navbar included in the master layout. Next, you iterate over an array of quotes using the built-in @each tag. The quotes array will be passed to this view from the QuoteController that you’ll create later in this tutorial. If there are no quotes, an appropriate message will be displayed.

      Save and exit this file.

      Now, to create the login page, run the following command from the terminal:

      • adonis make:view auth/login

      You will see an output similar to:

      Output

      ✔ create resources/views/auth/login.edge

      This will automatically create an auth folder within resources/views and also create a login.edge file within it. Open the login.edge file:

      • nano resources/views/auth/login.edge

      Add the following content:

      /resources/views/auth/login.edge

      @layout('layouts/master')
      @section('content')
        <div class="container">
          <div class="row">
            <div class="col-md-4 shadow bg-white mt-5 rounded offset-md-4">
              <form method="POST" action="{{route('login.store')}}">
                {{ csrfField() }}
                  <div>
                    @if(flashMessage('successmessage'))
                      <span class="alert alert-success p-1">{{ flashMessage('successmessage') }}</span>
                    @endif
                  </div>
                  <div class="form-group">
                    <label for="email">Email address</label>
                    <input type="email" class="form-control" id="email" name="email" value="{{old('email','')}}"  placeholder="Enter email">
                    {{ elIf('<span class=text-danger>$self</span>', getErrorFor('email'), hasErrorFor('email')) }}
                  </div>
                  <div class="form-group">
                    <label for="pasword">Password</label>
                    <input type="password" class="form-control" id="password" name="password" value="{{old('password','')}}" placeholder="Password">
                    {{ elIf('<span class=text-danger>$self</span>', getErrorFor('password'), hasErrorFor('password')) }}
                  </div>
      
                  <div class="text-center">
                    <button type="submit" class="btn btn-primary">Submit</button>
                  </div>
              </form>
            </div>
          </div>
        </div>
      @endsection
      

      This file holds a form that contains input elements that you’ll use to collect the username and password of a registered user before they can successfully get authenticated and start creating quotes. Another important element to note on this page is the {{ csrfField() }}. It is a global variable that AdonisJs will use to pass the CSRF access token when sending a POST, PUT, and DELETE request from your application.

      This was put in place to protect your application from Cross-Site Request Forgery (CSRF) attacks. It works by generating a unique CSRF secret for each user visiting your website and once your users send an HTTP request from the frontend, a corresponding token is generated for this secret and passed along with the request. This will allow the middleware created for this request within AdonisJs to verify that both the token and CSRF secret is valid and belong to the currently authenticated user.

      Save and exit the file once you’re finished.

      Next, you will create the register page with this command:

      • adonis make:view auth/register

      You will see output similar to this:

      Output

      ✔ create resources/views/auth/register.edge

      Locate and open the newly created file in resources/views/auth/register.edge:

      • nano resources/views/auth/register.edge

      Add the following code:

      resources/views/auth/register.edge

      @layout('layouts/master')
      @section('content')
        <div class="container ">
          <div class="row">
              <div class="col-md-4  bg-white p-3 mt-5 shadow no-border rounded offset-md-4">
                <form method="POST" action="{{route('register.store')}}">
                  {{ csrfField() }}
                    <div class="form-group">
                      <label for="name">Fullname</label>
                      <input type="text" class="form-control" id="name" name="name"  value="{{old('name','')}}" placeholder="Enter Fullname">
                      {{ elIf('<span class=text-danger>$self</span>', getErrorFor('name'), hasErrorFor('name')) }}
                    </div>
                    <div class="form-group">
                      <label for="email">Email address</label>
                      <input type="email" class="form-control" id="email"  name="email" value="{{old('email','')}}" placeholder="Enter email">
                      {{ elIf('<span class=text-danger>$self</span>', getErrorFor('email'), hasErrorFor('email')) }}
                    </div>
                    <div class="form-group">
                      <label for="pasword">Password</label>
                      <input type="password" class="form-control" id="password" name="password" placeholder="Password">
                      {{ elIf('<span class=text-danger>$self</span>', getErrorFor('password'), hasErrorFor('password')) }}
                    </div>
                    <div class="text-center">
                        <button type="submit" class="btn btn-primary">Submit</button>
                    </div>
                </form>
              </div>
          </div>
        </div>
      @endsection
      

      Similarly to what you have on the login page, this file contains an HTML form with input fields to collect the name, email, and password of a user during the registration process. Also included is the {{ csrfField() }} as it is required for each post request for an AdonisJs application.

      Save and exit the file.

      Now, you will generate a new file to create an inspirational quote by running the following command from the terminal:

      • adonis make:view quotes/create-quote

      You will see output like:

      Output

      ✔ create resources/views/quotes/create-quote.edge

      Open resources/views/quotes/create-quote.edge:

      • nano resources/views/quotes/create-quote.edge

      And add the following content to it:

      /resources/views/quotes/create-quote.edge

      @layout('layouts/master')
      @section('content')
      <div class="container">
          <div class="row">
              <div class="col-md-3"></div>
              <div class="col-md-6 shadow bg-white mt-5 rounded p-3">
                  <div class="float-right">
                      <a href="/" class="btn btn-outline-dark ">back</a>
                  </div>
                      <br>
      
                  <div class="clear-fix"></div>
                      <form method="POST" action="{{route('store.quote')}}">
                          {{ csrfField() }}
                          <div class="form-group">
                              <label for="quote">Create Quote</label>
                              <textarea type="text" rows="5"  name='body' id="body" class="form-control" id="quote" placeholder="Write an inspirational quote"></textarea>
                          </div>
      
                          <div class="text-center">
                              <button type="submit" class="btn btn-primary">Submit</button>
                          </div>
                      </form>
                  </div>
              </div>
              <div class="col-md-3"></div>
          </div>
      </div>
      @endsection
      

      This page extends the master layout and contains an HTML form with a text area element that allows a user to input text over multiple rows before being posted and handled by the appropriate route.

      Save and exit the file once you’re finished.

      Next, you will create a page for editing a particular quote. Run the following command from the terminal:

      • adonis make:view quotes/edit-quote

      You will see the following output:

      Output

      ✔ create resources/views/quotes/edit-quote.edge

      Open the file with:

      • nano resources/views/quotes/edit-quote.edge

      Add the following content to resources/views/quotes/edit-quote:

      /resources/views/quotes/edit-quote.edge

      @layout('layouts/master')
      @section('content')
      <div class="container">
          <div class="row">
              <div class="col-md-6 shadow bg-white rounded p-3 offset-md-3">
                  <div class="float-right">
                      <a href="/" class="btn btn-outline-dark ">back</a>
                  </div>
                  <br>
      
                  <div class="clear-fix"></div>
                  <form method="POST" action="/update-quote/{{quote.id}}">
                      {{ csrfField() }}
                      <div class="form-group">
                          <label for="pasword">Edit Quote</label>
                          <textarea type="text" rows="5"  name='body' id="body" class="form-control" id="quote" placeholder="write the inspirational quote">{{quote.body}}</textarea>
                      </div>
                      <div class="text-center">
                          <button type="submit" class="btn btn-primary">Update</button>
                      </div>
      
                  </form>
              </div>
          </div>
      </div>
      @endsection
      

      This page holds similar content as the create-quote.edge file—the difference is that it contains the details of a particular quote that needs to be edited, <form method="POST" action="/update-quote/{{quote.id}}">.

      Save and exit the file.

      Finally, generate a page to view a single inspirational quote:

      • adonis make:view quotes/quote

      You will see an output similar to this:

      Output

      ✔ create resources/views/quotes/quote.edge

      Open the file with:

      • nano resources/views/quotes/quote.edge

      Add the following code:

      /resources/views/quotes/quote.edge

      @layout('layouts/master')
      @section('content')
      <div class="container">
          <div class="row">
              <div class="col-md-6 offset-md-3">
                  <div class="card shadow-lg bg-dark text-white">
                      <div class="card-body">
                          <div class="float-right">
                              <a href="/" class="btn btn-outline-primary ">back</a>
                          </div>
                              <br>
                          <div class="clear-fix"></div>
                          <blockquote class="blockquote mb-0">
                              <p>{{quote.body}}</p>
                              <footer class="blockquote-footer">
                                  <cite title="Source Title">{{quote.username}}</cite>
                              </footer>
                          </blockquote>
                      </div>
                  </div>
              </div>
          </div>
      </div>
      @endsection
      

      This page renders the details of a particular quote, that includes the body of the quote, quote.body, and the author who created it, quote.username.

      Once you’re finished with the file, save and exit.

      You have created all the required pages for your application by using the Edge templating engine. Next, you’ll configure and create a connection to your application’s database.

      Step 3 — Creating a Database Schema

      If you serve your application now it will throw an error as you are yet to connect the application to a database. In this section, you will set up a connection to the database and then use the adonis command to generate a migration file that will be used to create the tables for it.

      AdonisJs ships with an ORM named Lucid ORM, which provides active record implementation for working with your database. It takes away the hassle of writing SQL queries that retrieve data from the database in realtime. This is especially helpful when working on a complex application that requires a lot of queries. As an example, retrieving all the quotes from your application can be achieved by writing this:

      const quotes = await Quote.all()
      

      To proceed with the appropriate configuration for your application database, ensure that you are still within the root directory of your application and create a .env file:

      Open the newly created file and add the following content:

      .env

      HOST=127.0.0.1
      PORT=3333
      NODE_ENV=development
      APP_URL=http://${HOST}:${PORT}
      CACHE_VIEWS=false
      APP_KEY=bTVOEgUvmTCfkvgrK8gEBC3Qxt1xSYr0
      DB_CONNECTION=mysql
      DB_HOST=127.0.0.1
      DB_PORT=3306
      DB_USER=sammy
      DB_PASSWORD=password
      DB_DATABASE=adonis
      SESSION_DRIVER=cookie
      HASH_DRIVER=bcrypt
      

      By default the database connection for an AdonisJs application is SQLite, which you will update to MySQL here. You also specify the PORT for the application, the application environment, and your database credentials. Ensure that you replace the DB_USER, DB_PASSWORD, and DB_DATABASE placeholder with your credentials.

      Next, you will create the model and a migration file for Quote using the Adonis CLI. To accomplish that, run the following command:

      • adonis make:model Quote --migration

      You’ll see output similar to the following:

      Output

      ✔ create app/Models/Quote.js ✔ create database/migrations/1568209992854_quote_schema.js

      This command will create a model for Quote in the app/Models folder and a schema file in the database/migrations folder. The newly created schema file will be prefixed with the current timestamp. Open the schema file with:

      • nano database/migrations/1568209992854_quote_schema.js

      Update its content with the following code:

      database/migrations/…quote_schema.js

      'use strict'
      /** @type {import('@adonisjs/lucid/src/Schema')} */
      const Schema = use('Schema')
      class QuoteSchema extends Schema {
        up () {
          this.create('quotes', (table) => {
            table.increments()
            table.integer('user_id').notNullable()
            table.string('username', 80).notNullable()
            table.string('body').notNullable()
            table.timestamps()
          })
        }
        down () {
          this.drop('quotes')
        }
      }
      module.exports = QuoteSchema
      

      A schema file in AdonisJs requires two different methods, which are:

      • up: Used to create a new table or alter an existing one.
      • down: Used to revert the changes applied in the up method.

      In addition to the timestamps() and increments() fields, you update the content of the schema file with the field attributes user_id, username, and the body of a quote that will be created. The user_id and username fields reference the details of the user who create a particular quote. This defines a one to many relationship and means a user can own an infinite number of quotes while a single quote can only belong to a user.

      Save and exit the file.

      AdonisJs comes installed with a User model and its migration file by default, which requires only a small modification to establish the relationship between the User and Quote model.

      Open the User model in app/Models/User.js:

      Add this method immediately after the tokens() method:

      app/Models/User.js

      ...
      class User extends Model {
        ...
        tokens () {
          return this.hasMany('App/Models/Token')
        }
      
        quote () {
          return this.hasMany('App/Models/Quote')
        }
      }
      
      module.exports = User
      

      This will establish a one to many relationship with the Quote table using user_id as the foreign key.

      Save and exit the file.

      To wrap up this section, use the following command to run migrations, which will execute the up() method of all migration files:

      You will see output similar to the following:

      Output

      migrate: 1503248427885_user.js migrate: 1503248427886_token.js migrate: 1568209992854_quote_schema.js Database migrated successfully in 3.42 s

      You’ve configured and secured a connection with your database. You also created a Quote model and its corresponding schema file and created a one to many relationship between a User and Quote. Next, you’ll generate the routes and create controllers to handle HTTP requests and the business logic to create, edit, and delete an inspirational quote.

      Step 4 — Creating Controllers and Setting Up Routes

      In this section, you will start by creating controllers to handle all the logic for the application and later attach these controllers to a specific route for it to be accessed by users via a URL.

      To start, you’ll use the Adonis CLI to create a new HTTP request controller to handle all authentication processes for your application by running the following command:

      • adonis make:controller Auth --type http

      This command will create an AuthController.js file and save it within app/Controllers/Http folder. You use the flag --type to indicate that you want this controller to be an HTTP controller.

      You will see an output similar to the following:

      Output

      ✔ create app/Controllers/Http/AuthController.js

      Next, open the newly created controller file:

      • nano app/Controllers/Http/AuthController.js

      Update it with the following content:

      app/Controllers/Http/AuthController.js

      'use strict'
      const User = use('App/Models/User')
      class AuthController {
      
          loginView({ view }) {
              return view.render('auth.login')
          }
          registrationView({ view }) {
              return view.render('auth.register')
          }
      
          async postLogin({ request, auth, response}) {
              await auth.attempt(request.input('email'), request.input('password'))
              return response.route('index')
          }
      
          async postRegister({ request, session, response }) {
              const user = await User.create({
                  username: request.input('name'),
                  email: request.input('email'),
                  password: request.input('password')
              })
              session.flash({ successmessage: 'User have been created successfully'})
              return response.route('login.create');
          }
      
          async logout ({ auth, response }) {
              await auth.logout()
              return response.route('/')
          }
      }
      module.exports = AuthController
      

      In this file, you import the User model and then create two methods named loginView() and registerView() to render the login and register pages respectively. Finally, you create the following asynchronous methods:

      • postLogin(): This method will obtain the value of the email and password posted through the help of the inbuilt request method in AdonisJs and then validate this user against the details in the database. If such a user exists in the database and has inputted the correct credential, they will be redirected back to the homepage and authenticated before they can create a new quote. Otherwise, a message indicating the wrong credentials will be displayed.
      • postRegister(): This will receive the value of the username, email, and password for a user to create an account for such user in the database. A message indicating that such user has been created successfully will be passed to the session and the user will be redirected to the login page to get authenticated and start creating a quote.
      • logout(): This method will handle the logout functionality and redirect the user back to the homepage.

      Save and exit the file.

      Now that you have set up the controller to register and authenticate users, you will proceed by creating an HTTP request controller to manage all operations regarding quotes.

      Back in the terminal, run the following command to create the QuoteController:

      • adonis make:controller Quote --type http --resource

      Using the --resource flag will create a controller with predefined resourceful methods to do CRUD (Create, Read, Update, and Delete) operations.

      You will see:

      Output

      ✔ create app/Controllers/Http/QuoteController.js

      Locate this file within app/Controllers/Http/QuoteController.js:

      • nano app/Controllers/Http/QuoteController.js

      Update it with the following content:

      app/Controllers/Http/QuoteController.js

      'use strict'
      const Quote = use('App/Models/Quote')
      
      class QuoteController {
      
        async index ({ view }) {
          const quote = await Quote.all()
          return view.render('index', {
            quotes: quote.toJSON()
          })
        }
      
        async create ({ view }) {
          return view.render('quotes.create-quote')
        }
      
        async store ({ request,auth,session, response }) {
          const quote = await Quote.create({
            user_id: auth.user.id,
            username: auth.user.username,
            body: request.input('body')
          })
          session.flash({ 'successmessage': 'Quote has been created'})
          return response.redirect('/')
        }
      
        async show ({ params, view }) {
          const quote = await Quote.find(params.id)
          return view.render('quotes.view-quote', {
            quote: quote.toJSON()
          })
        }
      
        async edit ({ params, view }) {
          const quote = await Quote.find(params.id)
          return view.render('quotes.edit-quote', {
            quote: quote.toJSON()
          })
        }
      
        async update ({ params, request, response, session }) {
          const quote = await Quote.find(params.id)
          quote.body = request.input('body')
          await quote.save()
          session.flash({'successmessage': 'Quote has been updated'})
          return response.redirect('/')
        }
      
        async destroy ({ params, response, session }) {
          const quote = await Quote.find(params.id)
          await quote.delete()
          session.flash({'successmessage': 'Quote has been deleted'})
          return response.redirect('/')
        }
      }
      module.exports = QuoteController
      

      In this controller, you imported the Quote model and updated the following methods that were automatically created by using AdonisJs CLI:

      • index(): to fetch all quotes from the database and render it on the homepage of the application.
      • create(): to render a page for creating quotes.
      • store(): to persist a newly created quote into the database and return an appropriate response.
      • show(): to obtain the id of a particular quote, retrieve it from the database, and render it on the edit quote page.
      • edit(): to obtain the detail of a particular quote from the database and render it for editing.
      • update(): to process any update to a quote and redirect the user back to the homepage.
      • destroy(): to delete a particular quote and remove it entirely from the database.

      Save and exit the file.

      After creating all the necessary controllers for this application, you can now set up the routes so that users can easily interact with your application. To begin, navigate to start/routes.js file

      Replace its content with the following:

      start/routes.js

      'use strict'
      const Route = use('Route')
      
      Route.get('/','QuoteController.index').as('index')
      Route.get('/register','AuthController.registrationView').as('register.create')
      Route.post('/register-store','AuthController.postRegister').as('register.store').validator('Register')
      Route.get('/login','AuthController.loginView').as('login.create')
      Route.post('/login-store','AuthController.postLogin').as('login.store')
      Route.get('/view-quote/:id','QuoteController.show').as('view.quote')
      
      Route.group(() => {
          Route.get('/create-quote','QuoteController.create').as('create.quote')
          Route.post('/store-quote','QuoteController.store').as('store.quote')
          Route.get('/edit-quote/:id','QuoteController.edit').as('edit.quote')
          Route.post('/update-quote/:id','QuoteController.update').as('update.quote')
          Route.get('/delete-quote/:id','QuoteController.destroy').as('delete.quote')
          Route.post('/logout','AuthController.logout').as('logout')
      }).middleware(['auth'])
      

      Here, you define the path for each route in your application, specify the HTTP verbs for each action, and bound the route to a particular method in each controller. You also name each of these routes as they have been referenced within the controllers and views.

      To ensure that only authenticated users can access all the quotes routes, you assign a group middleware named to it. And lastly, you attach a validator method to the register.store route to validate user input.

      Save and exit the file.

      You’ve created your controllers and set up the routes for your application. Next you’ll create the validator method defined in this step.

      Step 5 — Validating User Input

      AdonisJs does not have validators built-in by default. As a result you’ll install and register the validator for your application manually.

      Run the following command to install it:

      Open the following file to register the validator provider:

      Then register the validator provider by appending it to the list of providers as shown following:

      start/app.js

      ...
      const providers = [
         ...
         '@adonisjs/cors/providers/CorsProvider',
         '@adonisjs/shield/providers/ShieldProvider',
         '@adonisjs/session/providers/SessionProvider',
         '@adonisjs/auth/providers/AuthProvider',
         '@adonisjs/validator/providers/ValidatorProvider'
      ]
      

      Now that you have installed and registered the validator provider within your application, create a custom validator to validate user input during registration with the following command:

      • adonis make:validator Register

      This will create a Register.js file in the App/validators directory. Open the file with:

      • nano app/Validators/Register.js

      Add the following code to the file:

      app/Validators/Register.js

      'use strict'
      class Register {
        get rules () {
          return {
            name:'required',
            email:'required|email|unique:users',
            password:'required|min:8'
          }
        }
      
        get messages(){
          return{
            'name.required':'Full name is required',
            'email.required':'email is required',
            'email.unique':'email already exists',
            'password.required':'password is required',
            'password.min':'password should be at least 8 characters'
          }
        }
      }
      module.exports = Register
      

      You define rules for specific fields in your application. If validations fail at any time, the validator automatically sets the error as a flash message and the user will be redirected back to the form.

      Save and exit the file once you’re finished editing.

      Finally, to add styling for your application, open the following file:

      Replace its contents with the following:

      /public/style.css

      @import url('https://fonts.googleapis.com/css?family=Montserrat:300');
      
      html, body {
        height: 100%;
        width: 100%;
      }
      
      body {
        font-family: 'Montserrat', sans-serif;
        font-weight: 300;
        background-image: url("/splash.png");
        background-color: #220052;
      }
      
      * {
        margin: 0;
        padding: 0;
      }
      
      a {
        color: inherit;
        text-decoration: underline;
      }
      
      p {
        margin: 0.83rem 0;
      }
      
      .quote-wrapper {
        margin-top: 20px;
      }
      
      .quote-wrapper a {
        text-decoration: none;
      }
      
      .quote-wrapper a:hover {
        color: #ffffff;
      }
      
      .empty-quote {
        color: #ffffff;
      }
      
      form {
        padding: 20px;
      }
      

      In this file you update the CSS styling of your application in the style.css file.

      You’ve installed and registered a validator provider for the purpose of checking users’ input during the registration process. You also updated the content of your stylesheet to add more styling to the application. In the final step you’ll test your application.

      Step 6 — Serving the Application

      In this step, you’ll serve your application and create a user and password to test the authentication. You’ll also add a quote to your app and view this on the homepage.

      To test your application, start the development server with the following command from the root directory of your application:

      This will start the application on the port defined inside the root .env file, which is 3333. Navigate to http://localhost:3333 from your browser.

      Quote app homepage

      The homepage is empty at the moment as you have not created any quotes. Click on the Register button.

      Registration page

      Enter your details and click on the Submit button to complete the registration process. You will be redirected to the login page. Enter your email address and password for authentication.

      Login page

      Once you’re authenticated, click on the Create Quote button.

      Create quote page

      Enter a quote and navigate to the View all page to see your quote.

      View all quotes page

      You’ve tested your application by creating and authenticating a user and then writing a quote.

      Conclusion

      In this tutorial you’ve built a web application with AdonisJs. You set up the application using the AdonisJs CLI and leveraged the CLI for creating other relevant files such as controllers, models, and views.

      You can build web applications with this framework irrespective of their size and complexity. Feel free to download the source code for this project here on GitHub. To explore further features, you can also visit the official documentation.

      If you would like to explore some of our other JavaScript framework tutorials, check out the following:



      Source link