A minimalistic blog built with Next.js, React, and TypeScript. It uses Markdown for content and features search functionality powered by vector embeddings.
Design inspired by James Quiambao and Lee Robinson.
- Markdown-based blog posts with frontmatter
- Dark/light mode support
- Three types of search:
- Keyword search (traditional text search)
- Semantic search (using vector embeddings)
- Hybrid search (combination of both)
- RSS feed generation
- Responsive design
- Automated embedding generation via GitHub Actions
To run the development server:
npm run dev
To build for production:
npm run build
Post content is processed into semantic embeddings using VoyageAI's embedding model. New embeddings are generated automatically via GitHub Actions when posts are added or updated.
To manually generate embeddings for a specific post:
npm run generate-embeddings [post-slug]
To generate embeddings for all posts:
npm run generate-embeddings
Improvements
- Syntax highlight https://bionicjulia.com/blog/setting-up-nextjs-markdown-blog-with-typescript
- Add sitemap using next-sitemap
- Optimize image loading https://macwright.com/2016/05/03/the-featherweight-website
- Make thoughts page faster
- improve SEO
New features
- indicator for which page user is on like https://macwright.com/
- I'm feeling lucky feature, that randomly selects a blog
- expanding text
- Create pop up notes like https://www.rishi.cx/
- A real-time digital clock with seconds
- dark mode
- basic search
- embeddings
- semantic search
- Create a chat interface trained on my blog posts, have database for embeddings that allow daily insert on upload
- refer to https://github.com/Swizec/swizbot-ui
- build a map of favorite restaurants and places like build your corner
- Add listening and reading updates
- add hover over highlights for notes feature and expanding sidebar
- https://linusrogge.com/about
- hover to preview like https://stephango.com/buy-wisely
- breadcrumb navigation
- Setup contentlayer
brew install planetscale/tap/pscale
brew install mysql-client
pscale shell <DB_NAME> main
Run this to create table
CREATE TABLE tweets (
id INT AUTO_INCREMENT PRIMARY KEY,
content TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Create pgvector extension
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE content_chunks (
id UUID PRIMARY KEY,
post_slug TEXT NOT NULL,
post_title TEXT NOT NULL,
content TEXT NOT NULL,
chunk_type TEXT NOT NULL,
metadata JSONB NOT NULL,
sequence INTEGER NOT NULL,
embedding vector(1024),
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
-- Create a vector index for faster similarity search
CREATE INDEX ON content_chunks
USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100);
-- Create additional indexes for faster filtering
CREATE INDEX idx_content_chunks_post_slug ON content_chunks(post_slug);
CREATE INDEX idx_content_chunks_chunk_type ON content_chunks(chunk_type);
Run generate embeddings
npm run generate-embeddings