~netlandish/links

b479d3c7dc2893c2a7cc982ac780e32324709b8e — Peter Sanchez 3 months ago dfaafb8
Adding seoData structure to easily add SEO tags on any page.

Implements: https://todo.code.netlandish.com/~netlandish/links/80
4 files changed, 140 insertions(+), 7 deletions(-)

M core/routes.go
M core/templates.go
M helpers.go
M templates/base.html
M core/routes.go => core/routes.go +81 -6
@@ 328,8 328,11 @@ func (s *Service) Homepage(c echo.Context) error {
	pd.Data["forgot_password"] = lt.Translate("Forgot Password?")
	pd.Data["login"] = lt.Translate("Login")
	pd.Data["no_accounts"] = lt.Translate("No accounts? Click here to create one")
	gMap := gobwebs.Map{"pd": pd}
	return links.Render(c, http.StatusOK, "index.html", gMap)

	gmap := gobwebs.Map{
		"pd": pd,
	}
	return links.Render(c, http.StatusOK, "index.html", gmap)

}



@@ 408,8 411,18 @@ func (s *Service) PricingList(c echo.Context) error {
	pd.Data["feature_self_hosting_2"] = lt.Translate("Host your own version of Link Taco")
	pd.Data["feature_self_hosting_3"] = lt.Translate("Documentation")

	url := links.GetLinksDomainURL(c)
	url.Path = c.Echo().Reverse("core:pricing_list")
	seoData := links.GetSEOData(c)
	seoData.Title = pd.Title
	seoData.Description = lt.Translate("Pricing and feature details for LinkTaco.com")
	seoData.Keywords = lt.Translate("pricing, links, linktaco, feature, plans, pricing plans")
	seoData.URL = url.String()
	seoData.TwitterURL = url.String()

	gmap := gobwebs.Map{
		"pd": pd,
		"pd":      pd,
		"seoData": seoData,
	}
	return links.Render(c, http.StatusOK, "pricing_list.html", gmap)
}


@@ 479,8 492,19 @@ func (s *Service) FeatureTour(c echo.Context) error {

	pd.Data["import_pinboard"] = lt.Translate("Import from Pinboard, Chrome, Firefox, Safari")
	pd.Data["export_json"] = lt.Translate("Export in JSON or HTML format")

	url := links.GetLinksDomainURL(c)
	url.Path = c.Echo().Reverse("core:feature_tour")
	seoData := links.GetSEOData(c)
	seoData.Title = pd.Title
	seoData.Description = lt.Translate("All feature details for LinkTaco.com")
	seoData.Keywords = lt.Translate("features, pricing, links, linktaco, feature, plans, pricing plans")
	seoData.URL = url.String()
	seoData.TwitterURL = url.String()

	gmap := gobwebs.Map{
		"pd": pd,
		"pd":      pd,
		"seoData": seoData,
	}
	return links.Render(c, http.StatusOK, "feature_tour.html", gmap)
}


@@ 1731,6 1755,17 @@ func (s *Service) PopularLinkList(c echo.Context) error {

	pLinks := result.PopularLinks
	rssURL := c.Echo().Reverse(s.RouteName("popular_link_list_rss"))

	url := links.GetLinksDomainURL(c)
	url.Path = c.Echo().Reverse(s.RouteName("popular_link_list"))
	seoData := links.GetSEOData(c)
	seoData.Title = pd.Title
	seoData.Description = lt.Translate("Most popular links on LinkTaco.com")
	seoData.Keywords = lt.Translate("popular, links, linktaco, feature, plans, pricing plans")
	seoData.URL = url.String()
	seoData.TwitterURL = url.String()
	seoData.RssURL = url.String() + "/rss"

	gmap := gobwebs.Map{
		"pd":        pd,
		"links":     pLinks,


@@ 1738,6 1773,7 @@ func (s *Service) PopularLinkList(c echo.Context) error {
		"navFlag":   "popular",
		"tagFilter": "",
		"rssURL":    rssURL,
		"seoData":   seoData,
	}
	if links.IsRSS(c.Path()) {
		items := []links.Item{}


@@ 2033,14 2069,14 @@ func (s *Service) OrgLinksList(c echo.Context) error {

	var (
		isOrgLink, isHome, advancedSearch, isRSSAuth bool
		currURL, navFlag, rssURL, followAction       string
		currURL, navFlag, rssURL, followAction, slug string
	)
	org := &models.Organization{}
	if c.Path() != c.Echo().Reverse(s.RouteName("recent_link_list")) &&
		c.Path() != c.Echo().Reverse(s.RouteName("recent_link_list_rss")) {
		// This means that we want to see a specific org (private or businnes)
		// and not all the recent links
		slug := links.PullOrgSlug(c)
		slug = links.PullOrgSlug(c)
		op.Var("slug", slug)
		opts := &database.FilterOptions{
			Filter: sq.And{


@@ 2275,8 2311,25 @@ func (s *Service) OrgLinksList(c echo.Context) error {
		}
		return links.ServerRSSFeed(c.Response(), rss)
	}

	seoData := links.GetSEOData(c)
	url := links.GetLinksDomainURL(c)
	if isOrgLink {
		url.Path = c.Echo().Reverse(s.RouteName("org_link_list"), slug)
		seoData.Description = lt.Translate("Recent public links added to %s on LinkTaco.com", org.Name)
	} else {
		url.Path = c.Echo().Reverse(s.RouteName("recent_link_list"))
		seoData.Description = lt.Translate("Recent public links added to LinkTaco.com")
	}
	seoData.Title = pd.Title
	seoData.Keywords = lt.Translate("recent, public, links, linktaco")
	seoData.URL = url.String()
	seoData.TwitterURL = url.String()
	seoData.RssURL = url.String() + "/rss"

	gmap := gobwebs.Map{
		"pd":                pd,
		"seoData":           seoData,
		"links":             orgLinks,
		"org":               org,
		"isOrgLink":         isOrgLink,


@@ 2388,11 2441,22 @@ func (s *Service) OrgLinkDetail(c echo.Context) error {
	pd.Data["tags"] = lt.Translate("Tags")
	pd.Data["back"] = lt.Translate("Back")
	link := result.Link

	url := links.GetLinksDomainURL(c)
	url.Path = c.Echo().Reverse(s.RouteName("link_detail"), hash)
	seoData := links.GetSEOData(c)
	seoData.Title = pd.Title
	seoData.Description = lt.Translate("Bookmark '%s' on LinkTaco.com", link.Title)
	seoData.Keywords = lt.Translate("bookmark, note, detail, popular, links, linktaco")
	seoData.URL = url.String()
	seoData.TwitterURL = url.String()

	gmap := gobwebs.Map{
		"pd":        pd,
		"link":      link,
		"IsPrivate": link.IsPrivate(),
		"navFlag":   "bookmarks",
		"seoData":   seoData,
	}
	return links.Render(c, http.StatusOK, "link_detail.html", gmap)
}


@@ 3489,12 3553,23 @@ func (s *Service) NoteDetail(c echo.Context) error {
	pd.Data["tags"] = lt.Translate("Tags")
	pd.Data["back"] = lt.Translate("Back")
	link := result.Link

	url := links.GetLinksDomainURL(c)
	url.Path = c.Echo().Reverse(s.RouteName("note_detail"), hash)
	seoData := links.GetSEOData(c)
	seoData.Title = pd.Title
	seoData.Description = lt.Translate("Note '%s' on LinkTaco.com", link.Title)
	seoData.Keywords = lt.Translate("note, detail, popular, links, linktaco")
	seoData.URL = url.String()
	seoData.TwitterURL = url.String()

	gmap := gobwebs.Map{
		"pd":        pd,
		"link":      link,
		"IsPrivate": link.IsPrivate(),
		"IsAuth":    gctx.User.IsAuthenticated(),
		"navFlag":   "notes",
		"seoData":   seoData,
	}
	return links.Render(c, http.StatusOK, "link_detail.html", gmap)
}

M core/templates.go => core/templates.go +5 -0
@@ 50,7 50,12 @@ func AddGlobalTmpl(c echo.Context) gobwebs.Map {
	pd.Data["manage_shorts"] = lt.Translate("Short Links")
	pd.Data["admin"] = lt.Translate("Admin")
	pd.Data["my_feed"] = lt.Translate("Feed")

	gmap["base_pd"] = pd

	// SEO values
	gmap["seoData"] = links.GetSEOData(c)

	// serverVersion
	serverVersion := strings.Split(strings.Split(gctx.Server.AppInfo(), " ")[1], "-")
	gmap["serverVersion"] = serverVersion[len(serverVersion)-1]

M helpers.go => helpers.go +32 -0
@@ 996,3 996,35 @@ func GetAddLinkURL(c echo.Context, gURL addLinker) string {
	nextURL.RawQuery = qs.Encode()
	return nextURL.String()
}

type SEOData struct {
	Title           string
	Description     string
	Keywords        string
	URL             string
	ImageURL        string
	TwitterURL      string
	TwitterImageURL string
	RssURL          string
}

func GetSEOData(c echo.Context) *SEOData {
	lt := localizer.GetSessionLocalizer(c)
	url := GetLinksDomainURL(c)
	url.Path = c.Echo().Reverse("core:index")
	seoData := &SEOData{
		Title: lt.Translate("Social bookmarking plus link sharing, shortening and listings all in one app."),
		Description: lt.Translate(
			"Welcome to LinkTaco. Where you can mix all your link saving and sharing needs in one " +
				"tight little bundle. Much like a taco. A link taco if you will.",
		),
		Keywords:        lt.Translate("social bookmarks, bookmarking, links, link sharing, link shortening, link listings, bookmarks, link saving, qr codes, analytics"),
		URL:             url.String(),
		ImageURL:        "https://s3.amazonaws.com/linktaco/social-media-image.jpg",
		TwitterURL:      url.String(),
		TwitterImageURL: "https://s3.amazonaws.com/linktaco/social-media-image.jpg",
	}
	url.Path = c.Echo().Reverse("core:recent_link_list_rss")
	seoData.RssURL = url.String()
	return seoData
}

M templates/base.html => templates/base.html +22 -1
@@ 11,7 11,28 @@
    <link rel="icon" type="image/png" sizes="32x32" href="{{ staticURL "img/favicon-32x32.png" }}?{{.serverVersion}}" />
    <link rel="icon" type="image/png" sizes="16x16" href="{{ staticURL "img/favicon-16x16.png" }}?{{.serverVersion}}" />
    <link rel="apple-touch-icon" type="image/png" href="{{ staticURL "img/apple-touch-icon.png" }}?{{.serverVersion}}" />
    {{ block "seo" . }}{{ end }}
    {{ if .seoData }}
    <meta name="description" content="{{ .seoData.Description }}">
    <meta name="keywords" content="{{ .seoData.Keywords }}">
    <meta property="og:title" content="{{ .seoData.Title }} | Link Taco">
    <meta property="og:url" content="{{ .seoData.URL }}">
    <meta property="og:description" content="{{ .seoData.Description }}">
    <meta property="og:image" content="{{ .seoData.ImageURL }}">
    <meta property="og:image:secure_url" content="{{ .seoData.ImageURL }}">
    <meta property="og:image:width" content="1200">
    <meta property="og:image:height" content="630">
    <meta property="og:site_name" content="LinkTaco">
    <meta name="twitter:domain" content="linktaco.com">
    <meta name="twitter:card" content="summary_large_image">
    <meta name="twitter:title" content="{{ .seoData.Title }} | Link Taco">
    <meta name="twitter:url" content="{{ .seoData.URL }}">
    <meta name="twitter:description" content="{{ .seoData.Description }}">
    <meta name="twitter:image" content="{{ .seoData.TwitterImageURL }}">
    <meta name="twitter:creator" content="@linktaco">
    {{ if .seoData.RssURL }}
    <link rel="alternate" type="application/rss+xml" title="RSS" href="{{ .seoData.RssURL }}" />
    {{ end }}
    {{ end }}
    {{ block "extrahead" . }}{{ end }}
  </head>
  <body class="container{{if .hideNav}} full-contaiter{{end}}"{{if or .useTagAutocomplete .advancedSearch}} data-autocomplete="{{reverse "core:tag_autocomplete"}}?org={{.autoCompleteOrgID}}"{{end}}>