Skip to content

Pocketbase#4

Closed
axelav wants to merge 46 commits intomainfrom
pocketbase
Closed

Pocketbase#4
axelav wants to merge 46 commits intomainfrom
pocketbase

Conversation

@axelav
Copy link
Copy Markdown
Owner

@axelav axelav commented Dec 26, 2025

No description provided.

This design document outlines the refactor from Next.js to TrailBase + Vite:
- Replace Next.js with Vite for simpler build tooling
- Add TrailBase backend with SQLite for persistent storage
- Implement multi-user support with authentication
- Convert codebase to TypeScript
- Maintain existing UI/UX
- Deploy with Docker on VPS
This comprehensive plan breaks down the refactor into 15 bite-sized tasks:
- Backend setup with TrailBase and SQLite
- Frontend foundation with Vite and TypeScript
- Component migration from JavaScript to TypeScript
- API integration with React Query
- Authentication implementation
- Docker deployment configuration

Each task includes exact file paths, complete code examples, and
verification steps following TDD principles.
- Add back getCurrentDateLocalized and FWD_SLASH to utils
- Restore Footer with version, data link, and attribution
- Restore Header with keyboard shortcuts, animations, date display
- Preserve all original UX features (search toggle, mode switch, hover)
- Match original component behavior while using TypeScript
…ration

Migrates CreateEntryForm from JavaScript to TypeScript with proper type safety.
Key changes:
- Uses CreateEntryInput type (omits server-generated fields like id, user_id)
- Removes client-side UUID generation (backend handles ID creation)
- Preserves all validation logic (URL validation, duplicate checking, required fields)
- Maintains keyboard shortcut (ENTER to submit)
- Adapts field names to match backend schema (dismissed_at vs dismissedAt)
- Supports both create and edit modes via optional props

Part of Task 10 in the Interne refactor implementation plan.
Creates two new authentication components:
- LoginForm: Handles user login and registration with form toggle
- AuthProvider: Wraps app with auth guard and React Query provider

Key features:
- Email/password authentication
- Toggle between login and register modes
- Error handling and display
- Loading state during auth check
- Automatic redirect to login form when unauthenticated
- React Query setup with sensible defaults (retry: 1, no refetch on focus)

Also adds auth-specific styles to Forms.module.css:
- authContainer: Centered auth form container
- toggleAuth: Link-style button to toggle between login/register

Part of Task 11 in the Interne refactor implementation plan.
Creates the complete application with:
- Authentication wrapper via AuthProvider
- Entries listing with spaced repetition logic
- Entry create/edit/delete functionality
- Filter toggle (available vs all entries)
- Search functionality across title, description, and URL
- Keyboard shortcuts (ESC to toggle filter or exit edit mode)
- Loading states for data fetching
- Conditional rendering for view/edit modes

Key features:
- Uses React Query hooks for all CRUD operations
- Computes entry visibility based on entropy calculation
- Filters and sorts entries based on dismissed_at and availableAt
- Displays relative time for last viewed and availability
- Preserves all original UI/UX from the Next.js version

Also copies favicon.ico to public folder for branding.

Part of Task 12 in the Interne refactor implementation plan.
Add explicit type annotation to mode useState to allow both 'view' and 'edit' modes.
Without this, TypeScript infers the type as only 'view' literal, preventing mode changes.

Fixes TypeScript compilation errors:
- TS2367: Comparison between 'view' and 'edit' types
- TS2345: Cannot assign 'edit' to SetStateAction<'view'>
- TS2322: Type mismatch in setMode dispatch

Identified by code review of Task 12.
Creates complete Docker setup for production deployment:
- Dockerfile: Multi-stage build with frontend compilation and TrailBase runtime
- docker-compose.yml: Service configuration with port mapping and volume mounts
- .dockerignore: Excludes unnecessary files from Docker context
- .gitignore: Adds data/ directory to prevent database files from being committed

Docker setup:
- Stage 1: Node 20 Alpine builds frontend with pnpm
- Stage 2: Debian Bookworm runs TrailBase with static frontend files
- Exposes port 4000 for web access
- Mounts ./data volume for database persistence
- Serves frontend build from /app/static

To deploy:
1. Download TrailBase executable to backend/trailbase
2. Run: docker-compose up -d

Part of Task 13 in the Interne refactor implementation plan.
Replaces outdated Next.js development instructions with complete documentation for the refactored application:

Added sections:
- Features overview (spaced repetition, multi-user, search, keyboard shortcuts)
- Tech stack details (TrailBase backend, Vite/React/TypeScript frontend)
- Development setup instructions (prerequisites, backend/frontend setup)
- Project structure diagram
- Deployment instructions (Docker and VPS)
- Backup procedures for SQLite database

Removed references to:
- Next.js development server
- Old port numbers
- npm (replaced with pnpm)

Documentation now accurately reflects the TrailBase + Vite architecture implemented in the refactor.

Part of Task 14 in the Interne refactor implementation plan.
Corrects fundamental misunderstanding of TrailBase architecture:

BEFORE (incorrect):
- Tried to COPY a trailbase executable that doesn't exist
- Used custom config.json (TrailBase manages its own config)
- Used non-existent --static-files flag
- Based on debian image instead of official TrailBase image

AFTER (correct):
- Uses official trailbase/trailbase Docker image from Docker Hub
- Uses --public-dir flag to serve frontend static files
- Uses --data-dir to specify traildepot location
- Mounts ./traildepot volume for database persistence
- Removes custom config.json (TrailBase auto-generates config)

Key changes:
- Dockerfile: FROM trailbase/trailbase:latest (not debian)
- Dockerfile: Correct flags --public-dir and --data-dir
- docker-compose.yml: Mount traildepot/ instead of data/
- .gitignore: Ignore traildepot/ instead of data/
- backend/.gitignore: Simplified to just ignore traildepot/
- README.md: Updated with correct setup instructions

For local development:
- Run: trail run --dev (enables CORS for Vite dev server)
- TrailBase admin UI: http://localhost:4000/_/admin/

For Docker deployment:
- Frontend served from same origin (no CORS needed)
- All data persists in ./traildepot directory
Corrects all auth implementation to match actual TrailBase v1 API endpoints and schemas discovered from OpenAPI spec:

**Type Changes (src/types/user.ts):**
- AuthResponse: Changed access_token → auth_token, added csrf_token
- User: Added verified, admin, created fields (removed created_at)
- RegisterCredentials: Added required password_repeat field

**Service Changes (src/services/auth.ts):**
- Updated all endpoints to /api/auth/v1/* paths
- login: POST /api/auth/v1/login (was /auth/login)
- register: POST /api/auth/v1/register (was /auth/register)
- logout: POST /api/auth/v1/logout with server-side session clearing
- getCurrentUser: GET /api/auth/v1/status (was /auth/me)
- Store auth_token instead of access_token

**Hook Changes (src/hooks/useAuth.ts):**
- Use invalidateQueries instead of setQueryData after login/register
- This triggers refetch with new auth token to get current user

**UI Changes (src/components/LoginForm.tsx):**
- Added password_repeat field for registration
- Added password match validation
- Clear password_repeat on mode toggle

**Bug Fixes:**
- Removed stray 'sL;' typo in useEntries.ts

All changes verified against TrailBase OpenAPI spec. Auth flow now:
1. Login/Register → receives auth_token + refresh_token + csrf_token
2. Store auth_token in localStorage
3. Invalidate user query → triggers GET /api/auth/v1/status
4. User data populated, auth complete
TrailBase auth endpoints require application/x-www-form-urlencoded, not JSON.

Changes:
- login(): Convert credentials to URLSearchParams
- register(): Convert credentials to URLSearchParams with password_repeat
- Set Content-Type: application/x-www-form-urlencoded header
- Use formData.toString() for request body

Fixes 'Unsupported Media Type' error in registration/login.
- Replace useQuery with useState + useEffect for synchronous authStore access
- Use onAuthChange subscription for reactive auth state updates
- Invalidate entries (not user) on login/register since auth state is now managed separately
- Maintain same return shape for backwards compatibility
- dismissed_at → dismissed
- availableAt → nextAvailable
- password_repeat → passwordConfirm
Removed:
- Next.js components, pages, services, utils, styles (now in frontend/)
- TrailBase Dockerfile and .dockerignore
- Root package.json and lock files (frontend has its own)
- Old Next.js config files (next.config.js, now.json)
- Root public directory (favicon now in frontend/public/)
- Remove package-lock.json
- Regenerate pnpm-lock.yaml with PocketBase SDK
- Update README to use pnpm commands
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant