Skip to content

Get Article List

Interface Information

  • Endpoint: /api/articles
  • Method: GET
  • Content-Type: application/json
  • Authentication Required: No

Request Parameters

Query Parameters

ParameterTypeRequiredDefaultDescription
pagenumberNo1Page number (starting from 1)
limitnumberNo4Items per page (maximum 20)
featuredbooleanNofalseWhether to get only featured articles

Request Examples

Get first page of articles

bash
curl -X GET "http://localhost:3000/api/articles?page=1&limit=4"
bash
curl -X GET "http://localhost:3000/api/articles?featured=true&limit=6"

Get page 2 articles, 10 per page

bash
curl -X GET "http://localhost:3000/api/articles?page=2&limit=10"

Response Example

Success Response

json
{
  "success": true,
  "data": [
    {
      "id": 1,
      "title": "Nuxt 4 Full-Stack Development Guide",
      "excerpt": "This article details how to build modern full-stack applications with Nuxt 4...",
      "date": "2025-01-20T00:00:00.000Z",
      "category": "Technical Sharing",
      "cover": "https://example.com/covers/article1.jpg",
      "comments": 5,
      "views": 1200,
      "slug": "nuxt-4-full-stack-development-guide-1"
    },
    {
      "id": 2,
      "title": "Vue 3 Composition API Best Practices",
      "excerpt": "Deep understanding of Vue 3 Composition API usage techniques...",
      "date": "2025-01-18T00:00:00.000Z",
      "category": "Frontend Development",
      "cover": "https://example.com/covers/article2.jpg",
      "comments": 3,
      "views": 850,
      "slug": "vue-3-composition-api-best-practices-2"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 4,
    "total": 50,
    "pages": 13
  }
}

Response Field Descriptions

Article Object Fields

Field NameTypeDescription
idnumberArticle ID
titlestringArticle title
excerptstringArticle excerpt (first 100 characters)
datestringPublication date (ISO 8601)
categorystringCategory name
coverstring | nullCover image URL
commentsnumberComment count (currently fixed at 0)
viewsnumberView count
slugstringArticle slug (for routing)

Pagination Object Fields

Field NameTypeDescription
pagenumberCurrent page number
limitnumberItems per page
totalnumberTotal records
pagesnumberTotal pages

Slug Generation Rules

Slug is generated from title and ID, format: {title-pinyin}-{id}

Example:

  • Title: "Nuxt 4 Full-Stack Development Guide", ID: 1
  • Slug: "nuxt-4-full-stack-development-guide-1"

Frontend Integration Examples

Using useFetch

vue
<script setup>
const route = useRoute()
const page = computed(() => route.query.page || 1)
const limit = computed(() => route.query.limit || 4)

const { data, pending, error, refresh } = await useFetch('/api/articles', {
  query: { page, limit }
})
</script>

<template>
  <div>
    <div v-if="pending">Loading...</div>
    <div v-else-if="error">Load failed</div>
    <div v-else>
      <!-- Article list -->
      <article v-for="article in data.value.data" :key="article.id">
        <img :src="article.cover" :alt="article.title" />
        <h3>{{ article.title }}</h3>
        <p>{{ article.excerpt }}</p>
        <NuxtLink :to="`/articles/${article.slug}`">Read more</NuxtLink>
      </article>

      <!-- Pagination -->
      <div class="pagination">
        <NuxtLink 
          v-if="data.pagination.page > 1"
          :to="`?page=${data.pagination.page - 1}`"
        >
          Previous
        </NuxtLink>
        <span>Page {{ data.pagination.page }} of {{ data.pagination.pages }}</span>
        <NuxtLink 
          v-if="data.pagination.page < data.pagination.pages"
          :to="`?page=${data.pagination.page + 1}`"
        >
          Next
        </NuxtLink>
      </div>
    </div>
  </div>
</template>

Using Composable Function

typescript
// app/composables/useArticles.ts
export function useArticles() {
  const articles = ref([])
  const pagination = ref({
    page: 1,
    limit: 4,
    total: 0,
    pages: 0
  })
  const loading = ref(false)
  const error = ref(null)

  const fetchArticles = async (params = {}) => {
    loading.value = true
    error.value = null

    try {
      const response = await fetch(`/api/articles?${new URLSearchParams(params)}`)
      const result = await response.json()

      if (result.success) {
        articles.value = result.data
        pagination.value = result.pagination
      } else {
        throw new Error(result.message)
      }
    } catch (err) {
      error.value = err.message
    } finally {
      loading.value = false
    }
  }

  const loadPage = (page: number) => {
    fetchArticles({ page, limit: pagination.value.limit })
  }

  return {
    articles,
    pagination,
    loading,
    error,
    fetchArticles,
    loadPage
  }
}

Usage Scenarios

1. Homepage Article List

javascript
const { data } = await useFetch('/api/articles', {
  query: { featured: true, limit: 4 }
})

2. Article Category Page

javascript
const { data } = await useFetch('/api/articles', {
  query: { page, limit: 10 }
})

3. Infinite Scroll Loading

javascript
const { articles, pagination, fetchArticles } = useArticles()

const loadMore = async () => {
  if (pagination.value.page < pagination.value.pages) {
    await fetchArticles({ page: pagination.value.page + 1 })
    // Merge data
  }
}

// Listen to scroll events
window.addEventListener('scroll', () => {
  if (isBottom() && !loading.value) {
    loadMore()
  }
})

Notes

  1. Only returns published articles: Articles with status published
  2. Pagination limits: Maximum 20 items per page, exceeding will be limited
  3. Time sorting: Default sorted by creation time descending
  4. Comment count: Currently fixed at 0, pending comment feature implementation