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
- Create paper entry in the hub
- Build Research Brain using the editor
- Generate assets as needed
- Verify against guardrails
- Execute dissemination on publication
- Track completion in pipeline view
Publication Day Protocol
- Open hub dashboard
- Select the paper
- Generate all pending assets
- Review and verify each
- Copy/export to platforms
- 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.
Ready to Build Your Dissemination Engine?
This article concludes the comprehensive guide to AI-powered research dissemination. For the complete book with detailed instructions and digital assets: