Capture, annotate, and learn from YouTube videos like never before
VidMark is a powerful YouTube video annotation and organization tool that helps you capture insights, write notes, and track your learning progress from videos. With AI-powered summarization, and organization features, VidMark transforms passive viewing into active learning.
- Video Annotation & Note-taking - Capture key insights directly from YouTube videos
- AI-Powered Summarization - Automatically generate video summaries using GenKit AI
- Progress Analytics - Track your learning progress with statistics
- Dark/Light Mode - Customizable UI for comfortable viewing
- Responsive Design - Works seamlessly on desktop and mobile devices
Core Technologies:
- Frontend: Next.js 15 (App Router), TypeScript, React 19
- State Management: Zustand
- Styling: Tailwind CSS, shadcn/ui component library
- Authentication: Clerk
- Database: Convex (serverless database)
- AI Integration: GenKit with Google AI
- Video Processing: YouTube API
Additional Tools:
- Framer Motion (animations)
- Sonner (toast notifications)
- React Hooks (custom hooks)
- Convex (real-time database)
- Vercel (hosting)
Before you begin, ensure you have the following installed:
- Node.js (v18 or higher)
- pnpm (recommended) or npm/yarn
- Git
- A modern browser (Chrome, Firefox, Edge, or Safari)
-
Clone the repository:
git clone https://github.com/yourusername/vid-mark.git cd vid-mark -
Install dependencies:
pnpm install
-
Set up environment variables: Create a
.env.localfile in the root directory and add the following variables:NEXT_PUBLIC_CONVEX_URL=your-convex-url NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=your-clerk-publishable-key
-
Run the development server:
pnpm dev
-
Open the application: Navigate to http://localhost:3000 in your browser.
// Example of how to add a video programmatically
const addVideo = useMutation(api.video.addVideo);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
const videoId = extractVideoId(url);
if (!videoId) return toast.error("Invalid YouTube URL");
await toast.promise(
async () => {
const data = await fetchYouTubeData(videoId);
const channelData = await fetchChannel(data.channelId);
if (!user) throw new Error("You must be logged in");
await addVideo({
...data,
channelPicture: channelData.thumbnail,
});
setUrl("");
},
{
loading: "Adding video...",
success: "Video added!",
error: (err) => err.message || "Something went wrong",
}
);
};// Filter videos by status
const [filter, setFilter] = useState<"all" | "completed" | "watching" | "stared">("all");
const allVideos = useQuery(api.video.listByUser, {});
const completedVideos = useQuery(api.video.GetCompletedVideos);
const watchingVideos = useQuery(api.video.GetisWatchingVideos);
const staredVideos = useQuery(api.video.GetStaredVideos);
let videos = allVideos;
if (filter === "completed") videos = completedVideos;
else if (filter === "watching") videos = watchingVideos;
else if (filter === "stared") videos = staredVideos;VidMark integrates with GenKit AI to automatically generate video summaries. This feature is available in the video detail view.
// Example of tracking video progress
const getPercentage = (videoDuration: number, isProgressed: number) => {
if (videoDuration === 0) return 0;
return Math.min(Math.round((isProgressed / videoDuration) * 100), 100);
};
// Usage in your component
<Progress value={getPercentage(video.duration, video.progress)} />vid-mark/
βββ app/
β βββ (main)/
β β βββ _components/ # Main application components
β β βββ (routes)/ # Route-specific components
β β βββ layout.tsx # Main layout
β β βββ ...
β βββ (marketing)/ # Marketing pages
β β βββ _components/ # Marketing components
β β βββ layout.tsx # Marketing layout
β β βββ page.tsx # Home page
β βββ globals.css # Global styles
β βββ layout.tsx # Root layout
βββ components/
β βββ modals/ # Modal components
β βββ providers/ # Provider components
β βββ search-command.tsx # Search command component
β βββ ui/ # UI components
β βββ ...
βββ convex/ # Convex database schema and functions
βββ hooks/ # Custom hooks
βββ lib/ # Utility functions and libraries
βββ public/ # Static assets
βββ styles/ # CSS files
βββ .env.local # Environment variables
βββ .gitignore # Git ignore rules
βββ package.json # Project dependencies
βββ README.md # This file
| Variable | Description |
|---|---|
NEXT_PUBLIC_CONVEX_URL |
Your Convex application URL |
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY |
Clerk publishable key for authentication |
VidMark uses shadcn/ui for its component library, which allows for easy customization:
- Tailwind CSS: Modify
app/globals.cssfor global styles - Theme: Change the theme in
components/ui/theme-provider.tsx - Components: Customize components in the
components/uidirectory
We welcome contributions from the community! Here's how you can contribute to VidMark:
- Fork the repository
- Clone your fork locally
- Install dependencies using
pnpm install - Set up your environment variables
- Run the development server with
pnpm dev
- Use TypeScript for type safety
- Follow the existing code style and patterns
- Write clear, concise, and well-documented code
- Ensure all code passes the ESLint checks
- Create a new branch for your feature or bug fix
- Make your changes and commit them with descriptive messages
- Push your branch to your fork
- Open a pull request against the main branch
- Video Chunking: Break videos into segments for more granular tracking
- Collaborative Features: Allow sharing notes and annotations with others
- Export Options: Export notes and summaries in various formats
- Advanced AI Features: More sophisticated AI-powered analysis and recommendations
- Mobile App: Native mobile application for iOS and Android
- Performance optimizations
- Additional integrations with educational platforms
- Enhanced analytics and reporting
- Community-driven feature requests