Changeset 4d7443b in Klonkt


Ignore:
Timestamp:
06/14/2026 03:09:49 PM (3 months ago)
Author:
roboburr <roboburr@…>
Branches:
main
Children:
743bb81
Parents:
bf61be7
Message:

hub: home page redesigned as a label landing page

Separate landing instead of a list: hero (company site title + tagline + bio),
"Artists" roster (all sites except the company site, as avatar cards), and a
"Latest posts" feed across all artists. routes/hub.js now separates company
(primary) from artists (other sites).

Co-Authored-By: Claude <noreply@…>

Location:
src
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • src/routes/hub.js

    rbf61be7 r4d7443b  
    4141  `).all();
    4242
    43   // De primaire/oudste site geldt als de bedrijfssite (titel/omschrijving = koptekst).
     43  // De primaire/oudste site geldt als de bedrijfssite (label). De roster toont
     44  // alleen de artiesten (alle overige sites), niet de bedrijfssite zelf.
    4445  const company = res.locals.site || null;
     46  const artists = company ? sites.filter((s) => s.slug !== company.slug) : sites;
    4547
    4648  renderPage(req, res, 'pages/hub-home', {
    4749    pageTitle: company ? company.title : 'Overzicht',
    4850    socialDescr: (company && (company.description || company.tagline)) || '',
    49     bodyClass: 'on-home',
     51    bodyClass: 'on-home on-hub',
    5052    company,
     53    artists,
    5154    posts,
    52     sites,
    5355  });
    5456});
  • src/views/pages/hub-home.ejs

    rbf61be7 r4d7443b  
    1 <div class="container hub-home">
     1<div class="hub">
    22
     3  <%# ── HERO (label / bedrijf) ─────────────────────────────────────── %>
    34  <header class="hub-hero">
    4     <h1><%= company ? company.title : 'Overzicht' %></h1>
    5     <% if (company && (company.tagline || company.description)) { %>
    6       <p class="hub-hero-sub"><%= company.tagline || company.description %></p>
    7     <% } %>
     5    <div class="hub-hero-inner container">
     6      <h1 class="hub-hero-title"><%= company ? company.title : 'Overzicht' %></h1>
     7      <% if (company && company.tagline) { %>
     8        <p class="hub-hero-tag"><%= company.tagline %></p>
     9      <% } %>
     10      <% if (company && (company.profile_bio || company.description)) { %>
     11        <p class="hub-hero-desc"><%= company.profile_bio || company.description %></p>
     12      <% } %>
     13    </div>
    814  </header>
    915
    10   <%# ── Laatste posts van alle gebruikers ─────────────────────────── %>
    11   <section class="hub-section">
    12     <h2 class="hub-h2">Laatste posts</h2>
    13     <% if (posts && posts.length) { %>
    14       <div class="hub-grid">
    15         <% posts.forEach(function(p) { %>
    16           <a class="hub-card" href="/user/<%= p.site_slug %>/<%= p.slug %>">
    17             <% if (p.cover_image_url) { %>
    18               <span class="hub-card-cover" style="background-image:url('<%= p.cover_image_url %>')"></span>
    19             <% } %>
    20             <span class="hub-card-body">
    21               <span class="hub-card-title"><%= p.title %></span>
    22               <% if (p.excerpt) { %><span class="hub-card-excerpt"><%= p.excerpt %></span><% } %>
    23               <span class="hub-card-meta">
    24                 <%= p.site_title %><% if (p.published_at || p.created_at) { %> · <%= formatDate(p.published_at || p.created_at) %><% } %>
    25               </span>
     16  <div class="container hub-body">
     17
     18    <%# ── ARTIESTEN-ROSTER ─────────────────────────────────────────── %>
     19    <% if (artists && artists.length) { %>
     20    <section class="hub-sec">
     21      <h2 class="hub-sec-title">Artiesten</h2>
     22      <div class="roster">
     23        <% artists.forEach(function(a){ %>
     24          <a class="roster-card" href="/user/<%= a.slug %>">
     25            <span class="roster-avatar"<% if (a.profile_photo) { %> style="background-image:url('<%= a.profile_photo %>')"<% } %>>
     26              <% if (!a.profile_photo) { %><%= (a.title || a.slug).charAt(0).toUpperCase() %><% } %>
    2627            </span>
     28            <span class="roster-name"><%= a.title %></span>
     29            <% if (a.tagline) { %><span class="roster-tag"><%= a.tagline %></span><% } %>
     30            <span class="roster-count"><%= a.post_count %> post<%= a.post_count === 1 ? '' : 's' %></span>
    2731          </a>
    2832        <% }); %>
    2933      </div>
    30     <% } else { %>
    31       <p class="hub-empty">Nog geen posts.</p>
     34    </section>
    3235    <% } %>
    33   </section>
    3436
    35   <%# ── PrutFolio's (gebruikers) ───────────────────────────────────── %>
    36   <section class="hub-section">
    37     <h2 class="hub-h2">PrutFolio's</h2>
    38     <% if (sites && sites.length) { %>
    39       <ul class="hub-users">
    40         <% sites.forEach(function(s) { %>
    41           <li>
    42             <a class="hub-user" href="/user/<%= s.slug %>">
    43               <span class="hub-user-avatar">
    44                 <% if (s.profile_photo) { %>
    45                   <img src="<%= s.profile_photo %>" alt="">
    46                 <% } else { %>
    47                   <span><%= (s.title || s.slug).charAt(0).toUpperCase() %></span>
    48                 <% } %>
    49               </span>
    50               <span class="hub-user-meta">
    51                 <span class="hub-user-name"><%= s.title %></span>
    52                 <span class="hub-user-sub"><%= s.post_count %> post<%= s.post_count === 1 ? '' : 's' %></span>
    53               </span>
    54             </a>
    55           </li>
     37    <%# ── LAATSTE POSTS ────────────────────────────────────────────── %>
     38    <% if (posts && posts.length) { %>
     39    <section class="hub-sec">
     40      <h2 class="hub-sec-title">Laatste posts</h2>
     41      <div class="hub-feed">
     42        <% posts.forEach(function(p){ %>
     43          <a class="feed-item" href="/user/<%= p.site_slug %>/<%= p.slug %>">
     44            <% if (p.cover_image_url) { %>
     45              <span class="feed-cover" style="background-image:url('<%= p.cover_image_url %>')"></span>
     46            <% } %>
     47            <span class="feed-body">
     48              <span class="feed-meta"><%= p.site_title %> · <%= formatDate(p.published_at || p.created_at) %></span>
     49              <span class="feed-title"><%= p.title %></span>
     50              <% if (p.excerpt) { %><span class="feed-excerpt"><%= p.excerpt %></span><% } %>
     51            </span>
     52            <span class="feed-arrow" aria-hidden="true">→</span>
     53          </a>
    5654        <% }); %>
    57       </ul>
    58     <% } else { %>
    59       <p class="hub-empty">Nog geen gebruikers.</p>
     55      </div>
     56    </section>
    6057    <% } %>
    61   </section>
    6258
     59  </div>
    6360</div>
    6461
    6562<style>
    66 .hub-home { max-width: 1040px; margin: 2rem auto 4rem; padding: 0 1rem; }
    67 .hub-hero { text-align: center; padding: 1.5rem 0 2rem; border-bottom: 1px solid var(--rule); margin-bottom: 2rem; }
    68 .hub-hero h1 { font-family: var(--font-display, serif); font-size: 2.4rem; margin: 0 0 0.4rem; }
    69 .hub-hero-sub { color: var(--ink-muted); font-size: 1.05rem; margin: 0; }
     63.hub { width: 100%; }
    7064
    71 .hub-section { margin-bottom: 2.5rem; }
    72 .hub-h2 { font-family: var(--font-display, serif); font-size: 1.3rem; margin: 0 0 1rem; }
     65/* ── Hero ─────────────────────────────────────────────────────────── */
     66.hub-hero {
     67  background:
     68    radial-gradient(120% 140% at 50% -20%, color-mix(in srgb, var(--accent) 22%, var(--paper)) 0%, var(--paper) 60%);
     69  border-bottom: 1px solid var(--rule);
     70  text-align: center;
     71}
     72.hub-hero-inner { padding: 4rem 1rem 3.25rem; }
     73.hub-hero-title {
     74  font-family: var(--font-display, serif);
     75  font-size: clamp(2.4rem, 6vw, 3.6rem);
     76  line-height: 1.05; margin: 0;
     77  letter-spacing: -0.01em;
     78}
     79.hub-hero-tag {
     80  margin: 0.6rem 0 0; font-size: 1.05rem; font-weight: 600;
     81  color: var(--accent); text-transform: uppercase; letter-spacing: 0.08em;
     82}
     83.hub-hero-desc {
     84  margin: 1rem auto 0; max-width: 46ch;
     85  color: var(--ink-muted); font-size: 1.05rem; line-height: 1.5;
     86}
    7387
    74 .hub-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 1rem; }
    75 .hub-card {
    76   display: flex; flex-direction: column;
    77   border: 1px solid var(--rule); border-radius: 10px; overflow: hidden;
     88.hub-body { padding-bottom: 4rem; }
     89.hub-sec { margin-top: 3rem; }
     90.hub-sec-title {
     91  font-family: var(--font-display, serif);
     92  font-size: 1.5rem; margin: 0 0 1.2rem;
     93  display: flex; align-items: center; gap: 0.75rem;
     94}
     95.hub-sec-title::after { content: ''; flex: 1; height: 1px; background: var(--rule); }
     96
     97/* ── Roster (artiesten) ───────────────────────────────────────────── */
     98.roster {
     99  display: grid;
     100  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
     101  gap: 1rem;
     102}
     103.roster-card {
     104  display: flex; flex-direction: column; align-items: center; text-align: center;
     105  gap: 0.4rem; padding: 1.5rem 1rem 1.25rem;
     106  border: 1px solid var(--rule); border-radius: 14px;
    78107  background: var(--paper-2); color: var(--ink); text-decoration: none;
    79   transition: border-color 120ms, transform 120ms;
     108  transition: border-color 140ms, transform 140ms, box-shadow 140ms;
    80109}
    81 .hub-card:hover { border-color: var(--accent); transform: translateY(-2px); }
    82 .hub-card-cover { display: block; height: 130px; background-size: cover; background-position: center; background-color: var(--paper); }
    83 .hub-card-body { display: flex; flex-direction: column; gap: 0.35rem; padding: 0.85rem 1rem; }
    84 .hub-card-title { font-weight: 600; font-size: 1.02rem; line-height: 1.25; }
    85 .hub-card-excerpt { color: var(--ink-muted); font-size: 0.88rem; line-height: 1.4;
    86   display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
    87 .hub-card-meta { color: var(--ink-muted); font-size: 0.78rem; margin-top: 0.1rem; }
     110.roster-card:hover {
     111  border-color: var(--accent); transform: translateY(-3px);
     112  box-shadow: 0 8px 24px -12px color-mix(in srgb, var(--accent) 50%, transparent);
     113}
     114.roster-avatar {
     115  width: 84px; height: 84px; border-radius: 50%; margin-bottom: 0.4rem;
     116  background-size: cover; background-position: center; background-color: var(--paper);
     117  display: inline-flex; align-items: center; justify-content: center;
     118  font-family: var(--font-display, serif); font-size: 2rem; font-weight: 600; color: var(--accent);
     119  border: 2px solid color-mix(in srgb, var(--accent) 30%, var(--rule));
     120}
     121.roster-name { font-weight: 700; font-size: 1.08rem; }
     122.roster-tag { color: var(--ink-muted); font-size: 0.82rem; }
     123.roster-count {
     124  margin-top: 0.3rem; font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.06em;
     125  color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent);
     126  padding: 0.15rem 0.6rem; border-radius: 99px;
     127}
    88128
    89 .hub-users { list-style: none; padding: 0; margin: 0;
    90   display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 0.6rem; }
    91 .hub-user { display: flex; align-items: center; gap: 0.7rem; padding: 0.6rem 0.8rem;
    92   border: 1px solid var(--rule); border-radius: 10px; background: var(--paper-2);
    93   color: var(--ink); text-decoration: none; transition: border-color 120ms; }
    94 .hub-user:hover { border-color: var(--accent); }
    95 .hub-user-avatar { width: 40px; height: 40px; border-radius: 50%; overflow: hidden; flex-shrink: 0;
    96   background: var(--paper); color: var(--accent); display: inline-flex; align-items: center; justify-content: center;
    97   font-family: var(--font-display, serif); font-weight: 600; }
    98 .hub-user-avatar img { width: 100%; height: 100%; object-fit: cover; }
    99 .hub-user-meta { display: flex; flex-direction: column; min-width: 0; }
    100 .hub-user-name { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    101 .hub-user-sub { color: var(--ink-muted); font-size: 0.8rem; }
     129/* ── Feed (laatste posts) ─────────────────────────────────────────── */
     130.hub-feed { display: flex; flex-direction: column; gap: 0.6rem; }
     131.feed-item {
     132  display: flex; align-items: center; gap: 1rem;
     133  padding: 0.9rem 1rem; border: 1px solid var(--rule); border-radius: 12px;
     134  background: var(--paper-2); color: var(--ink); text-decoration: none;
     135  transition: border-color 140ms, background 140ms;
     136}
     137.feed-item:hover { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 5%, var(--paper-2)); }
     138.feed-cover {
     139  width: 64px; height: 64px; border-radius: 8px; flex-shrink: 0;
     140  background-size: cover; background-position: center; background-color: var(--paper);
     141}
     142.feed-body { display: flex; flex-direction: column; gap: 0.2rem; min-width: 0; flex: 1; }
     143.feed-meta { font-size: 0.76rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--accent); }
     144.feed-title { font-weight: 600; font-size: 1.05rem; line-height: 1.25; }
     145.feed-excerpt {
     146  color: var(--ink-muted); font-size: 0.88rem; line-height: 1.4;
     147  display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden;
     148}
     149.feed-arrow { color: var(--ink-muted); font-size: 1.2rem; flex-shrink: 0; transition: transform 140ms, color 140ms; }
     150.feed-item:hover .feed-arrow { color: var(--accent); transform: translateX(3px); }
    102151
    103 .hub-empty { color: var(--ink-muted); }
     152@media (max-width: 560px) {
     153  .hub-hero-inner { padding: 2.75rem 1rem 2.25rem; }
     154  .feed-cover { width: 52px; height: 52px; }
     155  .feed-arrow { display: none; }
     156}
    104157</style>
Note: See TracChangeset for help on using the changeset viewer.