From aed4bf903ca6dbbb2a6646f054e8ba29bb963a8f Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Wed, 29 Sep 2021 14:31:32 -0400 Subject: [PATCH] tilde.news customizations --- .gitignore | 14 +- app/assets/stylesheets/application.css.erb | 6 +- app/assets/stylesheets/local/lobsters.css | 69 ++++ app/models/user.rb | 2 +- app/views/about/about.html.erb | 379 +----------------- app/views/about/chat.html.erb | 70 +--- config/initializers/production.rb | 11 + config/puma.rb | 2 +- .../20200809023435_create_categories.rb | 30 +- public/apple-touch-icon-144.png | Bin 4536 -> 11654 bytes public/apple-touch-icon.png | Bin 1744 -> 3173 bytes public/favicon-16x16.png | Bin 0 -> 885 bytes public/favicon.ico | Bin 11134 -> 15406 bytes 13 files changed, 124 insertions(+), 459 deletions(-) create mode 100644 app/assets/stylesheets/local/lobsters.css create mode 100644 config/initializers/production.rb create mode 100644 public/favicon-16x16.png diff --git a/.gitignore b/.gitignore index 1e1b9608..79249b1b 100644 --- a/.gitignore +++ b/.gitignore @@ -32,16 +32,11 @@ public/.well-known public/avatars public/sitemap* -# templates to be created per-site -app/views/about/404.* -app/views/about/about.* -app/views/about/chat.* -app/views/about/privacy.* -public/apple-touch-icon* -public/favicon.ico - # prod config config/credentials.yml.enc + +# files added in production +lib/tasks/deploy.rake config/database.yml config/initializers/development.rb config/initializers/production.rb @@ -49,4 +44,5 @@ config/master.key config/scout_apm.yml config/*.sphinx.conf config/unicorn.conf.rb -lib/tasks/deploy.rake +config/scout_apm.yml +.env diff --git a/app/assets/stylesheets/application.css.erb b/app/assets/stylesheets/application.css.erb index fdbcb205..20e25c16 100644 --- a/app/assets/stylesheets/application.css.erb +++ b/app/assets/stylesheets/application.css.erb @@ -233,10 +233,10 @@ html { } body, textarea, input, button { - font-family: "helvetica neue", arial, sans-serif; - font-size: 10pt; + font-family: "IBM Plex Mono", "JetBrains Mono", Consolas, "Courier New", Courier, monospace; + font-size: 11pt; color: var(--color-fg); - line-height: 1.45em; + line-height: 1.35em; } body { diff --git a/app/assets/stylesheets/local/lobsters.css b/app/assets/stylesheets/local/lobsters.css new file mode 100644 index 00000000..2736adb3 --- /dev/null +++ b/app/assets/stylesheets/local/lobsters.css @@ -0,0 +1,69 @@ +/* light mode */ +:root { + --color-lobsters-fg-has-suggestions: #bd6060; + + --color-lobsters-tag-special-bg: #f9ddde; + --color-lobsters-tag-special-border: #f0b2b8; + + --color-lobsters-hat-sysop-crown-fill: #ddc7c7; + --color-lobsters-hat-sysop-brim-stroke: #bbb2b2; +} + +/* dark mode */ +@media (prefers-color-scheme: dark) { + :root { + --color-lobsters-fg-has-suggestions: #df7171; + + --color-lobsters-tag-special-bg: #3b1719; + --color-lobsters-tag-special-border: #611a21; + + --color-lobsters-hat-sysop-crown-fill: #3e2f2f; + --color-lobsters-hat-sysop-brim-stroke: #2c2222; + } +} + +li .byline a.story_has_suggestions { + color: var(--color-lobsters-fg-has-suggestions); +} + +a.tag_announce, a.tag_ask, a.tag_show, a.tag_interview { + background-color: var(--color-lobsters-tag-special-bg); + border-color: var(--color-lobsters-tag-special-border); + color: var(--color-fg-67); +} + +span.hat_openbsd_developer span.crown { + font-family: comic sans ms, comic sans, comic neue, sans-serif; + font-size: 7pt; +} + +span.hat_sysop { + border-color: var(--color-lobsters-hat-sysop-brim-stroke); + color: var(--color-fg-67); +} +span.hat_sysop span.crown { + background-color: var(--color-lobsters-hat-sysop-crown-fill); +} + +#l_holder { + position: relative; +} +#l_holder:after { + content: ''; + background: transparent url("/favicon-16x16.png") no-repeat center; + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; +} + +@media +only screen and (min-resolution: 2dppx), +only screen and (-webkit-min-device-pixel-ratio: 2) { + #l_holder { + background: transparent url("/favicon-16x16.png") no-repeat; + background-size: 16px; + background-position: 1px 1px; + } +} diff --git a/app/models/user.rb b/app/models/user.rb index 0d68d209..e61f2bdc 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -143,7 +143,7 @@ class User < ApplicationRecord "sysop", "webmaster", "enable", "new", "signup"].freeze # days old accounts are considered new for - NEW_USER_DAYS = 70 + NEW_USER_DAYS = 7 # minimum karma required to be able to offer title/tag suggestions MIN_KARMA_TO_SUGGEST = 10 diff --git a/app/views/about/about.html.erb b/app/views/about/about.html.erb index 7551fb51..82af547b 100644 --- a/app/views/about/about.html.erb +++ b/app/views/about/about.html.erb @@ -1,369 +1,14 @@ -<% render partial: 'about/subnav' %> -
- <%- raise "Site owner: You need to delete app/views/home/about.html.erb and write your own about page" if Rails.env.production? and Rails.application.name != 'Lobsters' -%> - -
-

- Lobsters is a computing-focused community centered around link aggregation - and discussion, launched on July 3rd, 2012. - The administrator is Peter Bhat Harkins ("pushcx"), contact him with any support issues. - Lobsters was created by joshua stein - with careful design touches to encourage a healthy community: -

- - - -

Tags and Topicality

-

- When links or stories are submitted, they must be tagged by the submitter from a list of predefined tags. - Users can choose to filter out or - subscribe to all submissions with particular tags (example: programming.rss) - or combinations of tags (example: programming,audio.rss). - All users see all stories by default. - The tagging system works this way for three reasons: -

- -
    -
  • - It keeps the site on-topic by only allowing a predefined list of tags. - These tags represent what most of the users of the site want to read, so - content that does not fit into any of those categories should not be - submitted. It also keeps stories organized and more easily searchable. -

  • - -
  • - It promotes discussion. On a site with separate forums, a Ruby programmer - would probably subscribe to a Ruby forum, but not a Python one. When a link - is posted to the Python forum, that Ruby programmer would probably never see - it, even though they may have something useful to say about it (perhaps the - link is about a Python library which does the same thing as a Ruby library - which that Ruby programmer created). On this site, the link would get posted - with a python tag and shown to everyone, - encouraging the Ruby programmer to read and comment on it (unless that Ruby - programmer disliked Python enough to filter it out). -

  • - -
  • - It keeps the community coherent. Often stories contain discussion - about more than one topic, yet on other sites they are confined to a single - category/forum, limiting the exposure. The link could be submitted to more - than one forum, but then each conversation would remain separate and users - would rarely interact with users from other forums. On this site, the story - would simply be tagged with multiple tags and all users would see all - discussion about the story in a single location. -

  • -
- -

- Creating new tags and retiring old tags is done by the community by submitting, discussing, and voting on meta-tagged requests about them, - and these events are logged (since 2018-04). - To propose a tag, post a meta thread with the name and description. - Explain the scope, list existing stories that should have been tagged, make a case for why people would want to specifically filter it out, and justify the increased complexity for submitters and mods. -

- -
-

- Lobsters is focused pretty narrowly on computing; tags like art don't imply every piece of art is on-topic. - Some rules of thumb for great stories to submit: Will this improve the reader's next program? Will it deepen their understanding of their last program? Will it be more interesting in five or ten years? -

- -

- Some things that are off-topic here but popular on larger, similar sites: - entrepreneurship, management, news about companies that employ a lot of programmers, - investing, world events, anthropology, self-help, personal productivity systems, - last-resort customer service requests via public shaming, - "I wanted to see what this site's amazing users think about this off-topic thing", - and - defining the single morally correct economic and political system for the entire world when we can't even settle tabs vs. spaces. -

-
- -

Invitation Tree

-

- The full <%= link_to 'user tree', users_tree_path %> is public and each user's profile - shows who invited them. This provides some degree of accountability and - helps identify voting rings. -

- -

- Invitations are used as a mechanism for spam-control, - to slow registrations to a pace we can acculturate (more below) - and to encourage users to be nice, not to make the Lobsters userbase an elite club. - Users are considered "new" for their first <%= User::NEW_USER_DAYS %> days, - and their usernames appear in green. - New users can't - send invites, - submit links to domains we haven't seen submitted before, - flag stories and comments, - suggest edits to story titles and tags, - resubmit links that have been seen before, - or - use tags for meta discussions or that are prone to off-topic stories - (<% Tag.not_permitted_for_new_users.pluck(:tag).map { |t| %><%= link_to t, tag_path(t) %> <%- } %>). - -

- -

- The quickest way to receive an invitation is to talk to someone you <%= link_to 'recognize from the site', users_tree_path %>. - If you wrote a link that was posted, please reach out in chat, we'd love to have you join the discussion. - Finally, if you can't find anyone you know in the invitation tree and didn't author something posted to the site, - <% if Rails.application.allow_invitation_requests? %> - you can request an invite. - <% else %> - consider getting to know the community in the chat room. - <% end %> -

- -

- There's no limit on how many invitations a user can send (though we might at some point, to manage growth). - There's also no official vetting process for new users, each user is responsible for inviting people they believe will contribute positively to Lobsters. - When accounts are banned for spam, sockpuppeting, or other abuse, - moderators will consider disabling their inviter's ability to send invitations or, rarely, also ban them. -

- -

Ranking

-

- All story and comment ranking on this site comes from user activity. - All users have equal votes, with no special priorities or penalties for specific users or domains. - Moderators have no ability to raise or lower the rankings of stories or comments (besides voting like any user). - Per-tag hotness modifiers affect all stories with - those tags, but these modifiers (and changes to them) are public. - Domains used for marketing analytics are banned and tracking parameters are removed from links - (look for TRACKING_DOMAINS and utm_ in story.rb). -

- -
-

- Users can flag stories and comments when there's a serious problem that needs moderator attention; two flags are needed to add the story or comment to the moderation queue. - Users must reach <%= User::MIN_KARMA_TO_FLAG %> karma to flag. - To guide usage and head off distracting meta conversations ("Why was this flagged!?", etc), flagging requires selecting from a preset list of reasons. -

- -

- For stories, these are: - "Off-topic" for stories that are not about computing; - "Already Posted" for duplicate submissions and links that elaborate on or responses to a thread that's less than a week old (see merging); and - "Broken Link" for links that 404, 500, or present a paywall; - "Spam" for links that promote a commercial service. -

- -

- For comments, these are: - "Off-topic" for drifting into meta or topics that aren't related to the story; - "Me-too" when a comment doesn't add new information, typically a single sentence of appreciation, agreement, or humor; - "Troll" for derailing conversations into classic arguments, well-intentioned or not; - "Unkind" when uncharitable, insulting, or dismissive; - and - "Spam" for promoting commercial services. -

-
- -

- Less than 1% of stories or comments get flagged, and users are not automatically punished by flags. - Users whose stories or comments are getting flagged significantly more often are strongly encouraged to talk to mods about what's not working. - (Please don't use flagging to try to push down topics or people you don't like; click "hide" on the story and move on rather than clutter up the mod dashboard with false alarms.) -

- -

Transparency Policy

-

- All moderator actions on this site are visible to - everyone and the identities of those moderators are <%= link_to 'public', moderators_path %>. - While the individual actions of a moderator may cause debate, there should be no question about if an action happened or who is responsible. -

- -

- If users are disruptive enough to warrant banning, they will be banned - absolutely, given notice of their banning, and their disabled user profile - will indicate which moderator banned them and why. - There will be no shadow banning or other secret moderation actions. -

- -

- The source code to this site and - its provisioning and deployment are - made available under a 3-clause BSD license for viewing, auditing, forking, or contributing to. - The codebase is used to run a dozen or so sister sites (that we know of) and we keep a list; - please get in touch if you've launched one. -

- -

- The Lobsters community is in a sweet spot that it's large enough to be worth asking questions about and small enough the answers make sense. - We have some basic stats available, - and Peter is happy to run queries against the database and Rails/MySQL/nginx logs (but not write them for you), - as long as they don't reveal personal info like IPs, browsing, and voting or create “worst-of” leaderboards celebrating most-flagged users/comments/stories. -

- -

- If you dislike the content or moderation policies here, you may prefer - Y Combinator News, - r/programming, - Slashdot, - Tilde News, or - comp.*. - Or you could use our codebase to start your own site. -

- -

Other Technical Features

- -
    -
  • - Mailing list mode can be enabled - per-user to receive all new stories (including their plain-text content as - fetched and extracted by Diffbot) and user - comments as e-mails, mirroring discussion threads offline. This makes it - easy and efficient to read new stories as well as keep track of new comments - on old threads or stories, just like technical mailing lists or Usenet of - yore. Each user is assigned a private mailing list address at this domain - which allows them to reply to stories or comments directly in their e-mail - client. These e-mails are then converted and submitted to the website as - comments, just as if the comment was posted through a web browser. - <%- raise "Don't just delete that error message. You didn't set up mailing list mode, right? This really isn't your about page, write one from scratch." if Rails.env.production? and Rails.application.name != 'Lobsters' -%> -

    - -
  • - Private messaging enables users to communicate privately - without having to publicly disclose an e-mail address, and users can receive - e-mail and Pushover notifications of new - private messages. -

  • - -
  • - Responsive design enhances functionality on smaller screens - such as phones and tablets without having to use a separate URL, 3rd party - (often read-only) websites, or mobile apps. -

  • - -
  • - Integrated search engine covers all - submitted stories and comments, including full-text caches of all submitted - story contents. Searching for a keyword will often bring up relevant stories - that don't even mention that keyword in the URL or title. -

  • - -
  • - Story merging collects comments on a topic that would otherwise fragment across multiple stories. - This keeps the front page from being overwhelmed by a single topic and the discussion together for those interested (or so disinterested they'd prefer to hide it). - Moderators merge stories on the same topic submitted within a week. - Here's a small and large example. -

  • - -
  • - Fuzzy-matching of submitted story URLs to avoid duplicate - submissions of similar URLs that differ only in http vs. - https, trailing slashes, useless analytics parameters, etc. When - using the story submission bookmarklet, story URLs are automatically - converted to use the page's canonical URL (if available) to present the best - URL to represent the story, as defined by the story's author or publisher. -

  • - -
  • - User-suggested titles and tags can - be automatically applied to a story when a quorum of users agrees on a new - title (such as removing a site's name, or appending the story's year of - publication) or set of tags, without any moderator action required. - (Log) -

  • - -
  • - Hats are a more formal process of - allowing users to post comments while "wearing such and such hat" to - give their words more authority (such as an employee speaking for the - company, or an open source developer speaking for the project). -

  • - -
  • - Per-tag, multi-tag and site-wide RSS feeds are - available to the public and logged-in users have private RSS feeds that - filter out each user's filtered tags. -

  • - -
  • - Official Fediverse mirror - posts all stories that have reached the front page for easy following, retooting/sharing, or archiving. -

  • - - <% if false %> -
  • - Tor onion/hidden - service for anonymous access to the site. -

  • - <% end %> - -
  • - Stickers will be available again when someone finds a service that will print and ship 2" square vinyl stickers - with a bleed <= 1/16" (preferably full-bleed) directly to people who want them. -

  • -
- -

Trivia

- -
    -
  • - Lobsters is hosted on three VPSs at DigitalOcean: - a s-4vcpu-8gb for the web server, - a s-2vcpu-4gb for the mariadb server, and - a s-1vcpu-1gb for the IRC bot. - Our domain name is registered with CRI Domains, who donated our first year of registration. - DNS is provided by DNSimple and - we use restic for backups to b2, both of which pushcx pays for. - Lobsters is cheap to run, so we don't take donations. -

  • - -
  • - 🦞 -

    - Sponsor of the lobster emoji: - In February 2018, Lobsters held a fundraiser - to officially adopt the new lobster emoji in support of the Unicode Foundation. -

  • - -
  • - The name "Lobste.rs" is a cute domain hack - without any deeper meaning. - <%- require 'digest/md5'; instance_variable_set("@#{controller_name}#{action_name}", Digest::MD5.hexdigest(Rails.env) == 'fd89784e59c72499525556f80289b2c7' && Digest::MD5.hexdigest(Rails.application.name) != '4e7c4ddc593da2e7a1cc8c6dc2d38eba') -%> - It has nothing to do - with - self-help guru - Jordan Peterson, whose fans started to call themselves "lobsters" - about six years after we started. -

  • - -
  • -

    - As a Rails app that's big enough to have real-world complexity but small enough to be easily read, - our codebase has seen a few interesting uses: -

    - -

    Please do reach out if you find a use for our code!

    -
  • - -
  • - We have a backup domain lobsters.dev in case of issues with our primary domain. -

  • - -
  • - If you prefer the article links or comment links to open a new tab instead of navigating in your current tab you can add - a client-side script to do so. - (Discussion) -

  • - -
-
+
about
+

this is a link aggregator for the tildeverse.

+
+

Rules

+
    +
  1. Political links are not allowed, unless directly related technology or tilde issues,ie
  2. +
      +
    • Net Neutrality
    • +
    • Privacy
    • +
    +
  3. Please limit content to PG-13, mild R rated
  4. +
diff --git a/app/views/about/chat.html.erb b/app/views/about/chat.html.erb index 19316730..a0077003 100644 --- a/app/views/about/chat.html.erb +++ b/app/views/about/chat.html.erb @@ -1,68 +1,8 @@ -<% render partial: 'about/subnav' %> -
-
-

- An official real-time discussion channel is available to members and guests - of the site, hosted on the - Libera.Chat IRC network - in #lobsters. - This channel was originally - created by - @kristof on freenode, and - stayed with the network on 2021-05-19 after that domain was lost. - @pushcx, - @355e3b (c355e3b on IRC), and - @aleph (Church on IRC) are channel operators. -

+
chat
+ tildeverse irc network here
+ webchat here -

- To participate in the discussion, join the - #lobsters channel on - irc.libera.chat with an IRC client. -

- -

- The policies and ideals of the discussion channel are the same as the website; quality content and conversing, respect for other users, and no spamming. - Slightly off-topic discussion is generally acceptable, but we're still not open to discussion of electoral politics and policies. - The channel isn't busy enough that there's always someone talking, so don't be surprised if you try to start a conversation and no one responds. - Leave it open and you'll see activity, though we're most active during US work hours. -

- -

- If you want an invite to the site, it's best to hang out and chat until people get to know you. - They'll likely ask you for a link to your homepage or a public profile to feel confident that you're not a spammer. - If you ask for an invite immediately on joining, expect people will be a lot more skeptical. -

- -

- If you are the author of or otherwise involved with a story that was submitted to the site, ask and someone can send you an invite. - We've unfortunately had problems with impersonation, so it helps a lot if you point out how your email address is linked to the story. -

- -

- The channel has a bot named - mockturtle. - It announces new stories submitted to the site and provides other useful features like showing the page title of URLs mentioned in the channel. -

- -

- If you'd like a cloak to note that you've contributed to - Lobsters development - or just for privacy as a regular user, contact a channel operator for a - lobsters/developer/username or lobsters/user/username - cloak. -

- -

- For a feed of stories without discussion, mockturtle also posts new stories in #lobsters-feed. -

- -

- Lobsters used to have a channel called #lobsters-boil for off-topic conversations (especially American politics) that "boiled over" from the main channel. - It was useful in the wake of some big events, but the mods didn't want to run it indefinitely. - Community members independently run ##crustaceans subject to their own policies, if you're looking for more off-topic discussion. -

- -
+

new posts are mirrored to tilde.chat in #meta and #tildeverse

+

comments are mirrored to #tildeverse

diff --git a/config/initializers/production.rb b/config/initializers/production.rb new file mode 100644 index 00000000..9437f575 --- /dev/null +++ b/config/initializers/production.rb @@ -0,0 +1,11 @@ +class << Rails.application + def domain + "tilde.news" + end + + def name + "tilde news" + end +end + +Rails.application.routes.default_url_options[:host] = Rails.application.domain diff --git a/config/puma.rb b/config/puma.rb index 476d5df7..dd4a5f14 100644 --- a/config/puma.rb +++ b/config/puma.rb @@ -55,7 +55,7 @@ on_worker_boot { |index| sleep sleep_for_index(index, worker_boot_duration) } # before forking the application. This takes advantage of Copy On Write # process behavior so workers use less memory. if ENV.fetch("RAILS_ENV") == "production" - bind "unix:///srv/lobste.rs/run/puma.sock" + bind "unix:///srv/lobsters/lobsters/run/puma.sock" # phased restarts # https://github.com/puma/puma/blob/master/docs/restart.md diff --git a/db/migrate/20200809023435_create_categories.rb b/db/migrate/20200809023435_create_categories.rb index 54563b86..3fda2faf 100644 --- a/db/migrate/20200809023435_create_categories.rb +++ b/db/migrate/20200809023435_create_categories.rb @@ -8,7 +8,7 @@ class CreateCategories < ActiveRecord::Migration[5.2] end def change - raise "You need to edit this migration to define categories matching your site" unless Rails.application.name == "Lobsters" + #raise "You need to edit this migration to define categories matching your site" unless Rails.application.name == 'Lobsters' create_table :categories do |t| t.string :category @@ -20,18 +20,22 @@ class CreateCategories < ActiveRecord::Migration[5.2] # list your tags in console with: Tag.all.pluck(:tag).join(' ') { - compsci: %w[ai compsci distributed formalmethods graphics osdev plt programming networking], - culture: %w[culture person philosophy law], - field: %w[cogsci crypto education finance hardware math science], - format: %w[ask audio pdf show slides transcript video], - genre: %w[art book event historical job news rant release satire], - interaction: %w[a11y design visualization], - languages: %w[apl assembly c c++ clojure css d dotnet elixir elm erlang fortran go haskell java javascript lisp lua ml nodejs objectivec perl php python ruby rust scala swift], - lobsters: %w[announce interview meta], - os: %w[android dragonflybsd freebsd illumos ios linux mac netbsd openbsd unix windows], - platforms: %w[browsers cryptocurrencies email games ipv6 mobile wasm web], - practices: %w[api debugging devops performance practices privacy reversing scaling security testing virtualization], - tools: %w[compilers databases emacs systemd vcs vim] + misc: ["test"], + capitalism: ["business", "capitalism", "censorship", "cloud-computing", "blockchain", "cryptocurrency", "5G", "adblock", "artificial-intelligence", "data-analysis", "data-brokers", "data-exploration", "data-science", "data-visualization", "extreme-capitalism", "finding-cures", "government", "health-insurance", "information-abundance", "intelligent-cloud", "intelligent-edge", "IoT", "machine-learning", "microsoft", "oracle", "propaganda", "SaaS", "social-data", "social-media", "surveillance", "surveillance-capitalism", "twitch", "U.S.A", "USA", "youtube"], + social: ["IRC", "matrix", "fediverse", "email"], + software: ["projects", "command line", "algorithms", "automation", "FOSS", "GNU", "gnu+linux", "agile", "programming", "open-source", "UNIX", "theory", "design", "kernel", "init", "software-development"], + hardware: ["Hardware", "desktop-computing", "Raspberry-Pi"], + os: ["BSD", "Linux", "macos", "windows", "distros"], + languages: ["bash", "css", "javascript", "lisp", "rust", "python"], + learn: ["ecology", "education", "EFF", "guide", "History", "Hackers", "hackerspace", "learning", "makerspace", "projects", "physics", "science", "space", "leadership"], + tools: ["emacs", "git", "shell", "systemd", "terminal", "ssh", "vim", "dns", "scripting"], + privacy: ["anonymity", "Privacy"], + security: ["cryptography", "cybersecurity", "security"], + tildes: ["yourtilde", "~team", "~town", "envs", "tildes", "tildeverse", "thunix", "system administration"], + culture: ["coffee", "content_warning", "current-events", "Art", "astronomy", "broadcasting", "equality", "fun", "gaming", "general", "health", "meme", "repair", "tips-n-tricks", "today-i-learned", "trivia", "yikes", "random", "MUSH", "satire", "sports"], + people: ["dennis-ritchie", "ken-thompson", "Luke Smith", "paul-ford", "richard-stallman"], + smallinternet: ["decentralized-internet", "gopher", "gemini", "internet-freedom", "lowtech", "self-hosting", "slow", "small internet", "SpartanWeb", "non-commerical-internet", "protocols", "text", "KISS", "design"], + web: ["digitalization", "internet", "modern-web", "mozilla", "Podcasts", "radio", "media", "multiplayer", "Reddit", "search engines", "Video", "web", "web-browsers", "web-development"], }.each do |category, tags| c = Category.create! category: category Tag.where(tag: tags).update_all(category_id: c.id) diff --git a/public/apple-touch-icon-144.png b/public/apple-touch-icon-144.png index 8223fa3f7bc3bb058f24637d11661aea406ef572..e615c07d1c2e00e0aa7466d6c22cfe928f0e985b 100644 GIT binary patch literal 11654 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

SO9`@8`7Fh5TChAaptWFJ1JU-5vab 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 literal 1744 zcmV;>1~2)EP)Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^RX2Lu8z8nwzMQ~&?~B6LMqbVF}# zZDnqB07G(RVRU6=Aa`kWXdp*PO;8|jZXjVGO<`k)sCPpE00uNkL_t(&-ql)5i(N$! z{=PG3GMPyxNG2pVYQShz1j#~;AQ3T%i9+H|5X46iL_rkAg}=asyZG1%E@L30zd$sI zJ0Y$NMzcsZ3Yt-LLWazYQ!dWw?&|01d&NZ#m&@(GUES5y_4um#aB*QC5P$-Kkc54t z{~`eqkPryrjSzwm*iQA+H3gsuh<><$ER6-a1r1*$1;W-R5rhv_C;et_OgsRJ4ZB>K z#CAH8)~9DgliYlH3{$*H#BP~HZ>c9~1)}yP`cF$H{eRuTNjxjuB%~RSkQedE1#Vgi zL@j=+W2sfE0G*1&`_nVgAJZ|QJB8sPyXDNcpd?q?@tP2AXH0#IjxN+eDqUgf_?6Ky zV1Q|+BN+LW6x6PQJh`APsCRrw+OKSfD`g>z) z=QRvd962k_pc`))Ab>WqdL(;t=Lz2p7Q7{f$Rj@xveae2-tHu8&!OhB}52wiy`K#_H-MOp0u*-k|T!NH>45obJ@^ zj;if3g*u9az7k*T-qB1?Z{4@=j_01g`?c5EGzAWS|Mr`UAAk7g_vddcEp?uMJbjHq zpAZyGJv%o8T6jegBw)TfAsD;exN-IBZ(n~kvwdOvgAe5x{p-RH=Z-&l?b6TxtX!w` zQZ&M3H=kaGZY|T<^I@Vw*901Yz-^=Z?Y{kMt3RX8wv^3B`VFCmi;R7UIyL73*>)$_KU=}yoQ0?rAepD8x191Nvdkqet4@up3SylXJVgU=SXt2<`T*a&9`GrN>@>dr5$f07_DuILzB7s zD^&fp-nLZIIbQvhe*Lwp6Ao8bgTKa-D^nz__E~vO}Ig&n&d zKdcm$h1{@p-j2B>#ZuALdj_+Wgp4F~oWR}}Pd1x2h2?&QQWYUu>!lclVMdi@=0dw3 z*)+~IEA?SmBIE4NUH82Cw!Z{DJm9A&&6xFU0WdW?Ti|tSc5b*t4X|k*IQ7x={Cr(R z5nF$yq^_ZI*k$(iJq2Djk4CBbD^;i>n`Zxe@9#eLRMI5r`9)VMYFJTj4=~c`$P)!# z_rCB_)3!vmNn(OOmnsN=a62I2Ub#(ODgcy5Rgtc;QBoi)Vq6?}2_(&0kw>7o};PZuT zV5(*kbms5mosTh?u->*zjVN^|!trG}cxNQlRJj>y4ZwSJVMk=m6_DU+FeO*>;)s*0c}0i8dp0!ry_GAKT#=V6%C!u} m?lCP_U%4`J)e??hGWZv2KT&Jgp4;010000Wv?3>pbPHURNY{9_)VwFsle)`f+N51}Aczn;tw<$9^t{1%)oXb9G%l^5i zz1>c1bSv(>|2UL=!mwSvV)#fKg~)1wlDSxoHC+iY|X-g|OZ zBdeyJrd<4%|HUgF2dTLz@o*njTyUs2T)-`0*3sUyr7Are|N6M|`R#q6GwoQr&j~(d zH;)hrw~3p?%HJ#~et(5wzhaPe8^=`6D?lHsmbgZgq$HN4S|t~y0x1R~14Bz)14~^) zqYy&_D?@WDLo;0i6DtD)CvUFHC>nC}Q!>*kaceLZ+msK~;0CgxI6tkVJh3R1!8128 zJ=HfcJu^95!A#Fw&qCKy0cfR(u7N4gN`*i}Glh(jk^(Dz{qpj1y-bj5AO@<|%P&g5 z)Aklnwg$a!eD4= z#LrOF3REMGWDZnKcxFmT21v=}HHsWSC6Y)=d^2-XODYRe8Nja6FUU)`-xTJDW{z(N zP!)rrsfmG^g{i5rf%DClSwJQHNah4*R;4l+I5|yOWcLOr6^0}g8sy24mYI_Z^uB&> zUP(@Vx_(+>S!Qy6Ua>wflq_@&4Rnnx^eqf6(kxAqEiDp_j4ccelT9oQQjC(5EX*y^ fOp+~<+B5Yv8jslI47%)Z&aiIYdBSaG< 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 Rn2)couct!;9QJOn{{n$F9~A%q