commits
Adds in memory cache with 5 min TTL to avoid hitting github altogether. with a manual refresh button on the frontend
Backend:
- Add GET /api/user/repos endpoint in router.go:63
- Add GetUserRepos handler in auth.go:327
Frontend:
- Add UserRepo type to api.ts
- Add getUserRepos API function to auth.ts
- Add useUserRepos hook to useAuth.ts
- Update DashboardApp to:
- Fetch user repos from API
- Use repos from user_repos table as fallback
- Load most recent repo automatically on login
This ensures the dashboard loads the user's most recently used repo
from the user_repos table after login, not just from URL params.
Backend:
- Add GetMostRecentUserRepo query to get most recent repo from user_repos
- Update GetCurrentUser to check user_repos if users.last_repo is empty
- Add debug logging to track last_repo flow
Frontend:
- Add debug logging to Dashboard useEffect to track repo detection
This ensures users are redirected to their previously selected repo after login,
even if users.last_repo is empty but user_repos has entries.
Added console logs to track:
- InsertUserRepo attempts and errors
- UpdateLastUsedAt attempts and results
This will help identify why user_repos table isn't being populated.
The handler now:
1. Updates users.last_repo field (existing behavior)
2. Inserts into user_repos table if not already exists
3. Updates last_used_at timestamp for the repo
This ensures selected repos are tracked in both places for persistence.
Create SelectRepoApp component that wraps SetupWizard with QueryClientProvider
and Toaster, fixing 'No QueryClient set' error on the select-repo page.
The query had 6 columns but only 5 values were being passed, causing
'5 values for 6 columns' error. Since updated_at has a DEFAULT value
in the schema, it doesn't need to be in the INSERT column list.
Backend changes:
- Add last_repo field to UserResponse in auth.go:27
- Update GetCurrentUser to include last_repo in response (auth.go:238)
- Update router to use POST /api/user/repo instead of /api/auth/last-repo (router.go:63)
- Implement empty folder filtering in github.go ListFiles function
- Add hasMatchingFiles helper to recursively check for matching files
Frontend changes:
- Simplify SetupWizard: remove 2-step wizard, default to root folder
- Add API call to save last_repo when completing setup
- Create new /select-repo page with SetupWizard component
- Update DashboardApp to check for last_repo from user data or URL params
- Redirect to /select-repo if no repo is configured
- Update 'Change repository' button to link to /select-repo
- Add last_repo field to User type in api.ts
This implements items 1-4 from the plan:
1. Save & Load Last Repo - Backend returns last_repo, frontend saves it via API
2. Remove Folder Selection - Setup wizard now single-step, defaults to root
3. Filter Empty Folders - Backend only returns folders with markdown files
4. Separate Repo Selection URL - New /select-repo page for repo selection
- Add last_repo column to users table schema in migration
- Fix CreateUser query to include last_repo value in INSERT
- Fix GetUserByGithubID and GetUserByID to scan last_repo field
- Fix UpdateUserRepo to use last_repo instead of lastRepo
- Standardize all SQL queries to use snake_case (last_repo) consistently
- Create reusable Loading and EmptyState components with brutalist design
- Replace basic spinners with styled Loading component throughout app
- Add EmptyState for no files/repos scenarios with helpful messaging
- Install and integrate sonner for toast notifications
- Add toast notifications for save errors, publish success/failures
- Update DashboardApp to include Toaster with custom styling
- Improve error handling in EditorContainer and SetupWizard
- Create comprehensive README.md with features, setup, architecture
- Create detailed SETUP.md with deployment guides and troubleshooting
- Update .env.example to match backend environment variables
- Fix docker-compose.yml environment variables and health checks
- Update frontend port from 4321 to 3000 in docker-compose
This completes Phase 4 polish and documentation tasks.
- Create multi-stage Dockerfile for backend (alpine, <50MB)
- Create Dockerfile for frontend with nginx
- Add nginx configuration with gzip, caching, and security headers
- Create docker-compose.yml with health checks and volumes
- Add Makefile with common commands (build, up, down, logs, etc.)
- Add .dockerignore files for both services
- Configure environment variables in docker-compose
- Add health check endpoints for monitoring
- Create branch API client with status and publish endpoints
- Add useBranchStatus and usePublish React Query hooks
- Create PublishDialog component with commit and PR inputs
- Create PublishSuccessDialog showing PR link and commit info
- Integrate publish flow into EditorContainer
- Add Publish button that creates PRs from edited files
- Disable publish button when there are unsaved changes
- Show branch status and edited files in publish dialog
- Display success message with link to created PR
- Install go-git library for git operations
- Create GitOperations module with clone, branch, commit, push functions
- Implement BranchManager with 4-hour branch reuse logic
- Add branch state database queries (save, get, delete)
- Create branch status endpoint (GET /api/repos/:owner/:repo/branch/status)
- Create publish endpoint (POST /api/repos/:owner/:repo/publish)
- Publish endpoint handles commit, push, and PR creation
- Auto-delete drafts after successful publish
- Install TipTap editor with markdown extensions (StarterKit, Typography, Link, CodeBlock)
- Create TipTapEditor component with custom styling matching design system
- Create MenuBar component with formatting controls
- Create FrontmatterEditor component for YAML metadata editing
- Create EditorContainer component managing editor state and auto-save
- Add file content API client and React Query hooks
- Implement debounced auto-save (2 second delay)
- Add unsaved changes warning before page unload
- Integrate editor into DashboardApp
- Convert HTML to markdown using turndown library
- Implement YAML frontmatter parser with Parse and Serialize functions
- Update GetFileContent to parse frontmatter from markdown files
- Add PUT endpoint for saving file drafts to SQLite
- Add database queries for draft content (save, get, delete)
- Modify GetFileContent to return draft content if available
- Support auto-save workflow for markdown editing
- Add UNIQUE(user_id, provider) constraint to auth_tokens table
- This is required for the ON CONFLICT clause in SaveAuthToken
- Fixes SQL logic error when saving OAuth tokens
- Users must be re-authenticated after this migration
- Log access token presence and length after FetchUser
- Log token details before SaveAuthToken
- Make SaveAuthToken failure a critical error that stops the flow
- Capture access token from Authorize call
- Use access token from Authorize if not present in gothUser
- This will help diagnose why tokens aren't being saved
- Add 'affiliation' parameter to GitHub API call to include all repos
- Include owner, collaborator, and organization_member repositories
- Add detailed error logging with status codes
- Log token prefix for debugging
- Log successful repository count
- This ensures users see all repos they have access to, not just owned
Step 1: Repository Selection
- Fetch and display all user repositories in a dropdown
- Add sort options: recently updated, recently created, by name
- Show loading state while fetching repositories
- Show error state if fetch fails
- Display repository count
Step 2: Folder Selection
- Fetch all directories from selected repository
- Display folders in dropdown with emoji icons
- Default option: root directory (all markdown files)
- Show loading state while fetching folders
- Show helpful message if no folders found
Benefits:
- No typing errors - users select from actual repositories
- Better UX - see what actually exists
- Automatic validation - can only select real repos/folders
- Replace repository dropdown with 2-step setup wizard
- Step 1: User enters repository owner and name manually
- Step 2: User configures folder path for blog posts
- Show repository config in sidebar with option to change
- Better UX: users explicitly configure what they want to edit
- Fixes 'Failed to load repositories' issue by not loading all repos
- Replace gothic.BeginAuthHandler/CompleteUserAuth with direct goth provider calls
- This gives us better control over session storage and state management
- Add detailed logging to debug cookie flow
- Fix gothic session store options initialization
- Add compiled binary to .gitignore
- Session cookies now properly persist between login and callback
- Add SameSite=Lax for OAuth cookie compatibility
- Log cookies in BeginAuth and CallbackAuth for debugging
- Add better error message when session expires
- Redirect to home with error on session expiry
- Initialize gothic.Store with CookieStore using SESSION_SECRET
- Configure session options for gothic (MaxAge, HttpOnly, Secure)
- This fixes the 'hash key is not set' error
- Gothic needs its own session store separate from our custom session management
- Add provider=github query parameter in BeginAuth handler
- Add provider=github query parameter in CallbackAuth handler
- This fixes the 'you must select a provider' error from gothic
- Gothic needs the provider name in the request context
- Build Header component with user info and logout button
- Create RepoSelector with sorting options (updated, created, name)
- Implement FileTree with recursive folder expansion
* Shows file/folder icons
* Highlights selected file
* Supports nested directory structure
- Build main Dashboard component with:
* Three-column layout (sidebar + main content)
* Repository selection interface
* File tree navigation
* Empty states for no repo/file selected
* Loading states with skeleton animations
* Placeholder for editor (Phase 2)
- Set up React Query provider for data management
- Use client:only directive for React hydration
- Build test successful
- Install axios and @tanstack/react-query
- Create TypeScript types for API responses (User, Repository, FileNode, etc.)
- Set up axios client with baseURL and credential support
- Add response interceptor for 401 redirect handling
- Implement auth API functions (getCurrentUser, logout)
- Implement repos API functions (listRepositories, listFiles, getFileContent)
- Create React Query hooks for data fetching:
* useCurrentUser - fetch authenticated user
* useLogout - logout mutation
* useRepositories - fetch repos with sorting
* useFiles - fetch file tree with extension filtering
* useFileContent - fetch individual file content
- All hooks use proper query keys and enabled conditions
- Create connector interface for future multi-backend support
- Implement GitHubConnector using go-github library
- Add repository listing with sorting support (updated, created, name)
- Implement recursive file tree traversal with extension filtering
- Add file content retrieval endpoint
- Create RepoHandler with three endpoints:
* GET /api/repos - list user repositories
* GET /api/repos/:owner/:repo/files - list files in repo
* GET /api/repos/:owner/:repo/files/* - get file content
- Wire up handlers in router with authentication middleware
- Build test successful
- Design with editorial/magazine aesthetic using Archivo Black and Crimson Pro fonts
- Implement bold amber-to-red gradient color scheme (avoiding purple clichés)
- Add custom animations (float, slide-in with stagger delays)
- Create geometric visual elements with diagonal cuts and shapes
- Build browser mockup with rotation hover effect
- Add grain texture overlay for refined feel
- Include features section with glassmorphism cards
- Use rounded-none buttons for brutalist edge
- Implement responsive grid layout
- Add GitHub icon with rotation on hover
- Fix Tailwind CSS version compatibility (downgrade to v3)
- Build test successful
- Add @astrojs/react and @astrojs/tailwind integrations
- Configure Tailwind CSS with custom theme variables
- Add shadcn/ui configuration with components.json
- Create utility function for class merging (cn helper)
- Implement button component with variants using CVA
- Add global styles with CSS variables for theming
- Configure Bun as package manager
- Implement GitHub OAuth provider setup with goth
- Add session management with encrypted cookies
- Create authentication middleware for protected routes
- Implement auth handlers (login, callback, user info, logout)
- Set up chi router with CORS support
- Add logging middleware for HTTP requests
- Create health check endpoint
- Integrate all components into main server
- Build test successful
- Create database package with connection pooling and WAL mode
- Add comprehensive database schema (users, auth_tokens, branch_states, draft_content)
- Implement migration runner using embedded SQL files
- Add data models for all database tables
- Create query functions for user and auth token operations
- Integrate database initialization into main server startup
- Build test successful
- Create backend directory structure with organized internal packages
- Add main.go with basic HTTP server and graceful shutdown
- Configure Go modules and add godotenv dependency
- Create Makefile with common development tasks
- Add .env.example with all configuration options
- Add .gitignore for backend artifacts
- Build test successful
Backend:
- Add GET /api/user/repos endpoint in router.go:63
- Add GetUserRepos handler in auth.go:327
Frontend:
- Add UserRepo type to api.ts
- Add getUserRepos API function to auth.ts
- Add useUserRepos hook to useAuth.ts
- Update DashboardApp to:
- Fetch user repos from API
- Use repos from user_repos table as fallback
- Load most recent repo automatically on login
This ensures the dashboard loads the user's most recently used repo
from the user_repos table after login, not just from URL params.
Backend:
- Add GetMostRecentUserRepo query to get most recent repo from user_repos
- Update GetCurrentUser to check user_repos if users.last_repo is empty
- Add debug logging to track last_repo flow
Frontend:
- Add debug logging to Dashboard useEffect to track repo detection
This ensures users are redirected to their previously selected repo after login,
even if users.last_repo is empty but user_repos has entries.
Backend changes:
- Add last_repo field to UserResponse in auth.go:27
- Update GetCurrentUser to include last_repo in response (auth.go:238)
- Update router to use POST /api/user/repo instead of /api/auth/last-repo (router.go:63)
- Implement empty folder filtering in github.go ListFiles function
- Add hasMatchingFiles helper to recursively check for matching files
Frontend changes:
- Simplify SetupWizard: remove 2-step wizard, default to root folder
- Add API call to save last_repo when completing setup
- Create new /select-repo page with SetupWizard component
- Update DashboardApp to check for last_repo from user data or URL params
- Redirect to /select-repo if no repo is configured
- Update 'Change repository' button to link to /select-repo
- Add last_repo field to User type in api.ts
This implements items 1-4 from the plan:
1. Save & Load Last Repo - Backend returns last_repo, frontend saves it via API
2. Remove Folder Selection - Setup wizard now single-step, defaults to root
3. Filter Empty Folders - Backend only returns folders with markdown files
4. Separate Repo Selection URL - New /select-repo page for repo selection
- Add last_repo column to users table schema in migration
- Fix CreateUser query to include last_repo value in INSERT
- Fix GetUserByGithubID and GetUserByID to scan last_repo field
- Fix UpdateUserRepo to use last_repo instead of lastRepo
- Standardize all SQL queries to use snake_case (last_repo) consistently
- Create reusable Loading and EmptyState components with brutalist design
- Replace basic spinners with styled Loading component throughout app
- Add EmptyState for no files/repos scenarios with helpful messaging
- Install and integrate sonner for toast notifications
- Add toast notifications for save errors, publish success/failures
- Update DashboardApp to include Toaster with custom styling
- Improve error handling in EditorContainer and SetupWizard
- Create comprehensive README.md with features, setup, architecture
- Create detailed SETUP.md with deployment guides and troubleshooting
- Update .env.example to match backend environment variables
- Fix docker-compose.yml environment variables and health checks
- Update frontend port from 4321 to 3000 in docker-compose
This completes Phase 4 polish and documentation tasks.
- Create multi-stage Dockerfile for backend (alpine, <50MB)
- Create Dockerfile for frontend with nginx
- Add nginx configuration with gzip, caching, and security headers
- Create docker-compose.yml with health checks and volumes
- Add Makefile with common commands (build, up, down, logs, etc.)
- Add .dockerignore files for both services
- Configure environment variables in docker-compose
- Add health check endpoints for monitoring
- Create branch API client with status and publish endpoints
- Add useBranchStatus and usePublish React Query hooks
- Create PublishDialog component with commit and PR inputs
- Create PublishSuccessDialog showing PR link and commit info
- Integrate publish flow into EditorContainer
- Add Publish button that creates PRs from edited files
- Disable publish button when there are unsaved changes
- Show branch status and edited files in publish dialog
- Display success message with link to created PR
- Install go-git library for git operations
- Create GitOperations module with clone, branch, commit, push functions
- Implement BranchManager with 4-hour branch reuse logic
- Add branch state database queries (save, get, delete)
- Create branch status endpoint (GET /api/repos/:owner/:repo/branch/status)
- Create publish endpoint (POST /api/repos/:owner/:repo/publish)
- Publish endpoint handles commit, push, and PR creation
- Auto-delete drafts after successful publish
- Install TipTap editor with markdown extensions (StarterKit, Typography, Link, CodeBlock)
- Create TipTapEditor component with custom styling matching design system
- Create MenuBar component with formatting controls
- Create FrontmatterEditor component for YAML metadata editing
- Create EditorContainer component managing editor state and auto-save
- Add file content API client and React Query hooks
- Implement debounced auto-save (2 second delay)
- Add unsaved changes warning before page unload
- Integrate editor into DashboardApp
- Convert HTML to markdown using turndown library
- Implement YAML frontmatter parser with Parse and Serialize functions
- Update GetFileContent to parse frontmatter from markdown files
- Add PUT endpoint for saving file drafts to SQLite
- Add database queries for draft content (save, get, delete)
- Modify GetFileContent to return draft content if available
- Support auto-save workflow for markdown editing
- Log access token presence and length after FetchUser
- Log token details before SaveAuthToken
- Make SaveAuthToken failure a critical error that stops the flow
- Capture access token from Authorize call
- Use access token from Authorize if not present in gothUser
- This will help diagnose why tokens aren't being saved
- Add 'affiliation' parameter to GitHub API call to include all repos
- Include owner, collaborator, and organization_member repositories
- Add detailed error logging with status codes
- Log token prefix for debugging
- Log successful repository count
- This ensures users see all repos they have access to, not just owned
Step 1: Repository Selection
- Fetch and display all user repositories in a dropdown
- Add sort options: recently updated, recently created, by name
- Show loading state while fetching repositories
- Show error state if fetch fails
- Display repository count
Step 2: Folder Selection
- Fetch all directories from selected repository
- Display folders in dropdown with emoji icons
- Default option: root directory (all markdown files)
- Show loading state while fetching folders
- Show helpful message if no folders found
Benefits:
- No typing errors - users select from actual repositories
- Better UX - see what actually exists
- Automatic validation - can only select real repos/folders
- Replace repository dropdown with 2-step setup wizard
- Step 1: User enters repository owner and name manually
- Step 2: User configures folder path for blog posts
- Show repository config in sidebar with option to change
- Better UX: users explicitly configure what they want to edit
- Fixes 'Failed to load repositories' issue by not loading all repos
- Replace gothic.BeginAuthHandler/CompleteUserAuth with direct goth provider calls
- This gives us better control over session storage and state management
- Add detailed logging to debug cookie flow
- Fix gothic session store options initialization
- Add compiled binary to .gitignore
- Session cookies now properly persist between login and callback
- Build Header component with user info and logout button
- Create RepoSelector with sorting options (updated, created, name)
- Implement FileTree with recursive folder expansion
* Shows file/folder icons
* Highlights selected file
* Supports nested directory structure
- Build main Dashboard component with:
* Three-column layout (sidebar + main content)
* Repository selection interface
* File tree navigation
* Empty states for no repo/file selected
* Loading states with skeleton animations
* Placeholder for editor (Phase 2)
- Set up React Query provider for data management
- Use client:only directive for React hydration
- Build test successful
- Install axios and @tanstack/react-query
- Create TypeScript types for API responses (User, Repository, FileNode, etc.)
- Set up axios client with baseURL and credential support
- Add response interceptor for 401 redirect handling
- Implement auth API functions (getCurrentUser, logout)
- Implement repos API functions (listRepositories, listFiles, getFileContent)
- Create React Query hooks for data fetching:
* useCurrentUser - fetch authenticated user
* useLogout - logout mutation
* useRepositories - fetch repos with sorting
* useFiles - fetch file tree with extension filtering
* useFileContent - fetch individual file content
- All hooks use proper query keys and enabled conditions
- Create connector interface for future multi-backend support
- Implement GitHubConnector using go-github library
- Add repository listing with sorting support (updated, created, name)
- Implement recursive file tree traversal with extension filtering
- Add file content retrieval endpoint
- Create RepoHandler with three endpoints:
* GET /api/repos - list user repositories
* GET /api/repos/:owner/:repo/files - list files in repo
* GET /api/repos/:owner/:repo/files/* - get file content
- Wire up handlers in router with authentication middleware
- Build test successful
- Design with editorial/magazine aesthetic using Archivo Black and Crimson Pro fonts
- Implement bold amber-to-red gradient color scheme (avoiding purple clichés)
- Add custom animations (float, slide-in with stagger delays)
- Create geometric visual elements with diagonal cuts and shapes
- Build browser mockup with rotation hover effect
- Add grain texture overlay for refined feel
- Include features section with glassmorphism cards
- Use rounded-none buttons for brutalist edge
- Implement responsive grid layout
- Add GitHub icon with rotation on hover
- Fix Tailwind CSS version compatibility (downgrade to v3)
- Build test successful
- Add @astrojs/react and @astrojs/tailwind integrations
- Configure Tailwind CSS with custom theme variables
- Add shadcn/ui configuration with components.json
- Create utility function for class merging (cn helper)
- Implement button component with variants using CVA
- Add global styles with CSS variables for theming
- Configure Bun as package manager
- Implement GitHub OAuth provider setup with goth
- Add session management with encrypted cookies
- Create authentication middleware for protected routes
- Implement auth handlers (login, callback, user info, logout)
- Set up chi router with CORS support
- Add logging middleware for HTTP requests
- Create health check endpoint
- Integrate all components into main server
- Build test successful
- Create database package with connection pooling and WAL mode
- Add comprehensive database schema (users, auth_tokens, branch_states, draft_content)
- Implement migration runner using embedded SQL files
- Add data models for all database tables
- Create query functions for user and auth token operations
- Integrate database initialization into main server startup
- Build test successful
- Create backend directory structure with organized internal packages
- Add main.go with basic HTTP server and graceful shutdown
- Configure Go modules and add godotenv dependency
- Create Makefile with common development tasks
- Add .env.example with all configuration options
- Add .gitignore for backend artifacts
- Build test successful