Save 37% off PRO during our Black Friday Sale! »

How do we casually create an Elixir community website with Phoenix?

How do we casually create an Elixir community website with Phoenix?

Presented at ElixirConf US 2021 by Ryotaro Imahashi
https://2021.elixirconf.com/#ryotaro-imahashi

Note:
Phoenix framework has had an robust and easy to use deployment system.
With the introduction of esbuild in the "1.6" version, builds are now even faster!

This talk shows how we create a ‘Casual’ and minimalistic website of kokura.ex, a local Elixir community in Japan, with Phoenix 1.6, and publish it.
We’ll show the following process:

- Build it with Docker to fix each of the versions of packages
- Prepare to build CI and CD to make operations easier
- Put it on Heroku to release the website to the public quickly

GitHub
https://github.com/miolab/kokuraex

kokura.ex website
https://kokura-ex.herokuapp.com

E5604a3f14a53abb15d7575e4ded8ebb?s=128

Ryotaro Imahashi

October 15, 2021
Tweet

Transcript

  1. How do we casually creat e an Elixir community websit

    e with Phoenix? Ryotaro Imahashi (kokura.ex ) 10/15, 2021
  2. Welcome to

  3. 4VNNBSZ 5IJTUBMLTIPXTIPXXFDSFBUFB b$BTVBM`BOENJOJNBMJTUJDXFCTJUFPG LPLVSBFY BMPDBM&MJYJSDPNNVOJUZJO +BQBO XJUI1IPFOJY BOEQVCMJTIJU *`MMTIPXXIBULPLVSBFY`TBDUJWJUJFT 

    MBUFS
  4. *XJMMJOGPSNB63-PG UIFTFTMJEFTGPSNZUBML MBUFSCZUXFFU !JN@NJPMBC

  5. 5IJTUBMLGPDVTPOUIFOFYUQSPDFTT 'PSb$BTVBM`BOERVJDLMZSFMFBTFBNJOJNBMJTUJD1IPFOJYXFCTJUF  1SFQBSFUIF1IPFOJYQSPKFDUCZOPFDUPXJUI%PDLFS "EBQU$44MBZPVUCZ5BJMXJOE$44 1VUJUPO)FSPLV1BB4UPSFMFBTFUIFXFCTJUFUPUIFQVCMJD 1SFQBSFUPCVJME$*BOE$%UPNBLFPQFSBUJPOTFBTJFSCZVTJOH $JSDMF$*WJB(JU)VC

  6. 5IJTUBMLEPFT/05GPDVTPOUIFOFYUQSPDFTT 5IFGPMMPXJOHJTBDUVBMMZJNQMFNFOUFEBOEFYFDVUFE CVUNVDI PGUIFFYQMBOBUJPOJTPNJUUFE 0QFSBUF(JUNBOBHFNFOU *NQMFNFOUNBSLVQ)5.- *NQMFNFOUUFTUT

  7. 5IFEJBHSBNPGUIJTTZTUFN HJUQVTI UP(JU)VC %FUFDUJPOPG DIBOHFTCZ$JSDMF$* #VJMEBOE %FQMPZUP)FSPLV IUUQTLPLVSBFYIFSPLVBQQDPN %PDLFSJNBHF FMJYJSTMJN

     *NQMFNFOUBUJPOXJUI 1IPFOJY OPFDUP  5BJMXJOE$44 .BDIJOF&YFDVUPS -JOVY7. )FSPLV $POUBJOFS3FHJTUPSZ
  8. ':* 5IF(JU)VCSFNPUFSFQPTJUPSZ63-GPSUIJTQSPKFDUXFIBWF JNQMFNFOUFE IUUQTHJUIVCDPNNJPMBCLPLVSBFY 1MFBTFUBLFBMPPLGPSZPVSSFGFSFODF 5IFDPEFPO(JU)VCJTBEEFEGSPNUIBUBUUIFQSFTFOUBUJPO

  9. BCPVUNF

  10. !JN@NJPMBC !JNBJNBccJN 3ZPUBSP*NBIBTIJ JO+BQBO *MJWFJO,JUBLZVTIV +BQBO *`N "XFCEFWFMPQFSPGQJYJW*OD BOE "OPSHBOJ[FSPGLPLVSBFY

    BMPDBM &MJYJSDPNNVOJUZ
  11. IUUQTXXXQJYJWOFU QJYJW*OD QJYJW*ODQSPWJEFTBWBSJFUZ PGTFSWJDFTUPTVQQPSU DSFBUPST DFOUFSFEPOUIF JMMVTUSBUJPODPNNVOJDBUJPO TFSWJDFlQJYJWz *GZPV`EMJLFUPUSZPVUPVS TFSWJDFT

    QMFBTFEPTP IUUQTWSPJEDPNFO
  12. .ZGBWPSJUFDPOUFOUT .ZNBJOGBWPSJUFDPOUFOUTBSFGPMMPXJOHT "OJNF /FPO(FOFTJT&WBOHFMJPO "UUBDLUIF5JUBO %FNPO4MBZFS,JNFUTVOP:BJCB  'VMMNFUBM"MDIFNJTU BMDIFNJTU 

     /BUTVNFT#PPLPG'SJFOET  7JPMFU&WFSHBSEFO .VTJD "WJDJJ  ;FEE  4UFWF3FJDI "OENPSF
  13. .ZBOPUIFSBDUJWJUZ %BJUPSZV"JLJ+VKVUTV 0OFPGUIF+BQBOFTFUSBEJUJPOBMNBSUJBMBSUT  8FQSBDUJDFb,BUB`PG+VKVUTV ,FOKVUTV *BJKVUTV  #PKVUTV BOENPSF

    1IPUP`TEFTDSJQUJPO ,BUBPG+VKVUTV b,BSBNF;VNF` 5FBDIJOHB#PKVUTVUSJBMMFTTPO  4IFJTBOJOUFSOBUJPOBMTUVEFOUGSPN#FMHJVN  *BJKVUTVEFEJDBUJPOQFSGPSNBODFBUUIF /BHPTIJ'FTUJWBM "MMJNBHFTXFSFUBLFOJO'VLVPLB#VEPLBOCFGPSF UIF$07*%FQJEFNJD
  14. BCPVULPLVSBFY

  15. lLPLVSBFYzJTBDPNNVOJUZ UIBUQSPNPUFTUIF&MJYJS QSPHSBNNJOHMBOHVBHFBOEJUT XFCBQQMJDBUJPOGSBNFXPSL  1IPFOJY JO,JUBLZVTIV XIFSF CPUIIJHITQFFEQSPDFTTJOH QFSGPSNBODFBOEIJHI

    EFWFMPQNFOUFGGJDJFODZDBO CFBDIJFWFE LPLVSBFY
  16. LPLVSBFYBDUJWJUZ .PLVNPLVUFDINFFUVQ   8IJDIJTBIBDLBUIPOXIFSFFBDIBUUFOEFFBDUT BMPOFUPXBSEFBDIHPBM JOSFMBY LPLVSBFY3BEJP  &WFSZ8FEOFTEBZGSPNBNUPBN

    +BQBO UJNF POBJSBU5XJUUFS4QBDFT JO+BQBOFTF   5IJTJTBOBVEJPEJTUSJCVUJPOQSPHSBNGSPN LPLVSBFY 5IFQSPHSBNGPDVTFTPOOFX*5UPQJDT JODMVEJOH UIPTFSFMBUFEUPUIF&MJYJSEFWFMPQNFOUMBOHVBHF 5IFSFXJMMCFBRVFTUJPOBOEBOTXFSDPSOFSGPS MJTUFOFSTBOEUFYUCBTFEJOGPSNBUJPOTIBSJOHPOUIF LPLVSBFYDIBOOFMJOUIFAFMJYJSKQATMBDL  5IPVHIXFUBMLDVSSFOUMZPOUIFSBEJPJO+BQBOFTF  XF`SFXFMDPNF&OHMJTITQFBLFSTBOEXJMMUSZUP JOUFSQSFUCPUIJO&OHMJTIBOE+BQBOFTF LPLVSBFY3BEJP JOGPSNBUJPO  IUUQTGVLVPLBFYDPOOQBTTDPNFWFOU
  17. LPLVSBFYBDUJWJUZ 044DPOUSJCVUJPO   LPLVSBFYBOE1FMFNBZ.FFUVQ B +BQBOFTF&MJYJSDPNNVOJUZ USZUP DPOUSJCVUF044 FTQFDJBMMZ

    /Y &9-"  BOE#FBN"TN XIJDISFBMJ[FIJHI TQFFEQSPDFTTJOHQFSGPSNBODF 1FMFNBZ.FFUVQ IUUQTQFMFNBZDPOOQBTTDPNFWFOU 
  18. $IBQUFS $IFDLJOHUIFEFWFMPQNFOU FOWJSPONFOUBOE CFHJOOJOHPGUIFTUPSZ

  19. 5IFWFSJGJFEWFSTJPOTPGUIJTUBML 5IFEFWFMPQNFOUNBDIJOFGPSUIJTUBMLJTB.BD*OUFM WFSTJPO#JH 4VS BOEFBDIWFSJGJFEWFSTJPOTPGUFDIOPMPHJFTBSFBTGPMMPXT &MJYJS &SMBOH051  1IPFOJY /PEFKT

    5BJMXJOE$44
  20. 5IFWFSJGJFEWFSTJPOTPGUIJTUBML 5IFEFWFMPQNFOUNBDIJOFGPSUIJTUBMLJTB.BD*OUFM WFSTJPO#JH 4VS BOEFBDIWFSJGJFEWFSTJPOTPGUFDIOPMPHJFTBSFBTGPMMPXT &MJYJS &SMBOH051  1IPFOJY /PEFKT

    5BJMXJOE$44
  21. 5IFWFSJGJFEWFSTJPOTPGUIJTUBML 1IPFOJY

  22. /PX MFUTTUBSUXJUIUIFDPOUFOUTPGUIJTUBML

  23. UJUMFEXJUI&MJDB`T"EWFOUVSFT JO1IPFOJYMBOE /PX MFUTTUBSUXJUIUIFDPOUFOUTPGUIJTUBML

  24. *OUSPEVDJOHUIFNBJODIBSBDUFS

  25. .BJO"DUPS /05NFBOTBDUPSPGDPODVSSFODZ FYFDVUJOHTZTUFN

  26. .BJO"DUPS &MJDB BO&MJYJSMPWFSEFWFMPQFS /05NFBOTBDUPSPGDPODVSSFODZ FYFDVUJOHTZTUFN

  27. .BJO"DUPS &MJDB BO&MJYJSMPWFSEFWFMPQFS  TIFXBOUTUPDSFBUFBUFDI DPNNVOJUZTJUFDBTVBMMZ /05NFBOTBDUPSPGDPODVSSFODZ FYFDVUJOHTZTUFN

  28. 8JSFGSBNFPGUIFTJUF XJTIGVMUIJOLJOH ( ´ʔ`)ɻоʢ

  29. 8JSFGSBNFPGUIFTJUF XJTIGVMUIJOLJOH ( ´ʔ`)ɻоʢ

  30. 8IJUF3BCCJUBMTPTBJE *NMBUF *NMBUF *NMBUFz *XBOOBNBLFJUNVDI RVJDLFSBOEFBTJFS

  31. *XBOOBPQFSBUF DPOUJOVPVTEFMJWFSZ XJUIFBTF

  32. #58 *`WFOFWFSVTFEB XFC1IPFOJYGSBNFXPSL  CVU*IFBSEJU`TOJDFGPS UIJTTJUVBUJPO

  33. "OE UIF1IPFOJYWFSTJPOXBTSFMFBTFE UIFMBTUNPOUI

  34. *U`TQFSGFDUUJNJOH JTO`UJU

  35. 0, MFU`TTUBSU 1IPFOJYXJUINF

  36. $IBQUFS TFUVQPG1IPFOJY

  37. 8IBUUIJTDIBQUFSDPWFST 8FXJMMSVOUISPVHIUIFQSPDFTT GSPNCVJMEJOHUIF%PDLFS EFWFMPQNFOUFOWJSPONFOUUPCVJMEJOH 1IPFOJY  BOEEJTQMBZJOHUIFGJSTUl8FMDPNFUP 1IPFOJYzTDSFFO 4UFQT 1SFQBSFEPDLFSGJMFT

    &YFDVUFAEPDLFSDPNQPTFCVJMEA *OTUBMM1IPFOJYGSBNFXPSL
  38. % tree -L 2 .(e.g. kokuraex/ ) ├── README.m d

    ├── ap p │ └── Dockerfil e └── docker-compose.yml /PX XFXJMMNBLFUIF1IPFOJYQSPKFDU EJSFDUPSZBOEQSFQBSFUIFEPDLFSGJMFTBT TIPXOPOUIFSJHIU "CPVUUIFQSPKFDUEJSFDUPSZ XFOBNFE lLPLVSBFYzUIJTUJNF /PUF 8FPNJUNFOUJPOJOHTFWFSBMGJMFT GPS FYBNQMF 3&"%.& HJUJHOPSF BOENPSF *OUIFGPMMPXJOHDIBQUFST UPP 1SFQBSFEPDLFSGJMFT
  39. [app/Dockerfile ] FROM elixir:1.12.2-sli m WORKDIR /usr/src/ap p RUN apt-get

    update -y && \ apt-get upgrade -y && \ apt-get install -y \ build-essential \ curl \ git \ gzip \ inotify-tools \ ssh \ sudo \ ta r RUN apt-get clea n RUN mix local.hex --force && \ mix local.rebar --forc e RUN mix archive.install hex phx_new 1.6.0 --forc e CMD [ "mix", "phx.server", "--no-halt" ] 1SFQBSFEEPDLFSDPNQPTFZNMBOE %PDLFSGJMFJTIFSF *UTQFDJGJFT1IPOFOJYWFSTJPO 1SFQBSFEPDLFSGJMFT [app/Dockerfile ] version: "3 " services : app : build: ./ap p volumes : - ./app:/usr/src/ap p ports : - "4000:4000 " stdin_open: tru e tty: tru e command: sh -c "mix phx.server --no-halt "
  40. % docker compose build "GUFSQSFQBSFEEPDLFSGJMFT  MFU`TFYFDVUF AEPDLFSDPNQPTFCVJMEA &YFDVUFAEPDLFSDPNQPTFCVJMEA

  41. % docker compose run app mix phx.new . --app kokuraex

    —no-ect o … The directory /usr/src/app already exists. Are you sure you want to continue? [Yn] y … Fetch and install dependencies? [Yn] y … "GUFSEPOFPGAEPDLFSDPNQPTFCVJMEA JOTUBMM1IPFOJY *OTUBMM1IPFOJYGSBNFXPSL
  42. % tree -L 2 . ├── README.m d ├── ap

    p │ ├── Dockerfil e │ ├── README.m d │ ├── _buil d │ ├── asset s │ ├── confi g │ ├── dep s │ ├── li b │ ├── mix.ex s │ ├── mix.loc k │ ├── pri v │ └── tes t └── docker-compose.ym l *OTUBMM1IPFOJYGSBNFXPSL … We are almost there! The following steps are missing : $ cd . Start your Phoenix app with : $ mix phx.serve r You can also run your app inside IEx (Interactive Elixir) as : $ iex -S mix phx.server 8FTBXUIFGPMMPXJOHNFTTBHF BOEDPOHSBUVMBUJPOT  UIFJOTUBMMBUJPOXBTDPNQMFUFE "OEBUUIFNPNFOU UIFEJSFDUPSZUSFFJTTIPXOPO UIFSJHIU
  43. "GUFS1IPFOJYJOTUBMMBUJPO  GJY*1UPl   zGPSEFWFYTGJMFCZVQEBUFBTCFMMPX *OTUBMM1IPFOJYGSBNFXPSL [app/config/dev.exs ] config

    :kokuraex, KokuraexWeb.Endpoint , # Binding to loopback ipv4 address prevents access from other machines . # Change to `ip: {0, 0, 0, 0}` to allow access from other machines . - http: [ip: {127, 0, 0, 1}, port: 4000] , + http: [ip: {0, 0, 0, 0}, port: 4000] ,
  44. /PX XFFYFDVUFEPDLFSDPNQPTFVQBOE MPPLMPDBMIPTUJOCSPXTFS *OTUBMM1IPFOJYGSBNFXPSL

  45. *OTUBMM1IPFOJYGSBNFXPSL :FT XFEJEJU 8FHPUUIFQSPPGUIBUUIFTDSFFO TIPXFEVQl8FMDPNFUP1IPFOJYz 5IFGJSTUNJTTJPOXBTDPNQMFUFE

  46. $IBQUFS "EBQU$44MBZPVUCZ 5BJMXJOE$44

  47. 8IBUUIJTDIBQUFSDPWFST 5PQSFQBSFUIFMBZPVUXJUIFBTF XFXJMMVTF 5BJMXJOE$44 *OUIJTTFDUJPO XFXJMMGPDVTPOUIFTFUVQBOE JOUSPEVDUJPOPG5BJMXJOEJNQMFNFOUBUJPO 8FXJMMBMTPFYQMBJOXFCTJUFDPOUFOUDSFBUJPO BOEQBHFUSBOTJUJPOT CVUXFXJMM/05FYQMBJO

    NVDIBOETLJQBCPVUNBSLVQ UFTUT BOEPUIFS JNQMFNFOUBUJPOEFUBJMT 4UFQT *OTUBMM/PEFKT 1SFQBSF5BJMXJOE$44FOWJSPONFOU 1SFQBSFFBDISPVUFQBHFBOENBSLVQ 4FUUBJMXJOEDMBTTJOMJOFDPEF
  48. 5IFNBJOSFBTPOJTUIBUCZ BEPQUJOH5BJMXJOE$44 B VUJMJUZGJSTU$44GSBNFXPSL  XFXJMMCFBCMFUPNBLFHPPE QSPHSFTTJOPVSNJTTJPOUP RVJDLMZTFUMBZPVUTUZMFT XJUIPVUXSJUJOHSBX$44 8IZXFDIPJDF5BJMXJOE$44

    IUUQTUBJMXJOEDTTDPN
  49. 5BJMXJOE$44SFRVJSFTUIFFOWJSPONFOUPG /PEFKT CVUPVS1IPFOJYWFSTJPOQSPKFDU EPFTOPUIBWFUIFPOFZFU 4P XFNVTUBEEUIFTUFQPGJOTUBMMBUJPO/PEFKT JO%PDLFSGJMF *OUIJTUBML XFVTFOQNQBDLBHFOUPJOTUBMM /PEFKTBOENBOBHFUIFWFSTJPOT

    5IFSFJTBMTPBSFBTPOXIZ*XBOUUPTQFDJGZ FWFONJOPSWFSTJPOTPG/PEFKTBOEBWPJE QSPCMFNTDBVTFECZWFSTJPOEJGGFSFODFT "GUFSJOTUBMMJOH/PEFKT XFSFCVJMEDPOUBJOFST BHBJOXJUIbEPDLFSDPNQPTFCVJME` *OTUBMM/PEFKT (for confirmation ) % docker compose exec app node - v v16.9.1 /05&O OQNQBDLBHF  IUUQTXXXOQNKTDPNQBDLBHFO [app/Dockerfile ] … + RUN apt-get install -y nodejs np m + RUN npm install -g n + RUN n 16.9. 1 + RUN apt-get purge -y nodejs np m RUN apt-get clea n … % docker compose build
  50. 'PSTFUVQ5BJMXJOE$44TNPPUI XFTJNQMZ DIPPTFIFYQBDLBHF lQIY@HFO@UBJMXJOEz 5IJTCVJMETVQ5BJMXJOE$44EFWFMPQNFOU FOWJSPONFOUUPBOFX1IPFOJYBQQMJDBUJPO OJDFBOERVJDLMZ #JHUIBOLTUPUIFIFYQSPKFDUPXOFS ,FWJO -BOH

     5IFGJSTUTUFQUPEPJTUPTUPQSVOOJOH DPOUBJOFSTBOEUIFOVQEBUFNJYFYTBTTIPXO POUIFSJHIU "GUFSUIBU XFEPNJYEFQTHFUBOEDPNQJMF 1SFQBSF5BJMXJOE$44FOWJSPONFOU % docker compose run app mix deps.compile /05&QIY@HFO@UBJMXJOE )FY IUUQTIFYQNQBDLBHFTQIY@HFO@UBJMXJOE (JU)VC IUUQTHJUIVCDPNLFWJOMBOHQIY@HFO@UBJMXJOE [app/mix.exs ] defp deps d o [ .. . - {:plug_cowboy, "~> 2.5" } + {:plug_cowboy, "~> 2.5"} , + {:phx_gen_tailwind, "~> 0.1.3" } ] end % docker compose run app mix deps.get
  51. 5IFOFYFDVUFUIFDPNNBOEAEPDLFSDPNQPTFSVO BQQNJYQIYHFOUBJMXJOEA /PXXFBSFSFBEZUPJNQMFNFOU$44XJUI5BJMXJOE 5IFNBJOGJMFTXIFSFUIFEJGGFSFODFTPDDVSSFEBSF TIPXOPOUIFSJHIU *GXFXBOUUPLOPXNPSFBCPVUQIY@HFO@UBJMXJOE  UIF(JU)VCBOE)FYEPDVNFOUTBUUIF63-POUIF SJHIUXJMMIFMQVT 0GDPVSTF

    XFXJMMBMTPGJOEUIFPGGJDJBM5BJMXJOE$44 EPDVNFOUBUJPOWFSZIFMQGVM IUUQTUBJMXJOEDTTDPNEPDTJOTUBMMBUJPO 1SFQBSF5BJMXJOE$44FOWJSPONFOU % docker compose run app mix phx.gen.tailwin d * creating assets/package.jso n * creating assets/tailwind.config.j s * injecting assets/css/app.cs s * injecting config/dev.ex s * injecting mix.ex s * injecting assets/js/app.j s NPM install new dependencies? [Yn] y * running cd assets/ && npm install mainly dif f modified: app/assets/css/app.cs s modified: app/assets/js/app.j s modified: app/config/dev.exs /05&QIY@HFO@UBJMXJOE )FY IUUQTIFYQNQBDLBHFTQIY@HFO@UBJMXJOE (JU)VC IUUQTHJUIVCDPNLFWJOMBOHQIY@HFO@UBJMXJOE
  52. /PXMFU`TTUBSUSFSVOOJOHDPOUBJOFSTCZ AEPDLFSDPNQPTFVQABOEDIFDLSFTVMUTJO PVSCSPXTFS 8JUIUIFJNQMFNFOUBUJPOFOWJSPONFOUPG 5BJMXJOE$44JOQMBDF UIFEFGBVMU$44TUZMF PG1IPFOJYIBTCFFOSFNPWFE /PXMFUTUSZPOFJNQMFNFOUBUJPOPG5BJMXJOE $44GSPNUIJTTUBUF 1SFQBSF5BJMXJOE$44FOWJSPONFOU

  53. "EEUIFDMBTTFTQSFQBSFECZ5BJMXJOE$44JOUIFIUBHCZ JOMJOFTUZMF 5IJTNBHJDIBTUIFFGGFDUPGDPOWFSUJOHUIFGPOUXFJHIU GPOU TJ[F BOEDPMPSPGGPOUTUPXIBUFWFSXFXBOU *GXFXBOUUPLOPXNPSFBCPVUXIJDIDMBTTEPFTXIBU JUJT SFDPNNFOEFEUPTFFUIF5BJMXJOE$44DIFBUTIFFU63- 'PSFYBNQMF

    UIFSFJTBDIFBUTIFFUUIBUMPPLTMJLF lUBJMXJOEDPNQPOFOUTDPNz IUUQTUBJMXJOEDPNQPOFOUTDPNDIFBUTIFFU 1SFQBSF5BJMXJOE$44FOWJSPONFOU [app/lib/kokuraex_web/templates/page/index.html.heex ] <section class="phx-hero" > - <h1><%= gettext "Welcome to %{name}!", name: "Phoenix" %></h1 > + <h1 class="font-medium text-4xl text-indigo-600"><%= gettext "Welcome to %{name}!", name: "Phoenix" %></h1 > <p>Peace of mind from prototype to production</p>
  54. /PX XFXJMMTUBSUJNQMFNFOUJOHUIFDPOUFOUTFUVQBOE QBHFUSBOTJUJPOTGPSPVSXFCTJUF LPLVSBFY 1BHFUSBOTJUJPOTBSFTIPXOCFMPX BOEUIF JNQMFNFOUBUJPOJTEPOFBTTIPXOPOUIFSJHIU 5IFFYBNQMFTIPXOIFSFJTGPSUIFBCPVUQBHF CVUUIF JNQMFNFOUBUJPOGPSUIFFWFOUQBHFDBOCFEPOFJOUIF

    TBNFXBZ 3FQMBDFBCPVUXJUIFWFOUBOEDMPOFJU  1MFBTFOPUFUIBUXFXJMMOFFEUPTUPQBOESFTUBSUUIF DPOUBJOFSBTOFFEFE 1SFQBSFFBDISPVUFQBHFBOENBSLVQ (page transitions ) hom e !"" abou t #"" event (New file ) [app/lib/kokuraex_web/templates/about/index.html.heex ] <h1>About</h1> [app/lib/kokuraex_web/router.ex ] … get "/", PageController, :inde x + get "/about", AboutController, :inde x end (New file ) [app/lib/kokuraex_web/controllers/about_controller.ex ] defmodule KokuraexWeb.AboutController d o use KokuraexWeb, :controlle r def index(conn, _params) d o render(conn, "index.html" ) en d end (New file) [app/lib/kokuraex_web/views/about_view.ex ] defmodule KokuraexWeb.AboutView d o use KokuraexWeb, :vie w end
  55. -FUTUBLFBMPPLBUUIFlBCPVUzQBHF  XIJDIIBTKVTUCFFOCPSO *UJTJOBQMBJOTUBUFXJUIOP$44DMBTTFT BQQMJFEZFU 'SPNIFSF XFDSFBUFUIFDPOUFOU  JODMVEJOHUFYUBOEJNBHFT UPTFUUIF

    MBZPVU 8FXPOUHPJOUPUIFEFUBJMTIFSF 5IFTPVOEPGBDMPDLUJDLJOHXIJMF NBSLVQJTCFJOHEPOFʜ 1SFQBSFFBDISPVUFQBHFBOENBSLVQ (localhost:4000/about)
  56. 4FUUBJMXJOEDMBTTJOMJOFDPEF *XJMMDBTUB 5BJMXJOE$44TQFMMʜ

  57. 4FUUBJMXJOEDMBTTJOMJOFDPEF 8FXJMMMFUZPVLOPXUIFSFTVMUTTPPOMBUFS -FUTMPPLGPSXBSEUPJU

  58. $IBQUFS 1VUJUPO)FSPLVUPSFMFBTF UIFXFCTJUFUPUIFQVCMJD

  59. 8IBUUIJTDIBQUFSDPWFST )FSPLVJTBOJDF1BB4GPSFBTZ BQQMJDBUJPOSFMFBTF *UTVQQPSUT&MJYJS PGDPVSTF 0VSXFCTJUFJTCVJMUPOEPDLFS BOEXF XJMMUSZUPEFQMPZJUVTJOH)FSPLVT DPOUBJOFSSFHJTUSZTZTUFN 4UFQT

    8IZEJEXFDIPPTF)FSPLV  4FUVQPG1IPFOJYGPSSFMFBTF 4FUVQPG)FSPLV %FQMPZ
  60. 8IZEJEXFDIPPTF)FSPLV *UTCFDBVTF JOBOVUTIFMM  XF`SFVTFEUPVTJOH)FSPLV1BB4 4P MFU`TTUBSUUIFTFUVQ

  61. 8IZEJEXFDIPPTF)FSPLV 4FUVQJOQSPHSFTTʜʜ

  62. 8IZEJEXFDIPPTF)FSPLV 4FUVQJOQSPHSFTTʜʜ 0I OP

  63. 8IZEJEXFDIPPTF)FSPLV )FZ XBJUBNJOVUF  *UIJOL*DBVHIUBHMJNQTFPGB1BB4UIBU MPPLTHPPE

  64. IUUQTGMZJP

  65. 8IZEJEXFDIPPTF)FSPLV l'MZJPz  0I EFBS /P *EJEOUTFFBOZUIJOH *WFBMSFBEZTUBSUFEUPCVJMEJUPO)FSPLV  TP*MMSFMFBTFJUUIFSFBOEUIFOCVJMEJUBHBJOPO

    'MZJPʜ
  66. 5IFTFDSFULFZHFOFSBUFECZUIJTTUFQJTUIF POFXFMMOFFEUPEFQMPZUP)FSPLVMBUFS .BLFBOPUFPGJUTPNFXIFSF TPXFEPOU MPTFJU 5IJTJTDPOGJEFOUJBMJOGPSNBUJPO 1MFBTFEPOUSFWFBMJUUPBOZPOF  "MTP VQEBUFPVS%PDLFSGJMFBOESFMFWBOU

    GJMFTBTTIPXOPOUIFSJHIU 4FUVQPG1IPFOJYGPSSFMFBTF [app/config/prod.exs ] … config :kokuraex, KokuraexWeb.Endpoint , - url: [host: "example.com", port: 80] , + http: [port: System.get_env("PORT")] , + url: [scheme: "https", host: "kokura-ex.herokuapp.com", port: 443] , + force_ssl: [rewrite_on: [:x_forwarded_proto]] , … [app/Dockerfile ] FROM elixir:1.12.2-sli m + ENV MIX_HOME=/root/.mix \ + MIX_ENV=prod \ + SECRET_KEY_BASE=${SECRET_KEY_BASE} \ + PORT=400 0 + COPY . /usr/src/ap p WORKDIR /usr/src/app "OZXBZ MFUTHPCBDLBMJUUMFCJU BOETUBSUXJUIUIFTFUVQJO1IPFOJYGPSSFMFBTF 8FGJSTUOFFEUPDSFBUFBTFDSFULFZCZSVOOJOHUIF DPNNBOEAEPDLFSDPNQPTFSVOBQQNJY QIYHFOTFDSFUA % docker compose run app mix phx.gen.secret [app/config/config.exs ] # Configures the endpoin t config :kokuraex, KokuraexWeb.Endpoint , url: [host: "localhost"] , + secret_key_base: System.get_env("SECRET_KEY_BASE") , …
  67. 4FUVQPG1IPFOJYGPSSFMFBTF (New file) [heroku.yml ] build : docker : web:

    app/Dockerfile [docker-compose.yml ] … + environment:SECRET_KEY_BASE=“TooLongStrings……… ” stdin_open: tru e tty: tru e command: sh -c "mix phx.server —no-halt" 1MFBTFOPUFUIBUUIFTFDIBOHFTNBZQSFWFOUPVSMPDBM %PDLFSEFWFMPQNFOUFOWJSPONFOUGSPNSVOOJOHQSPQFSMZ *GTP XFTIPVMEUBLFUIFGPMMPXJOHTUFQT  3FXSJUFEPDLFSDPNQPTFZNMBTTIPXOPOUIFSJHIU  XJUI4&$3&5@,&:@#"4&CFJOHBMPOHEVNNZUFYUPG ZPVSDIPJDF  8FDBOBMTPSFNPWFUIFATFDSFU@LFZ@CBTFAMJOFGSPN BQQDPOGJHEFWFYT *OUIFGVUVSF JUXPVMECFOJDFUPIBWFUXP%PDLFSGJMFT  POFGPSEFWFMPQNFOUBOEPOFGPSSFMFBTF 8FPNJUBOFYQMBOBUJPOPGUIBUIFSF 0PQT XFGPSHPUPOFNPSFJNQPSUBOUUIJOH 8FTIPVMEDSFBUFBIFSPLVZNMGJMFBOEQVUJUJOUIFSPPU PGPVSQSPKFDUEJSFDUPSZ [app/config/dev.exs ] … code_reloader: true , debug_errors: true , - secret_key_base: “LongPreWrittenWtrings…………… ” watchers: [ …
  68. /PUF  8FXJMMOPUFYQMBJOIPXUPDSFBUFB)FSPLVBDDPVOUIFSF*GZPVIBWFOUDSFBUFEBO BDDPVOUZFU QMFBTFSFGFSUPUIFPGGJDJBMXFCTJUFGPSFBTZUPGPMMPXJOTUSVDUJPOTUPHFU SFBEZ IUUQTEFWDFOUFSIFSPLVDPNDBUFHPSJFTCJMMJOH  *UJTCFTUJGZPVBMTPJOTUBMM)FSPLV$PNNBOE-JOF*OUFSGBDF )FSPLV$-*

    )FSPLV $-*NBLFTJUFBTZUPNBOBHF)FSPLVBQQTEJSFDUMZGSPNUIFUFSNJOBM5IFJOTUBMMBUJPO QSPDFTTJTIFSF IUUQTEFWDFOUFSIFSPLVDPNBSUJDMFTIFSPLVDMJ 4FUVQPG)FSPLV /PXJUTUJNFUPTFUVQ)FSPLV -FU`TMPHJOUP)FSPLVGSPNUIFUFSNJOBM % heroku login
  69. /PX MFUTDSFBUFB)FSPLVQSPKFDUCZFYFDVUJOHUIF DPNNBOEAIFSPLVDSFBUFBXFTPNFBQQOBNFA  *OUIFBXFTPNFBQQOBNFGJFME XFTIPVMEFOUFS UIFOBNFPGUIFBQQMJDBUJPOOBNFXFXBOU"OE UIJTTUSJOHXJMMCFEJSFDUMZJODPSQPSBUFEBTQBSUPG UIFBQQMJDBUJPO`TQVCMJD63- 

    "UUIFTBNFUJNF JUXJMMSFHJTUFSPVS)FSPLV SFQPTJUPSZUPUIFHJUSFNPUFSFQPTJUPSZ$IFDLJU PVUJOUIFAHJUSFNPUFADPNNBOE 8FMMBMTPOFFEUPBEEUIFTFDSFULFZXFDSFBUFE FBSMJFSUPUIF)FSPLVFOWJSPONFOUWBSJBCMFT -FU`TSFHJTUFSCZFYFDVUJPOUIFDPNNBOEAIFSPLV DPOGJHTFU4&$3&5@,&:@#"4&YYYYYYYYYYYYA 4FUVQPG)FSPLV % heroku create kokura-e x Creating ⬢ kokura-ex... don e https://kokura-ex.herokuapp.com/ | https:// git.heroku.com/kokura-ex.git % heroku config:set SECRET_KEY_BASE=xxxxxx x Setting SECRET_KEY_BASE and restartin g …
  70. /PXMFUTHFUSFBEZUPEFQMPZB%PDLFSCBTFE QSPKFDUCZVTJOHUIF)FSPLV$POUBJOFS 3FHJTUSZNFDIBOJTN 'PSBNPSFEFUBJMFEFYQMBOBUJPOPGUIF)FSPLV $POUBJOFS3FHJTUSZ JUXPVMECFBHPPEIFMQFS UPSFBEUIFPGGJDJBMEPDVNFOUBUJPO IUUQT EFWDFOUFSIFSPLVDPNBSUJDMFTDPOUBJOFS SFHJTUSZBOESVOUJNF

     )FSF XFXJMMGPDVTPOUIFFYFDVUJPOTUFQT )PXFWFS JUJTWFSZFBTZUPEP TPMFUTSVOUIF DPNNBOEPOUIFSJHIU 4FUVQPG)FSPLV % heroku container:logi n Login Succeeded % heroku stack:set containe r Setting stack to container... done
  71. &OTVSFUIBUPVSDPEFJTBMMHJUDPNNJUUFE BOEUIFO SVOUIFDPNNBOEAHJUQVTIIFSPLV NZ@CSBODINBJOA 5IJTXJMMQVTIPVSGJMFT JODMVEJOHIFSPLVZNM UPUIF SFNPUFSFQPTJUPSZPG)FSPLV  /PUFUIBUXFSFQMBDFUIFMFUUFSTlNZ@CSBODIzXJUI

    UIFOBNFPGUIFCSBODIXFSFXPSLJOHPO*O EFUBJM UPEPBUSJBMQVTIUP)FSPLVXIFOXFSFJO UIFEFWFMPQNFOUHJUCSBODI XFOFFEUPTQFDJGZ TPNFUIJOHMJLFzNZ@CSBODINBJOz 0ODFXFWFEPOFUIJT NPWFUPUIFBQQEJSFDUPSZ  BOEJUTUJNFGPSUIFQSPEVDUJPOSFMFBTFUJNF 3VOAIFSPLVDPOUBJOFSQVTIXFCABOEAIFSPLV DPOUBJOFSSFMFBTFXFCA %FQMPZ % cd ap p % heroku container:push we b … Your image has been successfully pushed. You can now release it with the 'container:release' command . $ heroku container:release we b Releasing images web to phx- containers... done % git push heroku my_branch:main
  72. 6OGPSUVOBUFMZ JGUIBUEPFTOUXPSL XIBUEPXFEP  5IFDPNNBOEAIFSPLVMPHTUBJMAXJMMIFMQVT $IFDLPVSMPHTBOEUSZUPTPMWFUIFQSPCMFN 5IFDBVTFPGUIFFSSPSNJHIUCF GPSFYBNQMF  :PVNJHIUOPUMPHJOUP)FSPLVCZAIFSPLVDPOUBJOFSMPHJOA

     TPUIFFSSPSBSPVOEBVUIJOUFSDFQUFEZPV  :PVNJHIUPNJUUIFFOWJSPONFOUWBSJBCMFTSFMBUFEUP )FSPLV FJUIFSPO)FSPLVPSJOPVS%PDLFSGJMF :PVNJHIUGPSHFUUPHJUQVTI)FSPLVUIFDIBOHFEGJMFT 8FXJMMBTTVNFUIBUFWFSZUIJOHXFOUXFMMIFSF /PX MFUTTFFUIFTJUFQVCMJTIFEGPSUIFXPSMEUPTFF 8FDBOSVOUIFAIFSPLVPQFOADPNNBOEUPEJTQMBZ UIFTJUFJOUIFCSPXTFS0QFO4FTBNF %FQMPZ % heroku logs --tail % heroku open
  73. %FQMPZ 8FXJMMMFUZPVLOPXUIFSFTVMUTTPPOMBUFS -FUTMPPLGPSXBSEUPJU cEFKBWV%

  74. $IBQUFS 4FUVQ$*BOE$%CZVTJOH $JSDMF$*

  75. 8IBUUIJTDIBQUFSDPWFST 'PSUIFDPODMVEJOHQBSUPGUIJTUBML XFMMCVJMEUIF $*BOE$%QJQFMJOF 5IF$*BOE$%QJQFMJOFXJMMCSJOHUPNBLF PQFSBUJPOTFBTJFSGPSVT*OUIJTDBTF XFXJMMCVJME UIF$*BOE$%QJQFMJOFCZVTJOH$JSDMF$*WJB (JU)VC 5IJTTFDUJPOXJMMNBJOMZGPDVTPOUIFFYQMBJOJOHUIF

    GMPXPGUIF$*BOE$%QJQFMJOFXFCVJMU CVUXFXJMM /05FYQMBJONVDIBOETLJQEFUBJMFEFYQMBOBUJPOPG $JSDMF$* (JU)VC BOE$*$%UIFNTFMWFT 4UFQT 1SFQBSFDJSDMFDJDPOGJHZNMJOMPDBM 4FU$JSDMF$*FOWJSPONFOU &YFDVUFUIF$*BOE$%QJQFMJOF
  76. 1SFQBSFDJSDMFDJDPOGJHZNMJOMPDBM 4P XFXJMMHPUISPVHIUIFQSPDFTTTUFQCZTUFQ CVUXFXJMM/05FYQMBJOIPX UPDSFBUFB$JSDMF$*BDDPVOU 'VSUIFSNPSF XFVTF(JU)VC CVUXFEP/05FYQMBJOIPXUPDPOOFDUUIF SFNPUFSFQPTJUPSZUPUIF$JSDMF$*TJEFJOEFUBJM 8FDBOGJOEEFUBJMFEJOTUSVDUJPOTPOUIFTFUPQJDTPO$JSDMF$*`TPGGJDJBMXFCTJUF

    )FSFJTUIF63-GPSUIPTF DJSDMFDJ%PDT:PVS'JSTU(SFFO#VJME IUUQTDJSDMFDJDPNEPDTHFUUJOHTUBSUFE $JSDMF$*IBTHPPEUFDIOJDBMEPDVNFOUBUJPO TPXFDBOGJOEPVUBOETPMWFNPTU QSPCMFNTCZSFBEJOHUIFJSEPDVNFOUBUJPO
  77. (New file) [circleci/config.yml ] version: 2. 1 executors : machine-executor

    : machine : image: ubuntu-2004:202107-0 2 orbs : heroku: circleci/heroku@1.2. 6 workflows : version: 2 build-deploy : jobs : - buil d - deploy : requires : - buil d filters : branches : only: mai n jobs : (Continue to next page) -FUTTUBSUCZXSJUJOHDPEFJOUPUIFDJSDMFDJDPOGJHZNMGJMF 5IFNBJOQPJOUTPGUIFQSPDFTTGMPXBSFBMTPEFTDSJCFEJOFBDITFDUJPO 8FXJMMBMTPJODMVEFSFGFSFODF63-T FYFDVUPST #ZBQQMZJOH.BDIJOFUPUIF&YFDVUPSUZQF XFSVOUIFKPCJOB-JOVY7. JNBHF 6CVOUV *OBEEJUJPO UIF.BDIJOF&YFDVUPSHJWFTVTGVMMBDDFTTUP UIF%PDLFSQSPDFTT5IJTBMMPXTVTUPCVJMEBOESVODVTUPN%PDLFS DPOUBJOFST  6TJOHNBDIJOFIUUQTDJSDMFDJDPNEPDTFYFDVUPSUZQFTVTJOH NBDIJOF  PSCT 5PFBTJMZTFUVQUIF)FSPLVEFQMPZNFOUQSPDFTT XFBSFVTJOH$JSDMF$*T )FSPLV0SC $JSDMF$*0SCJTBTIBSBCMFPQFOTPVSDFQBDLBHFUIBUCSJOHTUPHFUIFS CVJMEJOHCMPDLTUIBUNBLFJURVJDLBOEFBTZUPJOUFHSBUFBOEQSPDFTT EJGGFSFOUTFSWJDFT  0SCDJSDMFDJIFSPLV IUUQTDJSDMFDJDPNEFWFMPQFSPSCTPSCDJSDMFDJ IFSPLV XPSLGMPXT 0ODFUIFDPOUBJOFSJNBHFIBTCFFOCVJMUCZUIFlCVJMEKPCzBOE TVCTFRVFOUMZNFSHFEJOUPUIFNBJOSFQPTJUPSZ UIFEFQMPZNFOUQSPDFTTJT FYFDVUFE5IFJNQMFNFOUBUJPOJTSFGMFDUFEJOUIFQSPEVDUJPOFOWJSPONFOU 1SFQBSFDJSDMFDJDPOGJHZNMJOMPDBM
  78. (Continued from previous page ) jobs : build : executor

    : name: machine-executo r steps : - checkou t - run : name: Build Docker container s command: | set - x docker-compose buil d - run : name: Mix deps.get & compil e command: | set - x docker-compose run app bash -c "mix deps.get " docker-compose run app bash -c "mix compile" *OUIFCVJMEKPCTUFQ WBSJPVTCVJMEPQFSBUJPOTBSF FYFDVUFEBTUIFOBNFTVHHFTUT*OUIJTTUFQ UFTUJOH BOEGPSNBUUJOHDIFDLTBSFBMTPDBSSJFEPVUEVSJOHUIJT TUBHFPGUIFQSPDFTT 'PSSFBTPOTPGQBQFSTQBDF TPNFJOEFOUBUJPOJOUIF ZNMGJMFIBTCFFOPNJUUFE 1SFQBSFDJSDMFDJDPOGJHZNMJOMPDBM - run : name: Npm install in assets director y command: | set - x docker-compose run app bash -c "cd assets && npm i " - run : name: Mix forma t command: | set - x docker-compose run app bash -c "mix format --check-formatted " - run : name: Mix tes t command: | set - x docker-compose run app bash -c "MIX_ENV=test mix test " - run : name: Compile asset s command: | set - x docker-compose run app bash -c "MIX_ENV=prod mix assets.deploy " - run : name: Mix releas e command: | set - x docker-compose run app bash -c "MIX_ENV=prod mix release " - run : name: Run Docker container s command: | set - x docker-compose up - d sleep 1 docker ps -f status=runnin g docker-compose log s - persist_to_workspace : (Continue to next page)
  79. (Continued from previous page ) - persist_to_workspace : root: .

    paths : - ./app/dep s - ./app/_buil d - ./app/pri v - ./app/assets / - run : name: Finish buil d command: | set - x echo "Finish build" QFSTJTU@UP@XPSLTQBDF JOUIFCVJMEKPC  'JMFTEJSFDUPSJFTSFRVJSFEGPSEFQMPZNFOUBSF TIBSFEWJBl8PSLTQBDFzCFUXFFOUIFCVJMEBOE EFQMPZKPCT EFQMPZ 5IJTJTXIFSFUIFQSPDFTTPGEFQMPZJOHUP)FSPLV UBLFTQMBDF5IFFOWJSPONFOUWBSJBCMFTFUUJOHFUD  BSFEFTDSJCFEMBUFS 1SFQBSFDJSDMFDJDPOGJHZNMJOMPDBM deploy : executor : name: machine-executo r steps : - checkou t - attach_workspace : at: . - run : name: Check directories/file s command: | set - x pwd && ls -a && ls ap p - heroku/instal l - heroku/check-authenticatio n - run : name: Heroku container login, push, releas e working_directory: ap p command: | set - x ls - a heroku container:logi n heroku container:push web -a $HEROKU_APP_NAM E heroku container:release web -a $HEROKU_APP_NAM E - run : name: Finish deplo y command: | set - x echo "Finish deploy"
  80. % heroku authorizations:creat e Creating OAuth Authorization... don e ..

    . Token: LongStringsFooBarrrrrrrrrrrrr r Updated at: ... (PJOUPPVSQSPKFDUT$JSDMF$*EBTICPBSEBOETFU5XP FOWJSPONFOUWBSJBCMFT 'PSEFUBJMFEJOTUSVDUJPOTPOIPXUPEPUIJT XFDBOSFBE UIFPGGJDJBMEPDVNFOUBUJPOIFSF IUUQTDJSDMFDJDPNEPDTFOWWBSTTFUUJOHBO FOWJSPONFOUWBSJBCMFJOBQSPKFDU )&30,6@"11@/".& 5IJTJTUIFOBNFPGPVS)FSPLVBQQMJDBUJPOUIBUXBT EFDJEFECZUIFAIFSPLVDSFBUFADPNNBOE )&30,6@"1*@,&: &OTVSFXFHFUUIFBVUIFOUJDBUJPOUPLFOXJUIUIF DPNNBOEAIFSPLVBVUIPSJ[BUJPOTDSFBUFA BOESFHJTUFS UIFHFOFSBUFEUPLFOUPPVSQSPKFDUT$JSDMF$*EBTICPBSE BT)&30,6@"1*@,&: 4FU$JSDMF$*FOWJSPONFOU
  81. /PXXFGJOBMMZIBWFBQJQFMJOFUIBU VQEBUFTPVSQSPEVDUJPOFOWJSPONFOUXJUI KVTUBHJUQVTI 5IFEFQMPZQJQFMJOFJTBMNPTUGJOJTIFE BOE UIFHSFFOMJHIUIBTCFFOUVSOFEPO 5BEB &YFDVUFUIF$*BOE$%QJQFMJOF /PX BMMXFIBWFUPEPJTHJUQVTIUPUIFSFNPUF(JU)VCSFQPTJUPSZ

    8IFOXFQVTIUPBEFWFMPQNFOUCSBODI POMZUIFCVJMEKPCSVOT 0ODFUIFCVJMEJTDPNQMFUF XFDBONFSHFJUJOUPPVSNBJOSFQPTJUPSZ"GUFSXFEJEUIFNFSHF PQFSBUJPO CPUICVJMEBOEEFQMPZKPCTBSFSVOOJOH
  82. &YFDVUFUIF$*BOE$%QJQFMJOF 8FXJMMMFUZPVLOPXUIFSFTVMUTTPPOMBUFS -FUTMPPLGPSXBSEUPJUʜ

  83. &YFDVUFUIF$*BOE$%QJQFMJOF 8FXJMMMFUZPVLOPXUIFSFTVMUTTPPOMBUFS -FUTMPPLGPSXBSEUPJUʜ  /P XFSFOPUɹ/PXJTUIFSJHIUUJNF 5IFUJNFIBTDPNF

  84. 5IJTJTJU

  85. 5IJTJTJU IUUQTLPLVSBFYIFSPLVBQQDPN

  86. :FBI 8FEJEJU

  87. 5IFGJSTUHPBMXFTFU  XFXFSFBCMFUP BDDPNQMJTITNPPUIMZ

  88. "OEXFIPQFUPHSPX JUJOUIFGVUVSF

  89. *JNBHJOFTVDI BGVUVSFUFDINFFUVQ  3FBMUJNFDPEF TIBSJOH &WFOUOPUJGJFS #MPH $IBUUJOH FUDʜ (

    ´ʔ`)ɻоʢ
  90. *JNBHJOFTVDI BGVUVSFUFDINFFUVQ  3FBMUJNFDPEF TIBSJOH &WFOUOPUJGJFS #MPH $IBUUJOH FUDʜ (

    ´ʔ`)ɻоʢ
  91. 3FBMUJNFʜ  0GDPVSTF -JWF7JFX 3JHIU

  92. 8JUI-JWF7JFX JUXJMMCFFBTZBOE TNBSUUPDSFBUFSFBMUJNFDPEF TIBSJOH XPOUJU 

  93. *DBOUTUPQESFBNJOH

  94. "MMSJHIU *`MMSFMFBTFBMPUPGGFBUVSFTJOUIF 1IPFOJYGSBNFXPSL -FUTEPJU *MPWF1IPFOJY *MPWF&MJYJS *MPWFGMZJP *IBWFOUVTFEJUZFUʜ

  95. *NBHJOBUJPOJTUIFPOMZXFBQPO JOUIFXBSBHBJOTUSFBMJUZ *TOUUIBUSJHIU $IFTIJSF$BU

  96. "OE PIGSJFOET  XFBSFBMM"MJDF XIPVTFT&MJYJSUP SFGJOFPVSJNBHJOBUJPOBOESJEF UIF1IPFOJYGSPNUIFMBOEPG JNBHJOBUJPOUPUIFSFBMXPSMEBU XJMM

  97. LPLVSBFY0SHBOJ[FS 3ZPUBSP*NBIBTIJ !JN@NJPMBC 'JO 5IBOLZPVGPSXBUDIJOH 5IBOLZPVWFSZNVDI