Skip to content

Add /news page and 'Co nowego' dashboard card for blog posts #259

@Antoni-Czaplicki

Description

@Antoni-Czaplicki

Summary

Add a public /news page displaying blog posts from the backend, and a "Co nowego" (What's new) card on the dashboard showing recent posts. This improves SEO, allows advertising new features, and keeps users informed.

Backend API (to be implemented separately)

  • GET /api/blog/posts/ — list of published posts (id, title, slug, excerpt, published_at, author_name). Supports ?recent=N to filter posts from the last N days.
  • GET /api/blog/posts/{slug}/ — full post detail with markdown content

Implementation

1. Blog service (src/services/blog.service.ts)

New service extending BaseApiService:

  • getPosts(limit, offset) → paginated list
  • getRecentPosts(days) → posts from last N days (for dashboard card)
  • getPost(slug) → single post detail

2. /news page (src/app/news/page.tsx)

  • Public route (no auth required)
  • List of published posts: title, date, excerpt
  • Click through to /news/{slug}
  • Paginated or infinite scroll
  • Good SEO: proper <title>, meta description, structured data

3. /news/{slug} page (src/app/news/[slug]/page.tsx)

  • Public route
  • Render full markdown content (reuse existing markdown/LaTeX rendering from quiz questions — react-markdown, remark-math, rehype-katex)
  • Show: title, published date, author name, content
  • SEO: dynamic <title> and meta tags from post data
  • Consider generating OG images from post title

4. "Co nowego" dashboard card

Placement: Below the "Dodaj nowy quiz / Importuj quiz" card (ImportButtonsCard), sharing its grid cell or as a new row.

Current dashboard grid (src/app/(dashboard)/page.tsx):

QuestionQuizCard (col 1, row-span-2)  |  LastUsedCard (col 2)      |  SearchCard (col 3)
                                      |  ImportButtonsCard (col 2) |  AboutCard (col 3)

The "Co nowego" card should go in the middle column, below ImportButtonsCard. It should be compact — if there's vertical space to share with ImportButtonsCard, even better.

Visibility logic:

  • Show the card only if there is at least one post from the last 7 days — if no recent posts, don't render the card at all
  • When displayed, show posts from the last 90 days — this gives the card enough content to be useful while keeping it relevant

Data fetching:

  1. Fetch GET /api/blog/posts/?recent=7 to check if there are any posts (this can be a lightweight call, limit=1)
  2. If posts exist, fetch GET /api/blog/posts/?recent=90 to populate the card content
  3. Alternatively, fetch ?recent=90 once and check client-side if any post is from the last 7 days — simpler, single request

Card content:

  • Card header: "Co nowego" with a small icon (e.g., Newspaper from lucide)
  • List of post titles as links to /news/{slug}, with relative dates
  • Keep it compact — no images, no excerpts, just clickable titles
  • Optionally add a "Zobacz wszystkie" link to /news at the bottom

Component: src/app/(dashboard)/components/news-card.tsx

5. Navigation

Add "Aktualności" or "News" link to the main nav bar (between existing items or in a secondary position). Could also be a footer link.

Files to create

File Description
src/services/blog.service.ts Blog API service
src/app/news/page.tsx News list page
src/app/news/[slug]/page.tsx News detail page
src/app/(dashboard)/components/news-card.tsx "Co nowego" dashboard card
src/types/blog.ts BlogPost type definitions

Files to modify

File Changes
src/app/(dashboard)/page.tsx Add NewsCard to grid, prefetch recent posts SSR
Navigation component Add link to /news
src/app/sitemap.ts Include /news and individual post URLs

Design reference

The dashboard currently looks like this (middle column):

┌─────────────────────┐
│   Ostatnio używane   │
│   - Quiz 1           │
│   - Quiz 2           │
│   - ...              │
└─────────────────────┘
┌─────────────────────┐
│  Dodaj nowy quiz     │
│  Importuj quiz       │
├─────────────────────┤  ← "Co nowego" below buttons
│  Co nowego           │
│  • Post title 1      │
│  • Post title 2      │
│  • ...               │
│  Zobacz wszystkie →  │
└─────────────────────┘

The card should feel lightweight — a small section, not a dominant element. If no posts from the last 7 days exist, the card is hidden entirely and the space is reclaimed by the buttons card.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No fields configured for Task.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions