advanced-features

Implement advanced task features - Priorities, Tags, Due Dates, Reminders, Recurring Tasks, Search, Filter, and Sort. Use when adding Phase 5 advanced functionality. (project)

181 stars

Best use case

advanced-features is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Implement advanced task features - Priorities, Tags, Due Dates, Reminders, Recurring Tasks, Search, Filter, and Sort. Use when adding Phase 5 advanced functionality. (project)

Teams using advanced-features should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/advanced-features/SKILL.md --create-dirs "https://raw.githubusercontent.com/majiayu000/claude-skill-registry/main/skills/data/advanced-features/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/advanced-features/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How advanced-features Compares

Feature / Agentadvanced-featuresStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Implement advanced task features - Priorities, Tags, Due Dates, Reminders, Recurring Tasks, Search, Filter, and Sort. Use when adding Phase 5 advanced functionality. (project)

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Advanced Features Skill

## Quick Start

1. **Read Phase 5 Constitution** - `constitution-prompt-phase-5.md`
2. **Read Phase 5 Spec** - `spec-prompt-phase-5.md` for user stories
3. **Update database models** - Add new fields and tables
4. **Create migrations** - Alembic migrations
5. **Implement API endpoints** - FastAPI routers
6. **Build UI components** - React components
7. **Add event publishing** - Dapr pub/sub integration

## Feature Overview

| Feature | Description | Priority |
|---------|-------------|----------|
| **Priorities** | Low/Medium/High task priority | P0 |
| **Tags** | Categorize tasks with labels | P0 |
| **Due Dates** | Task deadlines with time | P0 |
| **Reminders** | Notification before due date | P1 |
| **Recurring Tasks** | Daily/Weekly/Monthly repeat | P1 |
| **Search** | Full-text task search | P1 |
| **Filter** | Filter by status/priority/tag | P0 |
| **Sort** | Sort by date/priority/name | P0 |

## Database Models

### Updated Task Model

```python
# backend/src/models/task.py
from sqlmodel import SQLModel, Field, Relationship
from datetime import datetime
from enum import Enum
from typing import Optional
import uuid

class Priority(str, Enum):
    LOW = "low"
    MEDIUM = "medium"
    HIGH = "high"

class RecurrenceType(str, Enum):
    NONE = "none"
    DAILY = "daily"
    WEEKLY = "weekly"
    MONTHLY = "monthly"

class Task(SQLModel, table=True):
    id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
    title: str = Field(max_length=255)
    description: str | None = Field(default=None)
    status: str = Field(default="pending")
    priority: Priority = Field(default=Priority.MEDIUM)
    due_date: datetime | None = Field(default=None)
    recurrence_type: RecurrenceType = Field(default=RecurrenceType.NONE)
    recurrence_interval: int | None = Field(default=None)
    next_occurrence: datetime | None = Field(default=None)
    user_id: uuid.UUID = Field(foreign_key="user.id")
    created_at: datetime = Field(default_factory=datetime.utcnow)
    updated_at: datetime = Field(default_factory=datetime.utcnow)

    # Relationships
    tags: list["TaskTag"] = Relationship(back_populates="task")
    reminders: list["Reminder"] = Relationship(back_populates="task")
```

### Tag Model

```python
# backend/src/models/tag.py
from sqlmodel import SQLModel, Field, Relationship
import uuid

class Tag(SQLModel, table=True):
    id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
    name: str = Field(max_length=50, index=True)
    color: str = Field(default="#6B7280")  # Hex color
    user_id: uuid.UUID = Field(foreign_key="user.id")

    # Relationships
    tasks: list["TaskTag"] = Relationship(back_populates="tag")

class TaskTag(SQLModel, table=True):
    __tablename__ = "task_tag"

    task_id: uuid.UUID = Field(foreign_key="task.id", primary_key=True)
    tag_id: uuid.UUID = Field(foreign_key="tag.id", primary_key=True)

    # Relationships
    task: "Task" = Relationship(back_populates="tags")
    tag: "Tag" = Relationship(back_populates="tasks")
```

### Reminder Model

```python
# backend/src/models/reminder.py
from sqlmodel import SQLModel, Field, Relationship
from datetime import datetime
import uuid

class Reminder(SQLModel, table=True):
    id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
    task_id: uuid.UUID = Field(foreign_key="task.id")
    remind_at: datetime
    message: str | None = Field(default=None)
    is_sent: bool = Field(default=False)
    created_at: datetime = Field(default_factory=datetime.utcnow)

    # Relationships
    task: "Task" = Relationship(back_populates="reminders")
```

## API Endpoints

### Tags Router

```python
# backend/src/routers/tags.py
from fastapi import APIRouter, Depends, HTTPException
from sqlmodel import Session, select
from uuid import UUID

router = APIRouter(prefix="/api/tags", tags=["tags"])

@router.get("/")
async def list_tags(
    session: Session = Depends(get_session),
    user: User = Depends(get_current_user)
):
    """List all tags for current user."""
    statement = select(Tag).where(Tag.user_id == user.id)
    tags = session.exec(statement).all()
    return tags

@router.post("/")
async def create_tag(
    tag_data: TagCreate,
    session: Session = Depends(get_session),
    user: User = Depends(get_current_user)
):
    """Create a new tag."""
    tag = Tag(**tag_data.model_dump(), user_id=user.id)
    session.add(tag)
    session.commit()
    session.refresh(tag)
    return tag

@router.post("/{task_id}/tags/{tag_id}")
async def add_tag_to_task(
    task_id: UUID,
    tag_id: UUID,
    session: Session = Depends(get_session),
    user: User = Depends(get_current_user)
):
    """Add a tag to a task."""
    task_tag = TaskTag(task_id=task_id, tag_id=tag_id)
    session.add(task_tag)
    session.commit()
    return {"status": "added"}

@router.delete("/{task_id}/tags/{tag_id}")
async def remove_tag_from_task(
    task_id: UUID,
    tag_id: UUID,
    session: Session = Depends(get_session)
):
    """Remove a tag from a task."""
    statement = select(TaskTag).where(
        TaskTag.task_id == task_id,
        TaskTag.tag_id == tag_id
    )
    task_tag = session.exec(statement).first()
    if task_tag:
        session.delete(task_tag)
        session.commit()
    return {"status": "removed"}
```

### Filter & Search Endpoint

```python
# backend/src/routers/tasks.py (updated)
from fastapi import Query
from typing import Optional
from datetime import datetime

@router.get("/")
async def list_tasks(
    # Filter parameters
    status: Optional[str] = Query(None, description="Filter by status"),
    priority: Optional[Priority] = Query(None, description="Filter by priority"),
    tag_ids: Optional[list[UUID]] = Query(None, description="Filter by tag IDs"),
    due_before: Optional[datetime] = Query(None, description="Due before date"),
    due_after: Optional[datetime] = Query(None, description="Due after date"),

    # Search
    search: Optional[str] = Query(None, description="Search in title/description"),

    # Sort
    sort_by: str = Query("created_at", description="Sort field"),
    sort_order: str = Query("desc", description="Sort order (asc/desc)"),

    # Pagination
    page: int = Query(1, ge=1),
    page_size: int = Query(20, ge=1, le=100),

    session: Session = Depends(get_session),
    user: User = Depends(get_current_user)
):
    """List tasks with filtering, search, and sorting."""
    statement = select(Task).where(Task.user_id == user.id)

    # Apply filters
    if status:
        statement = statement.where(Task.status == status)
    if priority:
        statement = statement.where(Task.priority == priority)
    if due_before:
        statement = statement.where(Task.due_date <= due_before)
    if due_after:
        statement = statement.where(Task.due_date >= due_after)

    # Tag filter (requires join)
    if tag_ids:
        statement = statement.join(TaskTag).where(TaskTag.tag_id.in_(tag_ids))

    # Full-text search
    if search:
        search_term = f"%{search}%"
        statement = statement.where(
            (Task.title.ilike(search_term)) |
            (Task.description.ilike(search_term))
        )

    # Sorting
    sort_column = getattr(Task, sort_by, Task.created_at)
    if sort_order == "desc":
        statement = statement.order_by(sort_column.desc())
    else:
        statement = statement.order_by(sort_column.asc())

    # Pagination
    offset = (page - 1) * page_size
    statement = statement.offset(offset).limit(page_size)

    tasks = session.exec(statement).all()
    return tasks
```

### Reminders Router

```python
# backend/src/routers/reminders.py
from fastapi import APIRouter, Depends
from dapr.clients import DaprClient

router = APIRouter(prefix="/api/reminders", tags=["reminders"])

@router.post("/")
async def create_reminder(
    reminder_data: ReminderCreate,
    session: Session = Depends(get_session),
    user: User = Depends(get_current_user)
):
    """Create a reminder for a task."""
    # Create reminder in database
    reminder = Reminder(**reminder_data.model_dump())
    session.add(reminder)
    session.commit()
    session.refresh(reminder)

    # Publish event for scheduling
    with DaprClient() as client:
        client.publish_event(
            pubsub_name="taskpubsub",
            topic_name="reminder-events",
            data={
                "event_type": "reminder.created",
                "reminder_id": str(reminder.id),
                "task_id": str(reminder.task_id),
                "user_id": str(user.id),
                "remind_at": reminder.remind_at.isoformat()
            }
        )

    return reminder
```

## Frontend Components

### Priority Badge Component

```tsx
// frontend/components/tasks/priority-badge.tsx
import { Badge } from "@/components/ui/badge";

interface PriorityBadgeProps {
  priority: "low" | "medium" | "high";
}

const priorityConfig = {
  low: { label: "Low", className: "bg-gray-100 text-gray-800" },
  medium: { label: "Medium", className: "bg-yellow-100 text-yellow-800" },
  high: { label: "High", className: "bg-red-100 text-red-800" },
};

export function PriorityBadge({ priority }: PriorityBadgeProps) {
  const config = priorityConfig[priority];
  return <Badge className={config.className}>{config.label}</Badge>;
}
```

### Tag Component

```tsx
// frontend/components/tasks/tag-badge.tsx
import { Badge } from "@/components/ui/badge";
import { X } from "lucide-react";

interface TagBadgeProps {
  name: string;
  color: string;
  onRemove?: () => void;
}

export function TagBadge({ name, color, onRemove }: TagBadgeProps) {
  return (
    <Badge
      style={{ backgroundColor: color }}
      className="text-white flex items-center gap-1"
    >
      {name}
      {onRemove && (
        <X className="h-3 w-3 cursor-pointer" onClick={onRemove} />
      )}
    </Badge>
  );
}
```

### Filter Bar Component

```tsx
// frontend/components/tasks/filter-bar.tsx
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Input } from "@/components/ui/input";
import { DatePicker } from "@/components/ui/date-picker";

interface FilterBarProps {
  onFilterChange: (filters: TaskFilters) => void;
}

export function FilterBar({ onFilterChange }: FilterBarProps) {
  const [filters, setFilters] = useState<TaskFilters>({});

  return (
    <div className="flex gap-4 flex-wrap">
      <Input
        placeholder="Search tasks..."
        onChange={(e) => handleSearchChange(e.target.value)}
        className="w-64"
      />

      <Select onValueChange={(value) => handleFilterChange("status", value)}>
        <SelectTrigger className="w-32">
          <SelectValue placeholder="Status" />
        </SelectTrigger>
        <SelectContent>
          <SelectItem value="pending">Pending</SelectItem>
          <SelectItem value="in_progress">In Progress</SelectItem>
          <SelectItem value="completed">Completed</SelectItem>
        </SelectContent>
      </Select>

      <Select onValueChange={(value) => handleFilterChange("priority", value)}>
        <SelectTrigger className="w-32">
          <SelectValue placeholder="Priority" />
        </SelectTrigger>
        <SelectContent>
          <SelectItem value="low">Low</SelectItem>
          <SelectItem value="medium">Medium</SelectItem>
          <SelectItem value="high">High</SelectItem>
        </SelectContent>
      </Select>

      <DatePicker
        placeholder="Due before"
        onChange={(date) => handleFilterChange("due_before", date)}
      />
    </div>
  );
}
```

## Event Publishing

```python
# backend/src/services/task_events.py
from dapr.clients import DaprClient
import json

class TaskEventPublisher:
    """Publish task events to Kafka via Dapr."""

    async def publish_task_created(self, task: Task):
        await self._publish("task.created", task)

    async def publish_task_updated(self, task: Task):
        await self._publish("task.updated", task)

    async def publish_task_deleted(self, task_id: str, user_id: str):
        with DaprClient() as client:
            client.publish_event(
                pubsub_name="taskpubsub",
                topic_name="task-events",
                data=json.dumps({
                    "event_type": "task.deleted",
                    "task_id": task_id,
                    "user_id": user_id,
                    "timestamp": datetime.utcnow().isoformat()
                })
            )

    async def _publish(self, event_type: str, task: Task):
        with DaprClient() as client:
            client.publish_event(
                pubsub_name="taskpubsub",
                topic_name="task-events",
                data=json.dumps({
                    "event_type": event_type,
                    "task_id": str(task.id),
                    "user_id": str(task.user_id),
                    "task": task.model_dump(mode="json"),
                    "timestamp": datetime.utcnow().isoformat()
                })
            )
```

## Alembic Migration

```python
# backend/alembic/versions/xxx_add_advanced_features.py
"""Add advanced task features

Revision ID: xxx
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

def upgrade():
    # Add new columns to task table
    op.add_column('task', sa.Column('priority', sa.String(10), default='medium'))
    op.add_column('task', sa.Column('due_date', sa.DateTime(), nullable=True))
    op.add_column('task', sa.Column('recurrence_type', sa.String(10), default='none'))
    op.add_column('task', sa.Column('recurrence_interval', sa.Integer(), nullable=True))
    op.add_column('task', sa.Column('next_occurrence', sa.DateTime(), nullable=True))

    # Create tag table
    op.create_table(
        'tag',
        sa.Column('id', postgresql.UUID(as_uuid=True), primary_key=True),
        sa.Column('name', sa.String(50), nullable=False),
        sa.Column('color', sa.String(7), default='#6B7280'),
        sa.Column('user_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('user.id'))
    )

    # Create task_tag junction table
    op.create_table(
        'task_tag',
        sa.Column('task_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('task.id'), primary_key=True),
        sa.Column('tag_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('tag.id'), primary_key=True)
    )

    # Create reminder table
    op.create_table(
        'reminder',
        sa.Column('id', postgresql.UUID(as_uuid=True), primary_key=True),
        sa.Column('task_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('task.id')),
        sa.Column('remind_at', sa.DateTime(), nullable=False),
        sa.Column('message', sa.Text(), nullable=True),
        sa.Column('is_sent', sa.Boolean(), default=False),
        sa.Column('created_at', sa.DateTime(), default=sa.func.now())
    )

    # Create indexes
    op.create_index('ix_task_priority', 'task', ['priority'])
    op.create_index('ix_task_due_date', 'task', ['due_date'])
    op.create_index('ix_tag_name', 'tag', ['name'])
    op.create_index('ix_reminder_remind_at', 'reminder', ['remind_at'])

def downgrade():
    op.drop_index('ix_reminder_remind_at')
    op.drop_index('ix_tag_name')
    op.drop_index('ix_task_due_date')
    op.drop_index('ix_task_priority')
    op.drop_table('reminder')
    op.drop_table('task_tag')
    op.drop_table('tag')
    op.drop_column('task', 'next_occurrence')
    op.drop_column('task', 'recurrence_interval')
    op.drop_column('task', 'recurrence_type')
    op.drop_column('task', 'due_date')
    op.drop_column('task', 'priority')
```

## Verification Checklist

- [ ] Database models updated (Task, Tag, TaskTag, Reminder)
- [ ] Alembic migration created and applied
- [ ] Tags API endpoints working
- [ ] Reminders API endpoints working
- [ ] Filter/Search/Sort working on tasks list
- [ ] Priority badges displayed in UI
- [ ] Tag management UI working
- [ ] Due date picker working
- [ ] Events published to Kafka
- [ ] All tests passing

## References

- [Phase 5 Spec](../../../spec-prompt-phase-5.md) - User stories
- [SQLModel Relationships](https://sqlmodel.tiangolo.com/tutorial/relationship-attributes/)
- [FastAPI Query Parameters](https://fastapi.tiangolo.com/tutorial/query-params/)
- [Phase 5 Constitution](../../../constitution-prompt-phase-5.md)

Related Skills

advanced-skill-creator

181
from majiayu000/claude-skill-registry

Meta-skill that generates domain-specific skills using advanced reasoning techniques. PROACTIVELY activate for: (1) Create/build/make skills, (2) Generate expert panels for any domain, (3) Design evaluation frameworks, (4) Create research workflows, (5) Structure complex multi-step processes, (6) Instantiate templates with parameters. Triggers: "create a skill for", "build evaluation for", "design workflow for", "generate expert panel for", "how should I approach [complex task]", "create skill", "new skill for", "skill template", "generate skill"

advanced-rendering

181
from majiayu000/claude-skill-registry

Master high-performance rendering for large datasets with Datashader. Use this skill when working with datasets exceeding 100M+ points, optimizing visualization performance, or implementing efficient rendering strategies with rasterization and colormapping techniques.

Advanced React Clean Integration

181
from majiayu000/claude-skill-registry

Integrate React with clean architecture without framework leakage using hooks as adapters and presenters. Use when connecting React to domain logic, designing hook-based DI, or isolating UI from business rules.

Advanced RE Analysis

181
from majiayu000/claude-skill-registry

Specialized reverse engineering analysis workflows for binary analysis, pattern recognition, and vulnerability assessment

advanced-patterns

181
from majiayu000/claude-skill-registry

Advanced T-SQL patterns and techniques for SQL Server. Use this skill when: (1) User needs help with CTEs or recursive queries, (2) User asks about APPLY operator, (3) User wants MERGE or OUTPUT clause help, (4) User works with temporal tables, (5) User needs In-Memory OLTP guidance, (6) User asks about advanced grouping (ROLLUP, CUBE, GROUPING SETS).

advanced-oscal-validator

181
from majiayu000/claude-skill-registry

Perform comprehensive OSCAL validation using community-inspired patterns including JSON schema validation, business rule validation, cross-reference checking, and best practices from IBM Trestle, oscal-pydantic, and Lula. Use for thorough document quality assurance.

Advanced Modular Library Design

181
from majiayu000/claude-skill-registry

Design modular libraries with clear package boundaries, feature-first organization, and clean API surfaces. Use when structuring monorepos, defining module boundaries, or designing library APIs.

advanced-memory-skill-creator

181
from majiayu000/claude-skill-registry

Use when planning, scaffolding, validating, or packaging Claude skills inside Advanced Memory MCP.

advanced-memoization-strategies

181
from majiayu000/claude-skill-registry

Apply principled memoization techniques to reduce re-rendering without introducing correctness bugs.

advanced-math-trading/robustness-risk

181
from majiayu000/claude-skill-registry

Tail risk, EVT, regularization, validation guardrails, and common pitfalls.

advanced-math-trading/portfolio-factors

181
from majiayu000/claude-skill-registry

Factor modeling and portfolio construction (Markowitz, Black-Litterman, constraints, turnover).

advanced-math-trading/foundations-core

181
from majiayu000/claude-skill-registry

Probability, moments/tails, Bayes, and statistical learning foundations for systematic trading.