AI & Technology

Building Your Research Dissemination Hub: A Private Dashboard for Researchers

Build a custom Next.js application that consolidates your entire Dissemination Engine into one private interface. Paper pipeline tracking, one-click asset generation, and complete privacy.

Building Your Research Dissemination Hub: A Private Dashboard for Researchers

You've learned the techniques. You've built the automation. Now it's time to consolidate everything into a unified interface—your personal Research Dissemination Hub.

This is the capstone of your Dissemination Engine: a professional application that makes systematic dissemination feel effortless.

Why Build a Hub?

The Scattered Tool Problem

Without a hub:

  • Context files in one folder
  • Scripts in another
  • Web Claude for some tasks
  • CLI for others
  • No unified view of your research pipeline

The Hub Solution

With a hub:

  • All papers and their status in one view
  • Research Brains managed centrally
  • One-click generation for all content types
  • Complete privacy on localhost
  • Professional interface you'll actually use

What You'll Build

A Next.js application running locally that provides:

Paper Pipeline Tracker

  • All your papers: in progress, under review, published
  • Dissemination status for each
  • Next actions and deadlines

Research Brain Manager

  • Create and edit Research Brains
  • Manage nuance guardrails
  • Update context as research evolves

Asset Factory Interface

  • One-click generation for any content type
  • Side-by-side editing and preview
  • Verification workflow integration

Media Center

  • Press release generation
  • Soundbite library management
  • Interview preparation tools

Grant Support

  • Broader Impacts generator
  • Dissemination plan creator
  • Track record documentation

Technical Architecture

The Stack

  • Framework: Next.js 14+ with App Router
  • Styling: Tailwind CSS
  • AI: Anthropic API
  • Database: SQLite (local storage)
  • Deployment: Localhost only

Project Structure

research-hub/
├── app/
│   ├── page.tsx              # Dashboard home
│   ├── papers/
│   │   ├── page.tsx          # Paper pipeline
│   │   └── [id]/page.tsx     # Single paper view
│   ├── brain/
│   │   └── page.tsx          # Research Brain manager
│   ├── generate/
│   │   └── page.tsx          # Asset Factory
│   ├── media/
│   │   └── page.tsx          # Media center
│   └── grants/
│       └── page.tsx          # Grant support
├── components/
│   ├── PaperCard.tsx
│   ├── GeneratorPanel.tsx
│   └── BrainEditor.tsx
├── lib/
│   ├── ai.ts                 # Anthropic integration
│   ├── db.ts                 # SQLite operations
│   └── types.ts              # TypeScript types
└── data/
    └── papers.db             # Local database

Core Data Models

Paper Model

// lib/types.ts

interface Paper {
  id: string;
  title: string;
  status: 'drafting' | 'submitted' | 'revision' | 'accepted' | 'published';
  journal?: string;
  publicationDate?: Date;
  researchBrainId: string;
  disseminationStatus: {
    twitterThread: boolean;
    linkedInArticle: boolean;
    pressRelease: boolean;
    blogPost: boolean;
    visualAbstract: boolean;
    newsletterBlurb: boolean;
  };
  createdAt: Date;
  updatedAt: Date;
}

interface ResearchBrain {
  id: string;
  paperId: string;
  contextReadme: string;
  nuanceGuardrails: string;
  styleGuide: string;
  updatedAt: Date;
}

interface GeneratedAsset {
  id: string;
  paperId: string;
  type: 'twitter' | 'linkedin' | 'press' | 'blog' | 'visual' | 'newsletter';
  content: string;
  verified: boolean;
  generatedAt: Date;
}

Building Key Features

The Dashboard

// app/page.tsx

export default async function Dashboard() {
  const papers = await getPapers();
  const stats = calculateStats(papers);

  return (
    <div className="min-h-screen bg-gray-50 p-8">
      <h1 className="text-3xl font-bold mb-8">Research Dissemination Hub</h1>

      {/* Stats Overview */}
      <div className="grid grid-cols-4 gap-6 mb-8">
        <StatCard title="Papers" value={stats.totalPapers} />
        <StatCard title="Published" value={stats.published} />
        <StatCard title="Pending Dissemination" value={stats.pendingDissemination} />
        <StatCard title="Fully Disseminated" value={stats.fullyDisseminated} />
      </div>

      {/* Quick Actions */}
      <div className="grid grid-cols-3 gap-6 mb-8">
        <QuickAction
          title="Generate Launch Package"
          description="Create all assets for a paper"
          href="/generate"
        />
        <QuickAction
          title="Update Research Brain"
          description="Edit context and guardrails"
          href="/brain"
        />
        <QuickAction
          title="Prepare for Interview"
          description="Generate soundbites and practice"
          href="/media"
        />
      </div>

      {/* Recent Papers */}
      <RecentPapers papers={papers.slice(0, 5)} />
    </div>
  );
}

The Asset Generator Interface

// app/generate/page.tsx

'use client';

import { useState } from 'react';
import { generateAsset } from '@/lib/ai';

export default function GeneratePage() {
  const [selectedPaper, setSelectedPaper] = useState<Paper | null>(null);
  const [assetType, setAssetType] = useState<string>('twitter');
  const [generatedContent, setGeneratedContent] = useState<string>('');
  const [loading, setLoading] = useState(false);

  const handleGenerate = async () => {
    if (!selectedPaper) return;

    setLoading(true);
    const content = await generateAsset(
      selectedPaper.researchBrain,
      assetType
    );
    setGeneratedContent(content);
    setLoading(false);
  };

  return (
    <div className="min-h-screen bg-gray-50 p-8">
      <h1 className="text-3xl font-bold mb-8">Asset Generator</h1>

      <div className="grid grid-cols-2 gap-8">
        {/* Input Panel */}
        <div className="bg-white p-6 rounded-lg shadow">
          <h2 className="text-xl font-semibold mb-4">Configuration</h2>

          <PaperSelector
            value={selectedPaper}
            onChange={setSelectedPaper}
          />

          <AssetTypeSelector
            value={assetType}
            onChange={setAssetType}
          />

          <button
            onClick={handleGenerate}
            disabled={!selectedPaper || loading}
            className="w-full mt-6 py-3 bg-blue-600 text-white rounded-lg"
          >
            {loading ? 'Generating...' : 'Generate'}
          </button>
        </div>

        {/* Output Panel */}
        <div className="bg-white p-6 rounded-lg shadow">
          <h2 className="text-xl font-semibold mb-4">Generated Content</h2>

          <div className="prose max-w-none">
            {generatedContent ? (
              <ReactMarkdown>{generatedContent}</ReactMarkdown>
            ) : (
              <p className="text-gray-500">
                Select a paper and asset type, then click Generate.
              </p>
            )}
          </div>

          {generatedContent && (
            <div className="mt-4 flex gap-2">
              <button onClick={() => copyToClipboard(generatedContent)}>
                Copy
              </button>
              <button onClick={() => saveAsset(selectedPaper.id, assetType, generatedContent)}>
                Save
              </button>
              <button onClick={() => markVerified(selectedPaper.id, assetType)}>
                Mark Verified
              </button>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

The Research Brain Editor

// app/brain/page.tsx

'use client';

import { useState, useEffect } from 'react';

export default function BrainEditorPage() {
  const [selectedPaper, setSelectedPaper] = useState<Paper | null>(null);
  const [brain, setBrain] = useState<ResearchBrain | null>(null);

  useEffect(() => {
    if (selectedPaper) {
      loadBrain(selectedPaper.researchBrainId).then(setBrain);
    }
  }, [selectedPaper]);

  const handleSave = async () => {
    if (brain) {
      await saveBrain(brain);
      showNotification('Research Brain saved');
    }
  };

  return (
    <div className="min-h-screen bg-gray-50 p-8">
      <h1 className="text-3xl font-bold mb-8">Research Brain Manager</h1>

      <PaperSelector value={selectedPaper} onChange={setSelectedPaper} />

      {brain && (
        <div className="mt-8 space-y-6">
          {/* Context Readme Editor */}
          <div className="bg-white p-6 rounded-lg shadow">
            <h2 className="text-xl font-semibold mb-4">Context Readme</h2>
            <textarea
              value={brain.contextReadme}
              onChange={(e) => setBrain({...brain, contextReadme: e.target.value})}
              className="w-full h-64 font-mono text-sm p-4 border rounded"
            />
          </div>

          {/* Nuance Guardrails Editor */}
          <div className="bg-white p-6 rounded-lg shadow">
            <h2 className="text-xl font-semibold mb-4">Nuance Guardrails</h2>
            <textarea
              value={brain.nuanceGuardrails}
              onChange={(e) => setBrain({...brain, nuanceGuardrails: e.target.value})}
              className="w-full h-64 font-mono text-sm p-4 border rounded"
            />
          </div>

          {/* Style Guide Editor */}
          <div className="bg-white p-6 rounded-lg shadow">
            <h2 className="text-xl font-semibold mb-4">Style Guide</h2>
            <textarea
              value={brain.styleGuide}
              onChange={(e) => setBrain({...brain, styleGuide: e.target.value})}
              className="w-full h-64 font-mono text-sm p-4 border rounded"
            />
          </div>

          <button
            onClick={handleSave}
            className="px-6 py-3 bg-green-600 text-white rounded-lg"
          >
            Save Changes
          </button>
        </div>
      )}
    </div>
  );
}

AI Integration

The AI Service

// lib/ai.ts

import Anthropic from '@anthropic-ai/sdk';

const client = new Anthropic();

export async function generateAsset(
  brain: ResearchBrain,
  assetType: string
): Promise<string> {
  const prompts = {
    twitter: `Create a Twitter thread (10 tweets)...`,
    linkedin: `Create a LinkedIn article (900 words)...`,
    press: `Create a press release...`,
    blog: `Create a blog post (2000 words)...`,
    newsletter: `Create a 150-word newsletter blurb...`,
  };

  const fullPrompt = `Research Context:
${brain.contextReadme}

Accuracy Guardrails:
${brain.nuanceGuardrails}

Voice/Style:
${brain.styleGuide}

Task:
${prompts[assetType]}

Stay within the accuracy guardrails. Maintain the documented voice.`;

  const message = await client.messages.create({
    model: 'claude-sonnet-4-20250514',
    max_tokens: 4096,
    messages: [{ role: 'user', content: fullPrompt }]
  });

  return message.content[0].text;
}

The Complete Workflow

For Each Paper

  1. Create paper entry in the hub
  2. Build Research Brain using the editor
  3. Generate assets as needed
  4. Verify against guardrails
  5. Execute dissemination on publication
  6. Track completion in pipeline view

Publication Day Protocol

  1. Open hub dashboard
  2. Select the paper
  3. Generate all pending assets
  4. Review and verify each
  5. Copy/export to platforms
  6. Mark dissemination complete

Privacy and Security

All Local

  • Database stored locally
  • No cloud sync required
  • API calls for generation only
  • Your research stays on your machine

Security Practices

// Environment variables for API key
// .env.local
ANTHROPIC_API_KEY=your-key-here

// Never commit keys
// .gitignore
.env.local
data/

Running Your Hub

Development

npm run dev

Access at http://localhost:3000

Production Build

npm run build
npm start

Bookmark for daily use.

The Transformation

With your Research Dissemination Hub:

Unified Interface: Everything in one place

Systematic Process: Consistent workflow for every paper

Complete Privacy: Sensitive work stays local

Time Savings: Minutes instead of hours

Sustainable Practice: Something you'll actually use

This is research dissemination as it should be: systematic, efficient, and accessible.


Claude for Research Dissemination

This article concludes the comprehensive guide to AI-powered research dissemination. Get the complete book with detailed instructions and digital assets.

Explore the Complete Book