Compare commits

..

No commits in common. "main" and "em_change-site" have entirely different histories.

17 changed files with 443 additions and 745 deletions

View File

@ -1,25 +1,24 @@
---
kind: pipeline
name: deploy to recipes.coopcloud.tech
name: deploy to dev.apps.coopcloud.tech
steps:
- name: build image
image: plugins/docker
settings:
username: 3wordchant
username:
from_secret: docker_reg_username_3wc
password:
from_secret: git_coopcloud_tech_token_3wc
repo: git.coopcloud.tech/coop-cloud/recipes.coopcloud.tech
from_secret: docker_reg_passwd_3wc
repo: 3wordchant/abra-apps
tags: latest
registry: git.coopcloud.tech
- name: deployment
image: git.coopcloud.tech/coop-cloud/stack-ssh-deploy:latest
image: decentral1se/stack-ssh-deploy:latest
settings:
stack: recipes_coopcloud_tech
host: swarm-0.coopcloud.tech
stack: dev_apps_coopcloud_tech
deploy_key:
from_secret: drone_ssh_swarm-0_coopcloud_tech
from_secret: drone_ssh_swarm-demo.autonomic.zone
host: swarm-demo.autonomic.zone
trigger:
branch:
- main

View File

@ -1,8 +0,0 @@
# authors
> If you're looking at this and you hack on `abra` and you're not listed here,
> please do add yourself! This is a community project, let's show some :heart:
- 3wordchant
- eejum
- hazelnot

View File

@ -1,4 +1,4 @@
FROM node:21-alpine AS build
FROM node:12-alpine
RUN mkdir /code
WORKDIR /code
@ -11,10 +11,5 @@ ENV PATH=$PATH:/code/node_modules/elm-linter/bin:/code/node_modules/elm-format/b
# Add remainder of files
COPY . .
RUN ["npm", "run", "build"]
FROM nginx
COPY --from=build /code/public/ /usr/share/nginx/html/
COPY ./nginx.conf /etc/nginx/conf.d/default.conf
ENTRYPOINT ["/usr/local/bin/npm"]
CMD ["run", "prod"]

View File

@ -1,8 +1,8 @@
# recipes.coopcloud.tech
> https://recipes.coopcloud.tech is the current live site
> WIP! https://dev.apps.coopcloud.tech is the current live site
[![Build Status](https://build.coopcloud.tech/api/badges/coop-cloud/recipes.coopcloud.tech/status.svg?ref=refs/heads/main)](https://build.coopcloud.tech/coop-cloud/recipes.coopcloud.tech)
[![Build Status](https://drone.autonomic.zone/api/badges/coop-cloud/recipes.coopcloud.tech/status.svg?ref=refs/heads/main)](https://drone.autonomic.zone/coop-cloud/recipes.coopcloud.tech)
The Co-op Cloud recipes catalogue. Our digital configuration commons, browsable in a simple and pleasant web UI.
@ -33,8 +33,6 @@ __Build command:__ `npm run build`
__Publish directory:__ `public`
Then, run `make` to deploy the new version to `mellor.coopcloud.tech`.
## thanks
created using [`elm-spa`](https://elm-spa.dev)

View File

@ -3,28 +3,25 @@ version: "3.8"
services:
app:
image: "git.coopcloud.tech/coop-cloud/recipes.coopcloud.tech:latest"
image: "3wordchant/abra-apps:latest"
networks:
- proxy
# healthcheck:
# test: "nodejs -e \"http.get('http://localhost:8000', (res) => { console.log('status: ', res.statusCode); if (res.statusCode == 200) { process.exit(0); } else { process.exit(1); } });\""
# interval: 30s
# timeout: 10s
# retries: 3
# start_period: 1m
healthcheck:
test: "nodejs -e \"http.get('http://localhost:8000', (res) => { console.log('status: ', res.statusCode); if (res.statusCode == 200) { process.exit(0); } else { process.exit(1); } });\""
interval: 30s
timeout: 10s
retries: 3
start_period: 1m
deploy:
update_config:
failure_action: rollback
order: start-first
labels:
- "traefik.enable=true"
- "traefik.http.services.abra-recipes.loadbalancer.server.port=80"
- "traefik.http.routers.abra-recipes.rule=(Host(`dev.apps.coopcloud.tech`)||Host(`recipes.coopcloud.tech`))"
- "traefik.http.routers.abra-recipes.entrypoints=web-secure"
- "traefik.http.routers.abra-recipes.tls.certresolver=production"
- "traefik.http.routers.abra-recipes.middlewares=abra-recipes-redirect"
- "traefik.http.middlewares.abra-recipes-redirect.headers.SSLForceHost=true"
- "traefik.http.middlewares.abra-recipes-redirect.headers.SSLHost=recipes.coopcloud.tech"
- "traefik.http.services.abra-apps-dev.loadbalancer.server.port=8000"
- "traefik.http.routers.abra-apps-dev.rule=Host(`recipes.coopcloud.tech`)"
- "traefik.http.routers.abra-apps-dev.entrypoints=web-secure"
- "traefik.http.routers.abra-apps-dev.tls.certresolver=production"
networks:
proxy:

View File

@ -16,7 +16,6 @@
"elm/url": "1.0.0",
"elm-community/json-extra": "4.3.0",
"elm-community/string-extra": "4.0.1",
"fapian/elm-html-aria": "1.4.0",
"pablohirafuji/elm-markdown": "2.0.5"
},
"indirect": {

View File

@ -1,6 +1,6 @@
deploy:
@DOCKER_CONTEXT=mellor.coopcloud.tech \
docker stack rm recipes_coopcloud_tech && \
docker stack rm dev_apps_coopcloud_tech && \
DOCKER_CONTEXT=mellor.coopcloud.tech \
docker stack deploy -c compose.yml recipes_coopcloud_tech
docker stack deploy -c compose.yml dev_apps_coopcloud_tech

View File

@ -1,17 +0,0 @@
server {
listen 80;
listen [::]:80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri /index.html =404;
}
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}

654
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,8 @@
{
"name": "abra-apps",
"version": "1.0.0",
"description": "Co-op Cloud recipe catalogue",
"repository": "https://git.coopcloud.tech/toolshed/recipes.coopcloud.tech",
"description": "Co-op Cloud app catalogue",
"repository": "https://git.coopcloud.tech/coop-cloud/abra-apps",
"scripts": {
"start": "npm install && npm run build:dev && npm run dev",
"prod": "npm install && npm run build && npm run serve",
@ -22,14 +22,14 @@
"author": "",
"license": "ISC",
"devDependencies": {
"chokidar-cli": "3.0.0",
"elm": "0.19.1-6",
"chokidar-cli": "2.1.0",
"elm": "0.19.1-3",
"elm-live": "4.0.2",
"elm-spa": "5.0.4",
"elm-test": "0.19.1-revision2",
"npm-run-all": "4.1.5"
},
"dependencies": {
"elm-format": "^0.8.6"
"elm-format": "^0.8.5"
}
}

View File

@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- CSS goes here -->
<link rel="stylesheet" href="/style.css">
<title>Co-op Cloud Recipes</title>
<title>abra recipes</title>
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<!--<link rel="stylesheet"
@ -20,7 +20,7 @@
<nav class="navbar navbar-expand-lg sticky-top font-weight-bold" style="background: rgb(255, 79, 136) none repeat scroll 0% 0%;">
<a class="navbar-brand text-dark" href="/">
<img src="/logo.png" class="d-inline-block align-top mr-2" alt="" width="30" height="30">
Co-op Cloud Recipes</a>
abra recipes</a>
</nav>
<div class="container-fluid">
<div class="pt-3">
@ -28,7 +28,7 @@
<div class="card">
<div class="card-header">
<h2>
Co-op Cloud Recipes</h2>
abra recipes</h2>
</div>
<div class="card-body">
<p>

View File

@ -29,51 +29,16 @@ i.fas, i.fab {
}
/* Filtering */
#filter {
position: fixed;
left: 0;
background-color: var(--light-blue);
padding-top: 1rem;
height: 100%;
}
#filter > form > div {
margin: 1rem 0;
}
#filter h3 {
font-size: 18px;
}
input[type=checkbox] {
margin-right: 0.5rem;
}
a.help {
display: inline-block;
margin-left: 0.5rem;
font-size: 14px;
color: var(--dark-pink);
}
/* Categories */
.category-tile {
cursor: pointer;
}
.category-tile:hover {
color: var(--dark-blue);
}
.category-tile.active {
color: var(--white);
}
/* Intro */
.card#intro {
margin: 1em 0;
background-color: var(--light-blue);
border-radius: 5px;
}
/* Cards */
@ -81,7 +46,6 @@ a.help {
.app-category {
background-color: var(--light-blue);
color: var(--white);
margin-left: 0.5rem;
}
.card-description {
@ -109,14 +73,10 @@ a.help {
.card-img-top {
width: 100%;
height: 5vw;
height: 16vw;
object-fit: cover;
}
.card-img-large {
height: 10vw;
}
.smaller-card {
border: 1px solid var(--dark-pink);
border-radius: 20px;
@ -135,6 +95,31 @@ a.help {
}
/* Search bar*/
.search-bar-container {
margin: 2em;
display: flex;
flex-flow: row wrap;
align-items: center;
}
.search-bar-input, .search-dropdown {
margin: 0.5em;
height: calc(1.5em + .75rem + 2px);
background-color: var(--white);
border: 1px solid var(--dark-pink);
border-radius: .5rem;
}
.search-bar-input {
width: 30rem;
}
.search-dropdown {
width: 10rem;
}
/* Navbar */
.navbar-text {
color: var(--dark-blue);
@ -147,7 +132,7 @@ a.help {
}
@media (min-width: 768px) {
.smaller-card .card-body p {
.card-body p {
height: 2.5rem;
}
}
@ -156,10 +141,3 @@ a.help {
.card-body p {
}
}
@media (max-width: 768px) {
#filter {
width: 100%;
position: relative;
margin-bottom: 1rem;
}

View File

@ -1,3 +0,0 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json"
}

View File

@ -36,16 +36,15 @@ view { params } =
let
elm_link = a [ href "https://elm-lang.org/" ] [ text "Elm" ]
coopcloud_link = a [ href "https://coopcloud.tech/" ] [ text "Co-op Cloud" ]
source_link = a [ href "https://git.coopcloud.tech/toolshed/recipes.coopcloud.tech" ] [ text "source" ]
autonomic_link = a [ href "https://autonomic.zone" ] [ text "Autonomic" ]
source_link = a [ href "https://git.coopcloud.tech/coop-cloud/abra-apps" ] [ text "source" ]
in
{ title = "About Co-op Cloud Recipes"
{ title = "about abra recipes"
, body =
[ div [ class "pt-3" ]
[ div [ class "col-md-6 col-sm-10 mb-3 offset-md-3 offset-sm-1" ]
[ div [ class "card" ]
[ div [ class "card-header" ]
[ h2 [] [ text "Co-op Cloud Recipes" ]
[ h2 [] [ text "abra recipes" ]
]
, div [ class "card-body" ]
[ p []
@ -53,7 +52,7 @@ view { params } =
text "a lil' "
, text " tool to display "
, coopcloud_link
, text " recipes."
, text " apps."
]
, p []
[
@ -64,9 +63,7 @@ view { params } =
]
, div [ class "card-footer" ]
[ p []
[ text "made with 🤪 at "
, autonomic_link
, text " ("
[ text "by @3wc ("
, source_link
, text ")"
]

View File

@ -37,9 +37,9 @@ type alias App =
{ name : String
, category : String
, repository : Maybe String
, versions : List String
, versions : Maybe (List String)
, icon : Maybe String
, status : Int
, status : String
, slug : String
, default_branch : String
, website : Maybe String
@ -151,13 +151,13 @@ title : Model -> String
title model =
case model.status of
Loading ->
"loading Co-op Cloud Recipes"
"loading abra recipes"
Failure ->
"error - Co-op Cloud Recipes"
"error - abra recipes"
Success app ->
app.name ++ " Co-op Cloud Recipes"
app.name ++ " abra recipes"
body : Model -> Html Msg
@ -192,23 +192,23 @@ viewStatusBadge app =
let
status_class =
case app.status of
5 ->
"1" ->
"badge-success"
4 ->
"2" ->
"badge-info"
3 ->
"3" ->
"badge-warning"
2 ->
"4" ->
"badge-danger"
_ ->
"badge-dark"
in
span [ class ("card-link badge " ++ status_class) ]
[ text ("Score: " ++ String.fromInt app.status) ]
[ text ("Score: " ++ app.status) ]
viewApp : App -> String -> Html Msg
@ -265,16 +265,13 @@ viewApp app readme =
, repository_link
, website_link
]
, img [ class "card-img-top card-img-large", src icon_url, alt ("icon for " ++ app.name) ] []
, img [ class "card-img-top", src icon_url, alt ("icon for " ++ app.name) ] []
, div [ class "card-body" ]
-- render Markdown with no special options
[ div [] (Markdown.toHtml Nothing readme)
]
, div [ class "card-footer" ]
[ h5 [] [ text "Versions" ]
, ul []
(List.map (\version -> li [] [ text version ]) (List.reverse app.versions))
]
[]
]
]
@ -286,7 +283,7 @@ viewApp app readme =
loadApp : Cmd Msg
loadApp =
Http.get
{ url = "https://recipes.coopcloud.tech/recipes.json"
{ url = "https://apps.coopcloud.tech/"
, expect = Http.expectJson GotApps appListDecoder
}
@ -307,37 +304,27 @@ loadREADME app =
in
Http.get
-- FIXME use live Gitea link
{ url = "https://git.coopcloud.tech/coop-cloud/" ++ app.slug ++ "/raw/branch/" ++ app.default_branch ++ "/README.md"
{ url = "https://cors-container.herokuapp.com/https://git.coopcloud.tech/coop-cloud/" ++ app.slug ++ "/raw/branch/" ++ app.default_branch ++ "/README.md"
, expect = Http.expectString GotText
}
featuresDecoder : Decode.Decoder String
featuresDecoder =
-- get features.status if it's there
Decode.oneOf
[ Decode.at [ "status" ] Decode.int
, Decode.succeed 5
[ Decode.at [ "status" ] Decode.string
, Decode.succeed ""
]
versionsDecoder : Decode.Decoder (List String)
versionsDecoder =
Decode.list (Decode.keyValuePairs Decode.value)
|> Decode.map buildVersions
buildVersions : List (List ( String, Decode.Value )) -> List String
buildVersions versions =
List.concatMap (List.map (\( version, _ ) -> version)) versions
appDecoder : Decode.Decoder App
appDecoder =
Decode.succeed App
|> andMap (Decode.field "name" Decode.string)
|> andMap (Decode.field "category" Decode.string)
|> andMap (Decode.maybe (Decode.field "repository" Decode.string))
|> andMap (Decode.at [ "versions" ] versionsDecoder)
-- |> andMap (Decode.succeed Nothing)
|> andMap (Decode.succeed Nothing)
|> andMap (Decode.maybe (Decode.field "icon" Decode.string))
|> andMap (Decode.at [ "features" ] featuresDecoder)
|> andMap (Decode.succeed "")

View File

@ -1,9 +1,8 @@
module Pages.Top exposing (Model, Msg, Params, page)
import Enum exposing (Enum)
import Html exposing (Html, a, button, div, form, h2, h3, h5, i, img, input, label, li, option, p, select, span, text, ul)
import Html.Attributes exposing (alt, class, classList, for, href, id, src, style, target, type_, value)
import Html.Attributes.Aria exposing (ariaLabel)
import Html exposing (Html, a, button, div, h2, h5, i, img, li, p, span, text, ul, form, label, select, option, input)
import Html.Attributes exposing (alt, class, href, src, style, id, for, value)
import Html.Events exposing (onClick, onInput)
import Http
import Json.Decode as Decode
@ -27,7 +26,6 @@ page =
}
-- INIT
@ -54,8 +52,8 @@ type alias Model =
, filter_category : Maybe Category
, filter_text : Maybe String
, status : Status
, apps : List App
, results : List App
, apps : (List App)
, results : (List App)
}
@ -76,13 +74,14 @@ type Category
categories : Enum Category
categories =
Enum.create
[ ( "(Everything)", All )
, ( "Apps", Apps )
[ ( "Apps", Apps )
, ( "Utilities", Utilities )
, ( "Development", Development )
, ("All", All)
]
init : Url Params -> ( Model, Cmd Msg )
init { params } =
( default_model, loadApps )
@ -95,14 +94,8 @@ default_image =
default_model : Model
default_model =
{ filter_score = Nothing
, filter_category = Nothing
, filter_text = Nothing
, status = Loading
, apps = []
, results = []
}
{ filter_score = Nothing, filter_category = Nothing, filter_text = Nothing,
status = Loading, apps = [], results = [] }
-- UPDATE
@ -120,55 +113,41 @@ filterAppsScore : List App -> Maybe Int -> List App
filterAppsScore apps score =
case score of
Just s ->
List.filter
(\app ->
app.status >= s
)
apps
List.filter (\app ->
app.status <= s
) apps
Nothing ->
apps
filterAppsCategory : List App -> Maybe Category -> List App
filterAppsCategory apps category =
case category of
Just c ->
if c == All then
apps
else
List.filter
(\app ->
List.filter (\app ->
app.category == categories.toString c
)
apps
) apps
Nothing ->
apps
filterAppsText : List App -> Maybe String -> List App
filterAppsText apps text =
case text of
Just "" ->
apps
Just t ->
List.filter
(\app ->
String.contains (String.toLower t)
(String.toLower app.name
++ String.toLower
(Maybe.withDefault "" app.description)
List.filter (\app ->
String.contains (String.toLower t) (
String.toLower app.name ++ String.toLower (
Maybe.withDefault "" app.description
)
)
apps
) apps
Nothing ->
apps
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
@ -177,53 +156,39 @@ update msg model =
FilterScore filter ->
let
filter_score =
String.toInt filter
filter_score = String.toInt filter
in
( { model
| filter_score = filter_score
, results =
filterAppsScore
(filterAppsCategory
(filterAppsText model.apps model.filter_text)
model.filter_category
)
(String.toInt filter)
}
, Cmd.none
)
, results = filterAppsScore (
filterAppsCategory (
filterAppsText model.apps model.filter_text
) model.filter_category
) (String.toInt filter)
}, Cmd.none )
FilterCategory filter ->
let
category =
categories.fromString filter
category = categories.fromString filter
in
( { model
| filter_category = category
, results =
filterAppsCategory
(filterAppsScore
(filterAppsText model.apps model.filter_text)
model.filter_score
)
category
}
, Cmd.none
)
, results = filterAppsCategory (
filterAppsScore (
filterAppsText model.apps model.filter_text
)model.filter_score
) category
}, Cmd.none )
FilterText filter ->
( { model
| filter_text = Just filter
, results =
filterAppsText
(filterAppsScore
(filterAppsCategory model.apps model.filter_category)
model.filter_score
)
(Just filter)
}
, Cmd.none
)
, results = filterAppsText (
filterAppsScore (
filterAppsCategory model.apps model.filter_category
) model.filter_score
) (Just filter)
}, Cmd.none )
GotApps result ->
case result of
@ -231,17 +196,11 @@ update msg model =
( { default_model
| status = Success
, apps = apps
, results = apps
}
, Cmd.none
)
, results = apps }, Cmd.none )
Err _ ->
( { default_model
| status = Failure
}
, Cmd.none
)
| status = Failure}, Cmd.none )
subscriptions : Model -> Sub Msg
@ -255,14 +214,14 @@ subscriptions model =
view : Model -> Document Msg
view model =
{ title = "Co-op Cloud Recipes"
{ title = "abra recipes"
, body = [ body model ]
}
body : Model -> Html Msg
body model =
div []
div [ class "pt-3" ]
[ viewApps model
]
@ -272,16 +231,16 @@ viewStatusBadge app =
let
status_class =
case app.status of
5 ->
1 ->
"badge-success"
4 ->
2 ->
"badge-info"
3 ->
"badge-warning"
2 ->
4 ->
"badge-danger"
_ ->
@ -344,21 +303,16 @@ viewApp app =
, p [ class "card-description" ] [ text (ellipsis 100 (withDefault "" app.description)) ]
]
, div [ class "footer" ]
[ viewStatusBadge app, span [ class "badge app-category" ] [ text app.category ] ]
[ span [ class "badge app-category" ] [ text app.category ]]
]
]
viewCategory : Model -> ( String, Category ) -> Html Msg
viewCategory model category =
div
[ classList
[ ( "category-tile", True )
, ( "active", categories.toString (Maybe.withDefault All model.filter_category) == Tuple.first category )
]
, onClick (FilterCategory (Tuple.first category))
]
[ text (Tuple.first category) ]
viewCategories : (String, Category) -> Html Msg
viewCategories category =
div [ class "category-tile", onClick (FilterCategory (Tuple.first category)) ] [text (Tuple.first category)]
viewApps : Model -> Html Msg
@ -381,63 +335,36 @@ viewApps model =
Success ->
div [ class "row justify-content-center" ]
[ div [ class "col-md-3", id "filter" ]
[ h2 [ class "app-headings" ] [ text "Finding things" ]
, form []
[ div []
[ h3 [] [ text "Search" ]
, input [ ariaLabel "search", id "text", onInput FilterText ] []
[ div [ class "col-md-3" ] [
h2 [ class "app-headings" ] [text "Categories"]
, div [] (List.map viewCategories categories.list)
]
, div []
[ h3 [] [ text "Categories" ]
, div [] (List.map (viewCategory model) categories.list)
]
, div []
[ h3 [] [ text "Status" ]
, div []
[ label [] [ text "Minimum score: " ]
, a [ class "help", target "_blank", href "https://docs.coopcloud.tech/abra/recipes/#status-features-score" ] [ text "(help)" ]
]
, select [ class "search-dropdown", id "level", onInput FilterScore ]
[ option [] [ text "any" ]
, option [ value "5" ] [ text "5 (amazing)" ]
, option [ value "4" ] [ text "4 (good)" ]
, option [ value "3" ] [ text "3 (ok)" ]
, option [ value "2" ] [ text "2 (basic)" ]
, option [ value "1" ] [ text "1 (chaos)" ]
]
]
]
]
, div [ class "col-md-6 offset-md-3" ]
, div [ class "col-md-6" ]
[ div [ class "row" ]
[ div [ class "col-sm-12" ]
[ div []
[]
[ div [ class "col-sm-12" ] [
div [] [
form [ class "search-bar-container" ] [
label [ for "text" ] [ text "Search" ]
, input [ class "search-bar-input", id "text", onInput FilterText ] []
, label [ for "level" ] [ text " and show only items that have at least " ]
, select [ class "search-dropdown", id "level", onInput FilterScore ] [
option [ ] [ text "any" ]
, option [ value "1" ] [ text "1 (production)" ]
, option [ value "2" ] [ text "2 (beta)" ]
, option [ value "3" ] [ text "3 (alpha)" ]
, option [ value "4" ] [ text "4 (pre-alpha)" ]
]
, text "builds "
]
]
, div [ id "intro", class "card" ]
[ div [ class "card-body" ]
[ h2 [ class "app-headings card-title" ] [ text "Co-op Cloud Recipes" ]
, text "You can use these recipes ("
, a
[ href
"https://docs.coopcloud.tech/intro/glossary/#recipe"
]
[ text "What's a recipe?"
]
, text ") with "
, a [ href "https://coopcloud.tech" ]
[ text "Co-op Cloud"
]
, text "."
]
]
, h2 [ class "app-headings" ] [ text "Apps" ]
, div [ class "row" ]
(List.map viewApp
(model.results
|> List.sortWith
(by .status DESC
(by .status ASC
|> andThen (String.toLower << .name) ASC
)
)
@ -446,21 +373,14 @@ viewApps model =
, div [class "col-md-3"] []
]
-- HTTP
loadApps : Cmd Msg
loadApps =
Http.request
{ url = "https://recipes.coopcloud.tech/recipes.json"
Http.get
{ url = "https://apps.coopcloud.tech/"
, expect = Http.expectJson GotApps appListDecoder
, headers = [ Http.header "Content-Type" "application/json" ]
, body = Http.emptyBody
, method = "GET"
, timeout = Nothing
, tracker = Nothing
}

View File

@ -70,15 +70,15 @@ view { page, toMsg } model =
, body =
[ div [ class "background" ]
[ nav
[ class "navbar navbar-expand-lg sticky-top" ]
[ a [ class "font-weight-bold navbar-text", href (Route.toString Route.Top) ]
[ class "navbar navbar-expand-lg sticky-top font-weight-bold" ]
[ a [ class "navbar-text", href (Route.toString Route.Top) ]
[ img
[ src "/logo-2.png"
, class "d-inline-block align-top mr-2"
, alt ""
, width 48
, height 16 ] []
, text "Co-op Cloud Recipes"
, text "abra recipes"
]
, ul [ class "navbar-nav" ]
[ li [ class "nav-tem" ] [ a [ class "nav-link navbar-text", href (Route.toString Route.About) ] [ text "about" ] ]