SuperAPI AI Directory

bitlysis-fullstack

Coding & development

View repository

Updated 10-15 18:45

About this skill

Bitlysis — Fullstack Development

When to Use

  • Building Next.js pages, layouts, or components
  • Creating FastAPI API endpoints
  • Designing database schemas with Drizzle ORM
  • Implementing data fetching with TanStack Query
  • Building full-stack features end-to-end

Instructions

Step 1: Next.js 15 / React 19 Rules

// ✅ Prefer Server Components — no 'use client' unless interactive
// app/dashboard/page.tsx
import { DataTable } from "@/components/data-table";
import { getAnalysisResults } from "@/lib/db/queries";

export default async function DashboardPage({ searchParams, }: { searchParams: Promise<{ page?: string }>; }) { const { page } = await searchParams; // Always await in App Router const results = await getAnalysisResults({ page: Number(page ?? 1) });

return ; }


```typescript
// ✅ Client components: only when you need interactivity
"use client";
import { useActionState } from "react"; // NOT useFormState (deprecated)

export function UploadForm() {
  const [state, formAction, isPending] = useActionState(uploadAction, null);
  return <form action={formAction}>...</form>;
}

Step 2: FastAPI Endpoint Pattern

from fastapi import FastAPI, Depends, HTTPException
from pydantic import BaseModel, Field
from typing import Annotated

app = FastAPI()

class AnalysisRequest(BaseModel):
    file_id: str = Field(..., description="Uploaded file identifier")
    method: Literal["anova", "ttest", "regression"] = "anova"

class AnalysisResponse(BaseModel):
    result_id: str
    summary: str
    p_value: float
    effect_size: float

@app.post("/api/v1/analyze", response_model=AnalysisResponse, status_code=202)
async def run_analysis(
    request: AnalysisRequest,
    db: Annotated[AsyncSession, Depends(get_db)],
    current_user: Annotated[User, Depends(get_current_user)],
) -> AnalysisResponse:
    """Trigger statistical analysis on an uploaded file."""
    file = await db.get(UploadedFile, request.file_id)
    if not file or file.owner_id != current_user.id:
        raise HTTPException(404, "File not found")
    
    result = await analysis_service.run(file, request.method)
    return AnalysisResponse(**result.model_dump())

Step 3: Database Schema (Drizzle ORM)

// db/schema/analysis.ts
import { pgTable, text, timestamp, real, uuid } from "drizzle-orm/pg-core";

export const analysisResults = pgTable("analysis_results", {
  id: uuid("id").primaryKey().defaultRandom(),
  fileId: uuid("file_id").notNull().references(() => uploadedFiles.id),
  userId: uuid("user_id").notNull().references(() => users.id),
  method: text("method").notNull(),
  pValue: real("p_value"),
  effectSize: real("effect_size"),
  summary: text("summary"),
  createdAt: timestamp("created_at").defaultNow().notNull(),
});

Step 4: Data Fetching (TanStack Query 5.95+)

// hooks/use-analysis.ts
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";

export function useAnalysisResult(resultId: string) {
  return useQuery({
    queryKey: ["analysis", resultId],
    queryFn: () => api.analysis.get(resultId),
    enabled: !!resultId,
    staleTime: 5 * 60 * 1000, // 5 minutes
  });
}

export function useRunAnalysis() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (req: AnalysisRequest) => api.analysis.post(req),
    onSuccess: (data) => {
      queryClient.invalidateQueries({ queryKey: ["analysis"] });
    },
  });
}

Step 5: Error Handling Pattern

// lib/api-client.ts — centralized error handling
export class ApiError extends Error {
  constructor(
    public readonly status: number,
    message: string,
    public readonly code?: string,
  ) {
    super(message);
  }
}

async function apiRequest<T>(url: string, options?: RequestInit): Promise<T> {
  const res = await fetch(url, options);
  if (!res.ok) {
    const body = await res.json().catch(() => ({}));
    throw new ApiError(res.status, body.message ?? "Request failed", body.code);
  }
  return res.json();
}

Step 6: Component Structure

// components/data-table.tsx — standard component structure
import type { AnalysisResult } from "@/types";

// 1. Types at top
type Props = {
  data: AnalysisResult[];
  onRowClick?: (row: AnalysisResult) => void;
};

// 2. Main component
export function DataTable({ data, onRowClick }: Props) {
  // 3. Hooks
  // 4. Derived state (useMemo)
  // 5. Callbacks (useCallback)
  // 6. Early returns for loading/empty states
  if (!data.length) return <EmptyState />;
  // 7. Render
}

// 8. Sub-components below
function EmptyState() { ... }

Output Format

For each feature, provide:

  1. Database schema (if new tables needed)
  2. API endpoint (FastAPI)
  3. React component or hook (Next.js)
  4. Types/interfaces

Activate Specialist

@.cursor/.agents/.agents/fullstack-developer.md