DEV Community

Subhendu Das
Subhendu Das

Posted on

Building a Content Calendar in DoAide Pulse

Calendar Idea Planning

Problem

Side‑project developers often publish blog posts and social updates on a whim. Without a structured schedule, content gets missed, deadlines slip, and the marketing cadence feels ad‑hoc. The result is an inconsistent presence on channels like Dev.to and Bluesky, which hurts discoverability. This is where content calendar pays off in practice.

How It Works

DoAide Pulse solves this by turning the idea‑to‑publish pipeline into a single, AI‑driven workflow. The feature is split into three layers:

  1. FastAPI API – exposes CRUD endpoints for calendar entries.
  2. Celery Workers – generate drafts, run quality gates, and push to the Dev.to API on a schedule.
  3. React UI – presents an interactive calendar that lets users drag‑and‑drop ideas and preview AI‑generated content.

When a developer creates a new entry, they provide a headline, tags, and an optional focus keyword. The backend calls an AI model (via OpenAI’s API) to draft the post body, social copy, and meta tags. The draft is stored in PostgreSQL, then queued in Redis for a Celery task that will publish it at the scheduled time. Getting content calendar right early saves rework later.

Implementation Details

FastAPI Endpoint

@router.post("/calendar/", response_model=CalendarEntry)
async def create_entry(entry: CalendarCreate, db: Session = Depends(get_db)):
    db_entry = CalendarEntry(**entry.dict())
    db.add(db_entry)
    db.commit()
    db.refresh(db_entry)
    # Queue AI generation
    task = generate_content.delay(db_entry.id)
    db_entry.task_id = task.id
    db.commit()
    return db_entry
Enter fullscreen mode Exit fullscreen mode

The endpoint validates that the headline is non‑empty and that the URL is HTTP/HTTPS, mirroring the recent fix: a blank template name or idea headline is refused commit.

Celery Task

@celery.task
def generate_content(entry_id):
    entry = db.query(CalendarEntry).get(entry_id)
    prompt = f"Write a 600‑word blog post about {entry.headline} with focus keyword {entry.focus_keyword}."
    draft = openai.Completion.create(engine="gpt-4", prompt=prompt, max_tokens=800)
    entry.draft = draft.choices[0].text
    db.commit()
    # Schedule publish
    publish_task.apply_async((entry.id,), eta=entry.scheduled_at)
Enter fullscreen mode Exit fullscreen mode

The task uses the openai Python client, stores the draft, and schedules a separate publish_task that will hit the Dev.to API.

Publish Task

@celery.task
def publish_task(entry_id):
    entry = db.query(CalendarEntry).get(entry_id)
    response = devto_api.publish(entry.draft, entry.tags)
    entry.published_at = datetime.utcnow()
    entry.devto_url = response.url
    db.commit()
Enter fullscreen mode Exit fullscreen mode

The devto_api wrapper encapsulates the official Dev.to API endpoints, handling authentication and rate limiting. Good content calendar keeps the rest of the workflow predictable.

React Calendar UI

The UI is built with Vite, React, and Tailwind CSS. The calendar component uses the react‑datepicker library to render a month view. Each cell can contain a stack of cards representing scheduled posts.

<Calendar>
  {entries.map(entry => (
    <Day key={entry.id} date={entry.scheduled_at}>
      <Card title={entry.headline} status={entry.status} />
    </Day>
  ))}
</Calendar>
Enter fullscreen mode Exit fullscreen mode

Drag‑and‑drop is implemented with react‑dnd. When a card is moved, a PATCH request updates the scheduled_at field in the FastAPI backend. Treat content calendar as a habit rather than a one-off task.

Example Workflow

  1. Create an Idea – The developer opens the calendar UI, clicks Add Post, and fills in the headline and tags.
  2. AI Draft – The backend immediately queues a Celery task. Within seconds, a draft appears in the card preview.
  3. Adjust Schedule – The user drags the card to a desired date. The backend updates the schedule.
  4. Publish – At the scheduled time, the publish_task posts the content to Dev.to and records the URL.
  5. Analytics – A separate dashboard shows subscriber growth and engagement, tied to the subscriber growth analytics commit.

The process eliminates the need for manual drafting, scheduling, and publishing, giving indie developers a reliable marketing cadence.

Conclusion

The Calendar Idea Planning feature turns a chaotic, manual workflow into a predictable, AI‑augmented pipeline. By combining FastAPI, Celery, Redis, and React, DoAide Pulse provides a developer‑friendly marketing automation stack that keeps side projects visible on the channels that matter.


All code snippets are illustrative and reflect the architecture described in the recent GitHub commits.

Related reading

Top comments (0)