diff --git a/frontend/src/Config/Helpers/Cards/Helpers.elm b/frontend/src/Config/Helpers/Cards/Helpers.elm index 1237246..4e5355d 100755 --- a/frontend/src/Config/Helpers/Cards/Helpers.elm +++ b/frontend/src/Config/Helpers/Cards/Helpers.elm @@ -14,6 +14,7 @@ import Config.Helpers.Format , paragraphFontSize , paragraphSpacing ) +import Config.Helpers.ImageFolders as M exposing (..) import Config.Helpers.Response exposing (contentContainer) import Config.Pages.Debate.Arguments.Records.Template exposing (argument) import Config.Style.Colour exposing (colourTheme) @@ -57,7 +58,7 @@ cardMaker device cardable contents = True C.Argument _ -> - True + False C.Gibberish _ -> True @@ -265,10 +266,21 @@ cardMaker device cardable contents = cardImageMaker : String -> Element msg cardImageMaker image = + let + mobileImageSize = + [ E.width <| px 45 + , E.height <| px 45 + ] + in el [ alignRight , alignTop - , padding 10 + , paddingEach + { top = 20 + , bottom = 0 + , left = 30 + , right = 0 + } ] <| el @@ -287,14 +299,10 @@ cardMaker device cardable contents = ] ++ (case ( device.class, device.orientation ) of ( Phone, Portrait ) -> - [ E.width <| px 45 - , E.height <| px 45 - ] + mobileImageSize ( Tablet, Portrait ) -> - [ E.width <| px 45 - , E.height <| px 45 - ] + mobileImageSize _ -> [ E.width <| px 90 @@ -464,7 +472,7 @@ cardMaker device cardable contents = C.Cuck cuck -> cardWithImage cuck.cuckName - ("/cucks/" ++ cuck.cuckImage ++ "/" ++ cuck.cuckImage ++ ".png") + (imagePathMaker M.Cuck cuck.cuckImage) contents C.BlogArticle blogArticle -> @@ -476,22 +484,20 @@ cardMaker device cardable contents = cardWithImageWithLink blogArticle.isNewTabLink blogArticle.articleName - ("/blog/" ++ blogArticle.articleImage ++ "thumb.png") + (imagePathMaker M.BlogCard blogArticle.articleImage) blogArticle.articleLink contents C.Argument argument -> - cardWithNoImageWithLink - argument.isNewTabLink + cardWithNoImage argument.argumentTitle - argument.proofLink contents C.Gibberish gibberish -> cardWithImageWithLink gibberish.isNewTabLink gibberish.gibberishTitle - ("/gibberish/" ++ gibberish.gibberishImage ++ ".png") + (imagePathMaker M.Gibberish gibberish.gibberishImage) gibberish.gibberishLink contents @@ -499,7 +505,7 @@ cardMaker device cardable contents = cardWithImageWithLink service.isNewTabLink service.serviceName - ("/services/" ++ service.serviceImage ++ ".png") + (imagePathMaker M.Service service.serviceImage) service.serviceLink contents @@ -507,7 +513,7 @@ cardMaker device cardable contents = cardWithImageWithLink debate.isNewTabLink debate.debateTitle - ("/debate/" ++ debate.debateImage ++ ".png") + (imagePathMaker M.Debate debate.debateImage) debate.debateLink contents @@ -515,14 +521,14 @@ cardMaker device cardable contents = cardWithImageWithLink donate.isNewTabLink donate.donateName - ("/donate/" ++ donate.donateImage ++ ".png") + (imagePathMaker M.Donate donate.donateImage) donate.donateLink contents C.Interview interview -> cardWithImage interview.interviewName - ("/interviews/" ++ interview.interviewImage ++ ".png") + (imagePathMaker M.Interviews interview.interviewImage) contents C.NutriDex nutriDex -> diff --git a/frontend/src/Config/Helpers/ImageFolders.elm b/frontend/src/Config/Helpers/ImageFolders.elm new file mode 100644 index 0000000..248c953 --- /dev/null +++ b/frontend/src/Config/Helpers/ImageFolders.elm @@ -0,0 +1,62 @@ +module Config.Helpers.ImageFolders exposing (..) + + +imagePathMaker : ImageFolder -> String -> String +imagePathMaker imageFolder name = + case imageFolder of + Cuck -> + "/" ++ getImageFolderString imageFolder ++ "/" ++ name ++ "/" ++ name ++ ".png" + + _ -> + "/" ++ getImageFolderString imageFolder ++ "/" ++ name ++ ".png" + + +getImageFolderString : ImageFolder -> String +getImageFolderString imageFolder = + case imageFolder of + Interviews -> + "interviews" + + Gibberish -> + "gibberish" + + Cuck -> + "cucks" + + BlogArticle -> + "blog" + + BlogCard -> + "blog/thumbs" + + Argument -> + "arguments" + + Service -> + "services" + + Debate -> + "debate" + + Donate -> + "donate" + + NutriDex -> + "nutridex" + + ServicePage -> + "services" + + +type ImageFolder + = Interviews + | Gibberish + | Cuck + | BlogArticle + | BlogCard + | Argument + | Service + | Debate + | Donate + | NutriDex + | ServicePage diff --git a/frontend/src/Config/Helpers/Price.elm b/frontend/src/Config/Helpers/Price.elm new file mode 100644 index 0000000..55b22b2 --- /dev/null +++ b/frontend/src/Config/Helpers/Price.elm @@ -0,0 +1,51 @@ +module Config.Helpers.Price exposing (..) + +import Config.Style.Colour exposing (colourTheme) +import Config.Style.Transitions exposing (hoverPageButtonDeepDarkOrange, transitionStyleMedium) +import Element as E exposing (..) +import Element.Background as B exposing (color) +import Element.Border as D exposing (rounded) +import Element.Font as F exposing (center) +import Config.Style.Glow exposing (glowDeepDarkGrey) + + +buyButton : String -> String -> Element msg +buyButton price url = + el + [ D.width 5 + , D.rounded 30 + , centerX + , glowDeepDarkGrey + , D.color colourTheme.backgroundLightGrey + , B.color colourTheme.backgroundLightGrey + ] + <| + el + [ B.color colourTheme.textDarkOrange + , D.rounded 30 + , F.size 25 + , F.bold + , transitionStyleMedium + , hoverPageButtonDeepDarkOrange + , paddingEach + { top = 10 + , right = 25 + , bottom = 10 + , left = 25 + } + ] + <| + newTabLink [] + { url = url + , label = + row + [ F.center + , paddingEach + { top = 3 + , right = 0 + , bottom = 0 + , left = 0 + } + ] + [ text price ] + } diff --git a/frontend/src/Config/Helpers/StrengthBar.elm b/frontend/src/Config/Helpers/StrengthBar.elm index e492027..1561979 100755 --- a/frontend/src/Config/Helpers/StrengthBar.elm +++ b/frontend/src/Config/Helpers/StrengthBar.elm @@ -10,12 +10,12 @@ import Element.Border as D barMaker : (Int -> String) -> Int -> Element msg barMaker getTooltip num = el - ([ height <| px 12 - , width fill - , D.rounded 10 - , D.color colourTheme.textDarkGrey - , D.width 2 - , B.gradient + [ height <| px 12 + , width fill + , D.rounded 10 + , D.color colourTheme.textDarkGrey + , D.width 2 + , B.gradient { angle = 1.57 , steps = List.concat @@ -23,9 +23,8 @@ barMaker getTooltip num = , List.repeat (10 - num) colourTheme.barRed ] } - ] - ++ [ tooltip (getTooltip num) ] - ) + , tooltip (getTooltip num) + ] none diff --git a/frontend/src/Config/Pages/Services/Records/ElmBuilds.elm b/frontend/src/Config/Pages/Services/Records/ElmBuilds.elm index 9ea5b7c..32160d8 100755 --- a/frontend/src/Config/Pages/Services/Records/ElmBuilds.elm +++ b/frontend/src/Config/Pages/Services/Records/ElmBuilds.elm @@ -14,7 +14,7 @@ servicesElmBuilds = let name : String name = - "Custom Elm Sites" + "Front End Development" in { serviceImage = formatName name , serviceLink = Path.toString Path.Services_Elm @@ -41,8 +41,8 @@ servicesElmBuilds = , title10 = "" } , articleParagraph = - { paragraph1 = [ text "The site that you're currently viewing this on was written by me in the Elm programming language. I end , chunkMaker servicesElmBuilds.serviceArticle.articleParagraph.paragraph2e. After a while, I realized that I could create high quality work with it, so I'm offering it as a service." ] - , paragraph2 = [ text "Below is an example of a function that I wrote in Elm. In this case, it's the function that is used all over my website to make the strength meters." ] + { paragraph1 = [ text "The site that you're currently viewing this on was written by me in the Elm programming language. In the process of programming this website, I realized that I could create reasonably high quality work with Elm, so I'm offering it as a service at a fee that reflects my skill level. ", text "If you're in the market for a new frontend for your website, please inquire at ", el [ F.bold, F.color colourTheme.textLightOrange ] <| text "nick@upRootNutrition.com", text "." ] + , paragraph2 = [text "Below is an example of a function that I wrote for this site. This particular function renders all of the circular images on all of the site's information cards. Any time you see one of those images, this function is responsible for it."] , paragraph3 = [ text "The source code for this website is viewable on " , newTabLink [] diff --git a/frontend/src/Config/Pages/Services/Records/NixBuilds.elm b/frontend/src/Config/Pages/Services/Records/NixBuilds.elm index 8ecde0e..906800a 100755 --- a/frontend/src/Config/Pages/Services/Records/NixBuilds.elm +++ b/frontend/src/Config/Pages/Services/Records/NixBuilds.elm @@ -41,8 +41,8 @@ servicesNixBuilds = , title10 = "" } , articleParagraph = - { paragraph1 = [ text "NixOS has become popular in my community, with many people choosing to explore it over Windows, MacOS, and other Linux distributions. Naturally, as a consequence of this, I receive numerous requests for help regarding the Nix programming language and NixOS system configuration. So, to fast-track newcomers and to make my life a little bit easier for both of us, I'm offering to build custom NixOS configurations for interested clients." ] - , paragraph2 = [ text "Below is an example of a nix flake that I wrote. In this case, it's the flake that was used to build the development shell for the production of this very website." ] + { paragraph1 = [ text "NixOS has become popular in my community, with many people choosing to explore it over Windows, MacOS, and other Linux distributions. Naturally, as a consequence of this, I receive numerous requests for help regarding the Nix programming language and NixOS system configuration. So, to fast-track newcomers and to make my life a little bit easier for both of us, I'm offering to build custom NixOS configurations for interested clients. ", text "If you're interested in having a custom Nix configuration, or having a pre-existing configuration refactored, please inquire at ", el [ F.bold, F.color colourTheme.textLightOrange ] <| text "nick@upRootNutrition.com", text "." ] + , paragraph2 = [ text "Below is an example of a nix flake that I wrote for the devshell that I used to manage and isolate the development environment for this site. All of the packages, pre-defined settings, and tooling used for this site are managed through this flake." ] , paragraph3 = [ text "The source code for this website's server is viewable on " , newTabLink [] diff --git a/frontend/src/Config/Style/Colour.elm b/frontend/src/Config/Style/Colour.elm index 825fe42..46bd136 100755 --- a/frontend/src/Config/Style/Colour.elm +++ b/frontend/src/Config/Style/Colour.elm @@ -18,6 +18,7 @@ type alias Theme = , backgroundDarkGrey : Color , backgroundDeepDarkGrey : Color , backgroundSpreadsheet : Color + , backgroundSpreadsheetDark : Color , shadow : Color , barGreen : Color , barRed : Color @@ -48,6 +49,7 @@ colourTheme = , backgroundDarkGrey = rgb255 30 30 30 , backgroundDeepDarkGrey = rgb255 20 20 20 , backgroundSpreadsheet = rgb255 36 36 36 + , backgroundSpreadsheetDark = rgb255 26 26 26 , shadow = rgb255 10 10 10 , barGreen = rgb255 0 102 0 , barRed = rgb255 102 0 0 diff --git a/frontend/src/Config/Style/Icons/Icons.elm b/frontend/src/Config/Style/Icons/Icons.elm index 42d7022..d0c0594 100755 --- a/frontend/src/Config/Style/Icons/Icons.elm +++ b/frontend/src/Config/Style/Icons/Icons.elm @@ -900,18 +900,16 @@ construction = ] -construction2 : SvgTypes.OuterPart msg -> Element msg -construction2 inner = +leaving : SvgTypes.OuterPart msg -> Element msg +leaving inner = HeSvg.buildSvg inner { svgAttributes = [ SvgAttr.viewBox "0 0 576 512" - - -- Using elm-svg because typed-svg has no way of setting the fill to currentColor. , SvgAttr.fill "currentColor" ] , svg = [ path - [ SvgAttr.d "M208 64a48 48 0 1 1 96 0 48 48 0 1 1 -96 0zM9.8 214.8c5.1-12.2 19.1-18 31.4-12.9L60.7 210l22.9-38.1C99.9 144.6 129.3 128 161 128c51.4 0 97 32.9 113.3 81.7l34.6 103.7 79.3 33.1 34.2-45.6c6.4-8.5 16.6-13.3 27.2-12.8s20.3 6.4 25.8 15.5l96 160c5.9 9.9 6.1 22.2 .4 32.2s-16.3 16.2-27.8 16.2l-256 0c-11.1 0-21.4-5.7-27.2-15.2s-6.4-21.2-1.4-31.1l16-32c5.4-10.8 16.5-17.7 28.6-17.7l32 0 22.5-30L22.8 246.2c-12.2-5.1-18-19.1-12.9-31.4zm82.8 91.8l112 48c11.8 5 19.4 16.6 19.4 29.4l0 96c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-74.9-60.6-26-37 111c-5.6 16.8-23.7 25.8-40.5 20.2S-3.9 486.6 1.6 469.9l48-144 11-33 32 13.7z" + [ SvgAttr.d "M320 0c-17.7 0-32 14.3-32 32s14.3 32 32 32l82.7 0L201.4 265.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L448 109.3l0 82.7c0 17.7 14.3 32 32 32s32-14.3 32-32l0-160c0-17.7-14.3-32-32-32L320 0zM80 32C35.8 32 0 67.8 0 112L0 432c0 44.2 35.8 80 80 80l320 0c44.2 0 80-35.8 80-80l0-112c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 112c0 8.8-7.2 16-16 16L80 448c-8.8 0-16-7.2-16-16l0-320c0-8.8 7.2-16 16-16l112 0c17.7 0 32-14.3 32-32s-14.3-32-32-32L80 32z" ] [] ] diff --git a/frontend/src/Layouts/Navbar.elm b/frontend/src/Layouts/Navbar.elm index d3a76ee..e54cbda 100755 --- a/frontend/src/Layouts/Navbar.elm +++ b/frontend/src/Layouts/Navbar.elm @@ -21,6 +21,7 @@ import Config.Style.Icons.Icons , home , hyperBlog , interviews + , leaving , lock , mastodon , nutriDex @@ -608,6 +609,12 @@ makeItem input route = ) [ itemIcon input route , itemText input route + , case route.isNewTabLink of + True -> + itemLeavingIcon input route + + False -> + none ] , url = route.url } @@ -648,6 +655,27 @@ itemIcon input route = } +itemLeavingIcon : NavbarInput contentMsg -> RowInput contentMsg -> Element contentMsg +itemLeavingIcon input route = + el + [ height <| px 50 + , width <| px 20 + , E.alignRight + , paddingXY 10 0 + ] + <| + leaving + { elementAttributes = + [ E.alignRight + , E.alignTop + , centerY + ] + , sharedModel = route.sharedModel + , svgAttributes = + [ SvgAttr.width "15" ] + } + + itemText : NavbarInput contentMsg -> RowInput contentMsg -> Element contentMsg itemText input route = el @@ -658,6 +686,12 @@ itemText input route = else transparent True , F.bold + , paddingEach + { top = 6 + , right = 0 + , bottom = 3 + , left = 0 + } ] <| text route.name diff --git a/frontend/src/Pages/Debate/Arguments.elm b/frontend/src/Pages/Debate/Arguments.elm index aa16c6d..50acddc 100755 --- a/frontend/src/Pages/Debate/Arguments.elm +++ b/frontend/src/Pages/Debate/Arguments.elm @@ -6,12 +6,14 @@ import Config.Helpers.Cards.Types as C import Config.Helpers.Converters exposing (toTitleCase) import Config.Helpers.Format exposing - ( paragraphFontSize + ( headerFontSizeSmall + , paragraphFontSize , paragraphSpacing ) import Config.Helpers.Headers.Helpers exposing (..) import Config.Helpers.Headers.Records exposing (argumentHeader) import Config.Helpers.Headers.Types as R exposing (..) +import Config.Helpers.ImageFolders as M exposing (..) import Config.Helpers.Response exposing ( pageList @@ -141,21 +143,119 @@ debateList device = [ [ headerMaker (R.Arguments argumentHeader) ] , List.map (\argument -> - cardMaker device (C.Argument argument) (contentList argument) + cardMaker device (C.Argument argument) (contentList device argument) ) argumentList ] -contentList : Argument -> List (Element msg) -contentList argument = - [ summaryMakerDesktop argument - , strengthBar argument - , tableMaker argument +contentList : Device -> Argument -> List (Element msg) +contentList device argument = + [ row + [ width fill + , paddingEach + { top = + case ( device.class, device.orientation ) of + ( Phone, Portrait ) -> + 8 + + ( Tablet, Portrait ) -> + 8 + + _ -> + 0 + , right = 0 + , bottom = 0 + , left = 0 + } + ] + [ column [ width fill, spacing 8 ] + [ summaryMakerDesktop argument + , strengthBar argument + ] + , case ( device.class, device.orientation ) of + ( Phone, Portrait ) -> + none + + ( Tablet, Portrait ) -> + none + + _ -> + argumentImageMaker argument + ] + , tableMaker device argument , desktopFormalizationMaker argument + , proofTreeButton argument.proofLink ] +argumentImageMaker : Argument -> Element msg +argumentImageMaker argument = + el + [ alignRight + , alignTop + , centerY + , paddingEach + { top = 0 + , right = 0 + , bottom = 0 + , left = 20 + } + ] + <| + el + [ D.rounded 10 + , D.width 3 + , D.color colourTheme.backgroundLightGrey + , B.color colourTheme.backgroundLightGrey + ] + <| + E.image + [ alignRight + , alignTop + , D.rounded 10 + , clip + , E.width <| px 65 + , E.height <| px 65 + ] + { src = imagePathMaker M.Argument argument.argumentImage + , description = "" + } + + +proofTreeButton : String -> Element msg +proofTreeButton url = + newTabLink + [ alignTop + , alignRight + , paddingXY 0 5 + ] + { url = url + , label = + el + [ F.color colourTheme.textLightGrey + , B.color colourTheme.textDarkOrange + , D.rounded 10 + , paddingEach + { top = 6 + , bottom = 3 + , left = 10 + , right = 10 + } + , mouseOver + [ F.color colourTheme.textLightOrange + , B.color colourTheme.textDeepDarkOrange + ] + , transitionStyleSlow + , headerFontSizeSmall + , F.bold + ] + <| + text + "Proof Tree" + } + + infoSpacing = E.width <| px 100 @@ -165,15 +265,12 @@ propositionMaker = column [ E.alignTop, E.alignLeft ] [ paragraph - ([ F.color colourTheme.textLightGrey - , paragraphSpacing - , paragraphFontSize - , F.bold - ] - ++ [ F.size 18 - , infoSpacing - ] - ) + [ F.color colourTheme.textLightGrey + , paragraphSpacing + , headerFontSizeSmall + , F.bold + , infoSpacing + ] [ el [ tooltip "A proposition is a declarative statement that can be evaluated as either true or false, and which serves as the basis for debate." @@ -432,8 +529,8 @@ getConfidenceTooltip num = "Confidence level out of expected range." -tableMaker : Argument -> Element msg -tableMaker argument = +tableMaker : Device -> Argument -> Element msg +tableMaker device argument = let cellPadding : Attribute msg cellPadding = @@ -454,12 +551,22 @@ tableMaker argument = ] <| E.table - [ D.rounded 10 - , D.width 2 - , D.color colourTheme.textDarkGrey - , clip - , B.color colourTheme.backgroundSpreadsheet - ] + ([ D.rounded 10 + , D.width 2 + , D.color colourTheme.textDarkGrey + , clip + ] + ++ (case ( device.class, device.orientation ) of + ( Phone, Portrait ) -> + [ B.color colourTheme.backgroundSpreadsheet ] + + ( Tablet, Portrait ) -> + [ B.color colourTheme.backgroundSpreadsheet ] + + _ -> + [] + ) + ) { data = argument.definitionTable , columns = [ { header = diff --git a/frontend/src/Pages/Donate.elm b/frontend/src/Pages/Donate.elm index daff3f0..a4110d8 100755 --- a/frontend/src/Pages/Donate.elm +++ b/frontend/src/Pages/Donate.elm @@ -391,13 +391,23 @@ tableMaker donate device = ] <| E.table - [ spacing 0 - , D.rounded 10 - , D.width 2 - , D.color colourTheme.textDarkGrey - , B.color colourTheme.backgroundSpreadsheet - , clip - ] + ([ spacing 0 + , D.rounded 10 + , D.width 2 + , D.color colourTheme.textDarkGrey + , clip + ] + ++ (case ( device.class, device.orientation ) of + ( Phone, Portrait ) -> + [ B.color colourTheme.backgroundSpreadsheet ] + + ( Tablet, Portrait ) -> + [ B.color colourTheme.backgroundSpreadsheet ] + + _ -> + [] + ) + ) { data = donate.donateFeatures , columns = List.map createColumn diff --git a/frontend/src/Pages/Home_.elm b/frontend/src/Pages/Home_.elm index e3dec9c..c001b27 100755 --- a/frontend/src/Pages/Home_.elm +++ b/frontend/src/Pages/Home_.elm @@ -17,8 +17,7 @@ import Config.Style.Colour exposing (colourTheme) import Config.Style.Glow exposing (glowDeepDarkGrey) import Config.Style.Icons.Icons exposing - ( construction2 - , upRootLarge + ( upRootLarge , upRootMedium , upRootSmall ) diff --git a/frontend/src/Pages/Nutridex.elm b/frontend/src/Pages/Nutridex.elm index 91aca7d..bb0b10c 100755 --- a/frontend/src/Pages/Nutridex.elm +++ b/frontend/src/Pages/Nutridex.elm @@ -14,6 +14,7 @@ import Config.Helpers.Format import Config.Helpers.Headers.Helpers exposing (..) import Config.Helpers.Headers.Records exposing (nutriDexHeader) import Config.Helpers.Headers.Types as R exposing (..) +import Config.Helpers.Price exposing (buyButton) import Config.Helpers.Response exposing ( pageList @@ -37,6 +38,7 @@ import Config.Style.Transitions , hoverPageButtonDeepDarkOrange , transitionStyleFast , transitionStyleMedium + , transitionStyleSlow ) import Effect exposing (Effect) import Element as E exposing (..) @@ -266,31 +268,7 @@ featureList nutridex device = ] [ html nutriDexLogo ] - , row - [ D.width 5 - , D.rounded 30 - , centerX - , glowDeepDarkGrey - , D.color colourTheme.backgroundLightGrey - , B.color colourTheme.backgroundLightGrey - ] - [ row - [ B.color colourTheme.textDarkOrange - , D.rounded 30 - , F.size 25 - , F.bold - , transitionStyleMedium - , hoverPageButtonDeepDarkOrange - , paddingEach - { top = 10 - , right = 25 - , bottom = 10 - , left = 25 - } - ] - [ price - ] - ] + , buyButton "$20" "https://uprootnutrition.myshopify.com/cart/31192710807615:1?channel=buy_button" , column [ centerX ] [ column @@ -348,9 +326,12 @@ linkFormat = [ F.color colourTheme.textLightGrey , paragraphSpacing , paragraphFontSize + , F.color colourTheme.textLightOrange + , mouseOver + [ F.color colourTheme.textDarkOrange + ] + , transitionStyleMedium ] - ++ [ F.color colourTheme.textLightOrange - ] nutriDexBodyMaker : Device -> Element msg diff --git a/frontend/src/Pages/Services/Analysis.elm b/frontend/src/Pages/Services/Analysis.elm index eeba80e..772dde0 100755 --- a/frontend/src/Pages/Services/Analysis.elm +++ b/frontend/src/Pages/Services/Analysis.elm @@ -4,9 +4,11 @@ import Config.Helpers.Cards.Helpers exposing (cardMaker) import Config.Helpers.Cards.Types as C exposing (..) import Config.Helpers.Format exposing (..) import Config.Helpers.Headers.Types exposing (Header) +import Config.Helpers.Price exposing (buyButton) import Config.Helpers.Response exposing (pageList, topLevelContainer) import Config.Helpers.ServiceFormat exposing (..) import Config.Helpers.ToolTip exposing (..) +import Config.Helpers.Viewport exposing (resetViewport) import Config.Pages.Services.Records.DebateAnalysis exposing (..) import Config.Style.Colour exposing (colourTheme) import Config.Style.Transitions @@ -28,7 +30,6 @@ import Route exposing (Route) import Route.Path as Path import Shared import View exposing (View) -import Config.Helpers.Viewport exposing (resetViewport) page : Shared.Model -> Route () -> Page Model Msg @@ -65,7 +66,6 @@ init () = - -- UPDATE @@ -136,5 +136,6 @@ contentList = , numberMaker servicesDebateAnalysis.serviceArticle.articleListEntries.list1 , titleMaker servicesDebateAnalysis.serviceArticle.articleTitles.title2 , bulletPointMaker servicesDebateAnalysis.serviceArticle.articleListEntries.list2 + , buyButton "Book!" "https://buy.stripe.com/14k3dr4Zh8p6c3mbIJ" ] ] diff --git a/frontend/src/Pages/Services/Coaching.elm b/frontend/src/Pages/Services/Coaching.elm index 2e6c19d..d78b09a 100755 --- a/frontend/src/Pages/Services/Coaching.elm +++ b/frontend/src/Pages/Services/Coaching.elm @@ -5,6 +5,7 @@ import Config.Helpers.Cards.Types as C import Config.Helpers.Format exposing (..) import Config.Helpers.Headers.Helpers exposing (..) import Config.Helpers.Headers.Types exposing (Header) +import Config.Helpers.Price exposing (buyButton) import Config.Helpers.Response exposing ( pageList @@ -12,6 +13,7 @@ import Config.Helpers.Response ) import Config.Helpers.ServiceFormat exposing (..) import Config.Helpers.ToolTip exposing (..) +import Config.Helpers.Viewport exposing (resetViewport) import Config.Pages.Services.Records.DebateCoaching exposing (servicesDebateCoaching) import Config.Style.Colour exposing (colourTheme) import Config.Style.Transitions @@ -33,7 +35,6 @@ import Route exposing (Route) import Route.Path as Path import Shared import View exposing (View) -import Config.Helpers.Viewport exposing (resetViewport) page : Shared.Model -> Route () -> Page Model Msg @@ -70,7 +71,6 @@ init () = - -- UPDATE @@ -147,5 +147,6 @@ contentList = , highlightedBlockMaker servicesDebateCoaching.serviceArticle.articleTitles.title6 servicesDebateCoaching.serviceArticle.articleListEntries.list6 , highlightedBlockMaker servicesDebateCoaching.serviceArticle.articleTitles.title7 servicesDebateCoaching.serviceArticle.articleListEntries.list7 , highlightedBlockMaker servicesDebateCoaching.serviceArticle.articleTitles.title8 servicesDebateCoaching.serviceArticle.articleListEntries.list8 + , buyButton "Book!" "https://buy.stripe.com/14k01f3Vd6gY6J2146" ] ] diff --git a/frontend/src/Pages/Services/Elm.elm b/frontend/src/Pages/Services/Elm.elm index 74e4778..8b33eca 100755 --- a/frontend/src/Pages/Services/Elm.elm +++ b/frontend/src/Pages/Services/Elm.elm @@ -12,6 +12,7 @@ import Config.Helpers.Response ) import Config.Helpers.ServiceFormat exposing (..) import Config.Helpers.ToolTip exposing (..) +import Config.Helpers.Viewport exposing (resetViewport) import Config.Pages.Services.Records.ElmBuilds exposing (servicesElmBuilds) import Config.Style.Colour exposing (..) import Config.Style.Transitions @@ -33,7 +34,6 @@ import Route exposing (Route) import Route.Path as Path import Shared import View exposing (View) -import Config.Helpers.Viewport exposing (resetViewport) page : Shared.Model -> Route () -> Page Model Msg @@ -70,7 +70,6 @@ init () = - -- UPDATE @@ -115,7 +114,7 @@ elmBuildsContainer device = elmBuildsList : Device -> Element msg elmBuildsList device = - column + column (case ( device.class, device.orientation ) of _ -> pageList device @@ -170,24 +169,16 @@ elmCodeRenderer = [ renderCodeLine syntaxTheme [ text "" |> el [ paddingXY 0 0 ] - , text "barMaker" + , text "cardImageMaker" |> el [ F.color syntaxTheme.key ] , text " : " |> el [ F.color syntaxTheme.operator ] - , text "(" - |> el [ F.color syntaxTheme.punctuation ] - , text "Int" + , text "String" |> el [ F.color syntaxTheme.keyword ] , text " -> " |> el [ F.color syntaxTheme.operator ] , text "String" |> el [ F.color syntaxTheme.keyword ] - , text ")" - |> el [ F.color syntaxTheme.punctuation ] - , text " -> " - |> el [ F.color syntaxTheme.operator ] - , text "Int" - |> el [ F.color syntaxTheme.keyword ] , text " -> " |> el [ F.color syntaxTheme.operator ] , text "Element" @@ -197,13 +188,67 @@ elmCodeRenderer = , renderCodeLine syntaxTheme [ text "" |> el [ paddingXY 0 0 ] - , text "barMaker" + , text "cardImageMaker" |> el [ F.color syntaxTheme.key ] - , text " getToolTip" - , text " num" + , text " image blurb" , text " =" |> el [ F.color syntaxTheme.operator ] ] + , renderCodeLine syntaxTheme + [ text "" + |> el [ paddingXY 16 0 ] + , text "let" + |> el [ F.color syntaxTheme.keyword ] + ] + , renderCodeLine syntaxTheme + [ text "" + |> el [ paddingXY 32 0 ] + , text "mobileImageSize" + , text " =" + |> el [ F.color syntaxTheme.operator ] + ] + , renderCodeLine syntaxTheme + [ text "" + |> el [ paddingXY 48 0 ] + , text "[" + |> el [ F.color syntaxTheme.punctuation ] + , text " E" + , text "." + |> el [ F.color syntaxTheme.punctuation ] + , text "width" + , text " <| " + |> el [ F.color syntaxTheme.operator ] + , text "px" + , text " 45" + |> el [ F.color syntaxTheme.string ] + ] + , renderCodeLine syntaxTheme + [ text "" + |> el [ paddingXY 48 0 ] + , text "," + |> el [ F.color syntaxTheme.punctuation ] + , text " E" + , text "." + |> el [ F.color syntaxTheme.punctuation ] + , text "height" + , text " <| " + |> el [ F.color syntaxTheme.operator ] + , text "px" + , text " 45" + |> el [ F.color syntaxTheme.string ] + ] + , renderCodeLine syntaxTheme + [ text "" + |> el [ paddingXY 48 0 ] + , text "]" + |> el [ F.color syntaxTheme.punctuation ] + ] + , renderCodeLine syntaxTheme + [ text "" + |> el [ paddingXY 16 0 ] + , text "in" + |> el [ F.color syntaxTheme.keyword ] + ] , renderCodeLine syntaxTheme [ text "" |> el [ paddingXY 16 0 ] @@ -211,197 +256,307 @@ elmCodeRenderer = ] , renderCodeLine syntaxTheme [ text "" - |> el [ paddingXY 28 0 ] - , text "(" - |> el [ F.color syntaxTheme.punctuation ] + |> el [ paddingXY 32 0 ] , text "[" |> el [ F.color syntaxTheme.punctuation ] - , text " Element" - |> el [ F.color syntaxTheme.keyword ] - , text "." - |> el [ F.color syntaxTheme.punctuation ] - , text "height" - , text " <| " - |> el [ F.color syntaxTheme.operator ] - , text "px" - , text " 12" - |> el [ F.color syntaxTheme.string ] + , text " alignRight" ] , renderCodeLine syntaxTheme [ text "" |> el [ paddingXY 32 0 ] , text "," |> el [ F.color syntaxTheme.punctuation ] - , text " Element" - |> el [ F.color syntaxTheme.keyword ] - , text "." - |> el [ F.color syntaxTheme.punctuation ] - , text "width" - , text " fill" + , text " alignTop" ] , renderCodeLine syntaxTheme [ text "" |> el [ paddingXY 32 0 ] , text "," |> el [ F.color syntaxTheme.punctuation ] - , text " Border" - |> el [ F.color syntaxTheme.keyword ] - , text "." - |> el [ F.color syntaxTheme.punctuation ] - , text "rounded" + , text " padding" , text " 10" |> el [ F.color syntaxTheme.string ] ] , renderCodeLine syntaxTheme [ text "" |> el [ paddingXY 32 0 ] + , text "]" + |> el [ F.color syntaxTheme.punctuation ] + ] + , renderCodeLine syntaxTheme + [ text "" + |> el [ paddingXY 16 0 ] + , text "<|" + |> el [ F.color syntaxTheme.operator ] + ] + , renderCodeLine syntaxTheme + [ text "" + |> el [ paddingXY 32 0 ] + , text "el" + ] + , renderCodeLine syntaxTheme + [ text "" + |> el [ paddingXY 48 0 ] + , text "[" + |> el [ F.color syntaxTheme.punctuation ] + , text " D" + , text "." + |> el [ F.color syntaxTheme.punctuation ] + , text "rounded" + , text " 100" + |> el [ F.color syntaxTheme.string ] + ] + , renderCodeLine syntaxTheme + [ text "" + |> el [ paddingXY 48 0 ] , text "," |> el [ F.color syntaxTheme.punctuation ] - , text " Border" - |> el [ F.color syntaxTheme.keyword ] + , text " D" + , text "." + |> el [ F.color syntaxTheme.punctuation ] + , text "width" + , text " 5" + |> el [ F.color syntaxTheme.string ] + ] + , renderCodeLine syntaxTheme + [ text "" + |> el [ paddingXY 48 0 ] + , text "," + |> el [ F.color syntaxTheme.punctuation ] + , text " glowDeepDarkGrey" + ] + , renderCodeLine syntaxTheme + [ text "" + |> el [ paddingXY 48 0 ] + , text "," + |> el [ F.color syntaxTheme.punctuation ] + , text " D" , text "." |> el [ F.color syntaxTheme.punctuation ] , text "color" , text " colourTheme" , text "." |> el [ F.color syntaxTheme.punctuation ] - , text "textDarkGrey" - ] - , renderCodeLine syntaxTheme - [ text "" - |> el [ paddingXY 32 0 ] - , text "," - |> el [ F.color syntaxTheme.punctuation ] - , text " Border" - |> el [ F.color syntaxTheme.keyword ] - , text "." - |> el [ F.color syntaxTheme.punctuation ] - , text "width" - , text " 2" - ] - , renderCodeLine syntaxTheme - [ text "" - |> el [ paddingXY 32 0 ] - , text "," - |> el [ F.color syntaxTheme.punctuation ] - , text " Background" - |> el [ F.color syntaxTheme.keyword ] - , text "." - |> el [ F.color syntaxTheme.punctuation ] - , text "gradient" - ] - , renderCodeLine syntaxTheme - [ text "" - |> el [ paddingXY 48 0 ] - , text "{" - |> el [ F.color syntaxTheme.punctuation ] - , text " angle" - , text " = " - |> el [ F.color syntaxTheme.operator ] - , text "1.57" - |> el [ F.color syntaxTheme.string ] + , text "backgroundDarkGrey" ] , renderCodeLine syntaxTheme [ text "" |> el [ paddingXY 48 0 ] , text "," |> el [ F.color syntaxTheme.punctuation ] - , text " steps" - , text " = " - ] - , renderCodeLine syntaxTheme - [ text "" - |> el [ paddingXY 56 0 ] - , text "List" - |> el [ F.color syntaxTheme.keyword ] + , text " B" , text "." |> el [ F.color syntaxTheme.punctuation ] - , text "concat" - ] - , renderCodeLine syntaxTheme - [ text "" - |> el [ paddingXY 62 0 ] - , text "[ " - |> el [ F.color syntaxTheme.punctuation ] - , text "List" - |> el [ F.color syntaxTheme.keyword ] - , text "." - |> el [ F.color syntaxTheme.punctuation ] - , text "repeat" - , text " num " - , text "colourTheme" - , text "." - |> el [ F.color syntaxTheme.punctuation ] - , text "barGreen" - ] - , renderCodeLine syntaxTheme - [ text "" - |> el [ paddingXY 62 0 ] - , text ", " - |> el [ F.color syntaxTheme.punctuation ] - , text "List" - |> el [ F.color syntaxTheme.keyword ] - , text "." - |> el [ F.color syntaxTheme.punctuation ] - , text "repeat" - , text " (" - |> el [ F.color syntaxTheme.punctuation ] - , text "10" - |> el [ F.color syntaxTheme.string ] - , text " - " - |> el [ F.color syntaxTheme.operator ] - , text "num" - , text " )" - |> el [ F.color syntaxTheme.punctuation ] + , text "color" , text " colourTheme" , text "." |> el [ F.color syntaxTheme.punctuation ] - , text "barRed" + , text "backgroundDarkGrey" ] , renderCodeLine syntaxTheme [ text "" - |> el [ paddingXY 62 0 ] + |> el [ paddingXY 48 0 ] , text "]" |> el [ F.color syntaxTheme.punctuation ] ] + , renderCodeLine syntaxTheme + [ text "" + |> el [ paddingXY 32 0 ] + , text "<|" + |> el [ F.color syntaxTheme.operator ] + ] , renderCodeLine syntaxTheme [ text "" |> el [ paddingXY 48 0 ] + , text "E" + , text "." + |> el [ F.color syntaxTheme.punctuation ] + , text "image" + ] + , renderCodeLine syntaxTheme + [ text "" + |> el [ paddingXY 64 0 ] + , text "(" + |> el [ F.color syntaxTheme.punctuation ] + , text "[" + |> el [ F.color syntaxTheme.punctuation ] + , text " alignRight" + ] + , renderCodeLine syntaxTheme + [ text "" + |> el [ paddingXY 64 0 ] + , text "," + |> el [ F.color syntaxTheme.punctuation ] + , text " alignTop" + ] + , renderCodeLine syntaxTheme + [ text "" + |> el [ paddingXY 64 0 ] + , text "," + |> el [ F.color syntaxTheme.punctuation ] + , text " D" + , text "." + |> el [ F.color syntaxTheme.punctuation ] + , text "rounded" + , text " 100" + |> el [ F.color syntaxTheme.string ] + ] + , renderCodeLine syntaxTheme + [ text "" + |> el [ paddingXY 64 0 ] + , text "," + |> el [ F.color syntaxTheme.punctuation ] + , text " clip" + ] + , renderCodeLine syntaxTheme + [ text "" + |> el [ paddingXY 64 0 ] + , text "]" + |> el [ F.color syntaxTheme.punctuation ] + ] + , renderCodeLine syntaxTheme + [ text "" + |> el [ paddingXY 64 0 ] + , text "++" + |> el [ F.color syntaxTheme.operator ] + , text " (" + |> el [ F.color syntaxTheme.punctuation ] + , text "case" + |> el [ F.color syntaxTheme.keyword ] + , text " (" + |> el [ F.color syntaxTheme.punctuation ] + , text " device" + , text "." + |> el [ F.color syntaxTheme.punctuation ] + , text "class" + , text "," + |> el [ F.color syntaxTheme.punctuation ] + , text " device" + , text "." + |> el [ F.color syntaxTheme.punctuation ] + , text "orientation" + , text " )" + |> el [ F.color syntaxTheme.punctuation ] + , text " of" + |> el [ F.color syntaxTheme.keyword ] + ] + , renderCodeLine syntaxTheme + [ text "" + |> el [ paddingXY 80 0 ] + , text "(" + |> el [ F.color syntaxTheme.punctuation ] + , text " Phone" + , text "," + |> el [ F.color syntaxTheme.punctuation ] + , text " Portrait" + , text " )" + |> el [ F.color syntaxTheme.punctuation ] + , text " ->" + |> el [ F.color syntaxTheme.operator ] + ] + , renderCodeLine syntaxTheme + [ text "" + |> el [ paddingXY 96 0 ] + , text "mobileImageSize" + ] + , renderCodeLine syntaxTheme + [ text "" + |> el [ paddingXY 80 0 ] + , text "(" + |> el [ F.color syntaxTheme.punctuation ] + , text " Tablet" + , text "," + |> el [ F.color syntaxTheme.punctuation ] + , text " Portrait" + , text " )" + |> el [ F.color syntaxTheme.punctuation ] + , text " ->" + |> el [ F.color syntaxTheme.operator ] + ] + , renderCodeLine syntaxTheme + [ text "" + |> el [ paddingXY 96 0 ] + , text "mobileImageSize" + ] + , renderCodeLine syntaxTheme + [ text "" + |> el [ paddingXY 80 0 ] + , text "_" + , text " ->" + |> el [ F.color syntaxTheme.operator ] + ] + , renderCodeLine syntaxTheme + [ text "" + |> el [ paddingXY 96 0 ] + , text "[" + |> el [ F.color syntaxTheme.punctuation ] + , text " E" + , text "." + |> el [ F.color syntaxTheme.punctuation ] + , text "width" + , text " <| " + |> el [ F.color syntaxTheme.operator ] + , text "px" + , text " 90" + |> el [ F.color syntaxTheme.string ] + ] + , renderCodeLine syntaxTheme + [ text "" + |> el [ paddingXY 96 0 ] + , text "," + |> el [ F.color syntaxTheme.punctuation ] + , text " E" + , text "." + |> el [ F.color syntaxTheme.punctuation ] + , text "height" + , text " <| " + |> el [ F.color syntaxTheme.operator ] + , text "px" + , text " 90" + |> el [ F.color syntaxTheme.string ] + ] + , renderCodeLine syntaxTheme + [ text "" + |> el [ paddingXY 96 0 ] + , text "]" + |> el [ F.color syntaxTheme.punctuation ] + ] + , renderCodeLine syntaxTheme + [ text "" + |> el [ paddingXY 64 0 ] + , text ")" + |> el [ F.color syntaxTheme.punctuation ] + ] + , renderCodeLine syntaxTheme + [ text "" + |> el [ paddingXY 64 0 ] + , text ")" + |> el [ F.color syntaxTheme.punctuation ] + ] + , renderCodeLine syntaxTheme + [ text "" + |> el [ paddingXY 64 0 ] + , text "{" + |> el [ F.color syntaxTheme.punctuation ] + , text " src" + , text " = " + |> el [ F.color syntaxTheme.operator ] + , text "image" + ] + , renderCodeLine syntaxTheme + [ text "" + |> el [ paddingXY 64 0 ] + , text "," + |> el [ F.color syntaxTheme.punctuation ] + , text " description" + , text " = " + |> el [ F.color syntaxTheme.operator ] + , text "blurb" + ] + , renderCodeLine syntaxTheme + [ text "" + |> el [ paddingXY 64 0 ] , text "}" |> el [ F.color syntaxTheme.punctuation ] ] - , renderCodeLine syntaxTheme - [ text "" - |> el [ paddingXY 40 0 ] - , text "]" - |> el [ F.color syntaxTheme.punctuation ] - ] - , renderCodeLine syntaxTheme - [ text "" - |> el [ paddingXY 48 0 ] - , text "++" - |> el [ F.color syntaxTheme.operator ] - , text " [ " - |> el [ F.color syntaxTheme.punctuation ] - , text "tooltip" - , text " (" - |> el [ F.color syntaxTheme.punctuation ] - , text "getToolTip" - , text " num" - , text ")" - |> el [ F.color syntaxTheme.punctuation ] - , text " ]" - |> el [ F.color syntaxTheme.punctuation ] - ] - , renderCodeLine syntaxTheme - [ text "" - |> el [ paddingXY 28 0 ] - , text ")" - |> el [ F.color syntaxTheme.punctuation ] - ] - , renderCodeLine syntaxTheme - [ text "" - |> el [ paddingXY 28 0 ] - , text "none" - ] ] diff --git a/frontend/src/Pages/Services/Nix.elm b/frontend/src/Pages/Services/Nix.elm index caa96ef..6febb83 100755 --- a/frontend/src/Pages/Services/Nix.elm +++ b/frontend/src/Pages/Services/Nix.elm @@ -12,6 +12,7 @@ import Config.Helpers.Response ) import Config.Helpers.ServiceFormat exposing (..) import Config.Helpers.ToolTip exposing (..) +import Config.Helpers.Viewport exposing (resetViewport) import Config.Pages.Services.Records.NixBuilds exposing (servicesNixBuilds) import Config.Style.Colour exposing (..) import Config.Style.Transitions @@ -33,7 +34,6 @@ import Route exposing (Route) import Route.Path as Path import Shared import View exposing (View) -import Config.Helpers.Viewport exposing (resetViewport) page : Shared.Model -> Route () -> Page Model Msg @@ -70,7 +70,6 @@ init () = - -- UPDATE diff --git a/frontend/src/Pages/Services/Nutrition.elm b/frontend/src/Pages/Services/Nutrition.elm index 1a1c57b..f466067 100755 --- a/frontend/src/Pages/Services/Nutrition.elm +++ b/frontend/src/Pages/Services/Nutrition.elm @@ -5,6 +5,7 @@ import Config.Helpers.Cards.Types as C import Config.Helpers.Format exposing (..) import Config.Helpers.Headers.Helpers exposing (..) import Config.Helpers.Headers.Types exposing (Header) +import Config.Helpers.Price exposing (buyButton) import Config.Helpers.Response exposing ( pageList @@ -139,5 +140,6 @@ contentList = , numberMaker servicesNutritionScience.serviceArticle.articleListEntries.list1 , titleMaker servicesNutritionScience.serviceArticle.articleTitles.title2 , bulletPointMaker servicesNutritionScience.serviceArticle.articleListEntries.list2 + , buyButton "Book!" "https://buy.stripe.com/5kA5lz77pdJq6J28wz" ] ] diff --git a/frontend/static/blog/bigfatsurprisethumb.png b/frontend/static/blog/thumbs/bigfatsurprise.png similarity index 100% rename from frontend/static/blog/bigfatsurprisethumb.png rename to frontend/static/blog/thumbs/bigfatsurprise.png diff --git a/frontend/static/blog/everettvegansthumb.png b/frontend/static/blog/thumbs/everettvegans.png similarity index 100% rename from frontend/static/blog/everettvegansthumb.png rename to frontend/static/blog/thumbs/everettvegans.png diff --git a/frontend/static/blog/huntergatherersthumb.png b/frontend/static/blog/thumbs/huntergatherers.png similarity index 100% rename from frontend/static/blog/huntergatherersthumb.png rename to frontend/static/blog/thumbs/huntergatherers.png diff --git a/frontend/static/blog/meatapologeticsthumb.png b/frontend/static/blog/thumbs/meatapologetics.png similarity index 100% rename from frontend/static/blog/meatapologeticsthumb.png rename to frontend/static/blog/thumbs/meatapologetics.png diff --git a/frontend/static/blog/nagragoodrichthumb.png b/frontend/static/blog/thumbs/nagragoodrich.png similarity index 100% rename from frontend/static/blog/nagragoodrichthumb.png rename to frontend/static/blog/thumbs/nagragoodrich.png diff --git a/frontend/static/blog/plantbasedmetathumb.png b/frontend/static/blog/thumbs/plantbasedmeta.png similarity index 100% rename from frontend/static/blog/plantbasedmetathumb.png rename to frontend/static/blog/thumbs/plantbasedmeta.png diff --git a/frontend/static/blog/quacksmashingthumb.png b/frontend/static/blog/thumbs/quacksmashing.png similarity index 100% rename from frontend/static/blog/quacksmashingthumb.png rename to frontend/static/blog/thumbs/quacksmashing.png diff --git a/frontend/static/blog/sapiendietthumb.png b/frontend/static/blog/thumbs/sapiendiet.png similarity index 100% rename from frontend/static/blog/sapiendietthumb.png rename to frontend/static/blog/thumbs/sapiendiet.png diff --git a/frontend/static/blog/seedoilsthumb.png b/frontend/static/blog/thumbs/seedoils.png similarity index 100% rename from frontend/static/blog/seedoilsthumb.png rename to frontend/static/blog/thumbs/seedoils.png diff --git a/frontend/static/blog/shenanigansthumb.png b/frontend/static/blog/thumbs/shenanigans.png similarity index 100% rename from frontend/static/blog/shenanigansthumb.png rename to frontend/static/blog/thumbs/shenanigans.png diff --git a/frontend/static/blog/sweetdeceptionthumb.png b/frontend/static/blog/thumbs/sweetdeception.png similarity index 100% rename from frontend/static/blog/sweetdeceptionthumb.png rename to frontend/static/blog/thumbs/sweetdeception.png diff --git a/frontend/static/services/customelmsites.png b/frontend/static/services/frontenddevelopment.png similarity index 100% rename from frontend/static/services/customelmsites.png rename to frontend/static/services/frontenddevelopment.png