flixdb
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data β all from the browser, and deployed in milliseconds.
React-based frontend application for managing notes and receipts with PocketBase authentication.
The frontend uses a generic resource management pattern to eliminate code duplication between similar resources:
useResourceManager.tsx- Generic hook for CRUD operations and state managementResourceManager.tsx- Generic UI component for resource management pagesresource-configs.tsx- Resource-specific configurations
NotesManager.tsx- Notes management interface (uses generic components)ReceiptsManager.tsx- Receipts management interface (uses generic components)NoteForm.tsx/ReceiptForm.tsx- Resource-specific formsNoteList.tsx/ReceiptList.tsx- Resource-specific listsNoteItem.tsx/ReceiptItem.tsx- Individual item components
App.tsx- Main application component with authentication state managementHomePage.tsx- Landing page with navigationLoginForm.tsx- User login formuseGeolocation.tsx- Geolocation hook for receipts
- User authentication with email/password
- Generic CRUD operations for multiple resource types
- Real-time UI updates
- Responsive design with TailwindCSS
- Local storage for auth token persistence
- Error handling and loading states
- Geolocation support for receipts
- Star/unstar functionality for receipts
- User enters email/password in LoginForm
- App stores auth token in localStorage
- Token is included in all API requests via Authorization header
- App checks token validity on page load
- User can logout to clear token and return to login
To add a new resource type (e.g., tasks, bookmarks):
- Define the TypeScript types in
shared/types.ts - Create a resource configuration in
resource-configs.tsx - Create resource-specific Form and List components
- Create a Manager component using the generic
ResourceManager
Example:
// In resource-configs.tsx
export const tasksResourceConfig: ResourceManagerConfig<Task, CreateTaskRequest, UpdateTaskRequest> = {
apiPath: "/api/tasks",
resourceName: "task",
resourceNamePlural: "tasks",
mapCreateRequest: (data) => ({ title: data.title }),
mapUpdateRequest: (data) => data,
updateItemInList: (items, id, updatedItem) =>
items.map((item) => item.id === id ? updatedItem : item),
};
// In TasksManager.tsx
export default function TasksManager({ user, onLogout }) {
const resourceManager = useResourceManager(tasksResourceConfig);
return (
<ResourceManager
{...resourceManager}
user={user}
onLogout={onLogout}
title="Tasks Manager"
FormComponent={TaskForm}
ListComponent={TaskList}
// ... other props
/>
);
}
- Eliminated ~200 lines of duplicate code between Notes and Receipts managers
- Type-safe - Full TypeScript support with generics
- Consistent UX - All resources follow the same interaction patterns
- Easy to extend - Adding new resources requires minimal boilerplate
- Maintainable - Bug fixes and improvements apply to all resources