### Define Initial Setup Request
Source: https://github.com/athou/commafeed/blob/master/_autodocs/03-rest-endpoints.md
Schema for the initial admin user setup request body.
```typescript
InitialSetupRequest {
name: string // admin username
password: string // admin password
email?: string // admin email
}
```
--------------------------------
### client.user.initialSetup
Source: https://github.com/athou/commafeed/blob/master/_autodocs/01-client-api.md
Performs initial server setup by creating an admin user.
```APIDOC
## initialSetup(req: InitialSetupRequest)
### Description
Perform initial server setup (creates admin user).
### Parameters
- **req.name** (string) - Required - Admin username
- **req.password** (string) - Required - Admin password
- **req.email** (string) - Optional - Admin email
### Example
```typescript
await client.user.initialSetup({
name: "admin",
password: "adminpass",
email: "admin@example.com"
})
```
```
--------------------------------
### GET /server/get
Source: https://github.com/athou/commafeed/blob/master/_autodocs/03-rest-endpoints.md
Retrieves server information and capabilities.
```APIDOC
## GET /server/get
### Description
Get server information and capabilities.
### Method
GET
### Endpoint
/server/get
### Response
#### Success Response (200)
- **announcement** (string) - Optional
- **version** (string) - Required
- **gitCommit** (string) - Required
- **allowRegistrations** (boolean) - Required
- **emailAddressRequired** (boolean) - Required
- **smtpEnabled** (boolean) - Required
- **demoAccountEnabled** (boolean) - Required
- **websocketEnabled** (boolean) - Required
- **websocketPingInterval** (number) - Required
- **treeReloadInterval** (number) - Required
- **forceRefreshCooldownDuration** (number) - Required
- **initialSetupRequired** (boolean) - Required
- **minimumPasswordLength** (number) - Required
- **pushNotificationsEnabled** (boolean) - Required
```
--------------------------------
### Perform initial server setup
Source: https://github.com/athou/commafeed/blob/master/_autodocs/01-client-api.md
Creates the initial admin user for the server instance.
```typescript
await client.user.initialSetup({
name: "admin",
password: "adminpass",
email: "admin@example.com"
})
```
--------------------------------
### POST /user/initialSetup
Source: https://github.com/athou/commafeed/blob/master/_autodocs/03-rest-endpoints.md
Creates the initial admin user account if the system setup is required.
```APIDOC
## POST /user/initialSetup
### Description
Create admin user for initial setup.
### Method
POST
### Endpoint
/rest/user/initialSetup
### Request Body
- **name** (string) - Required - admin username
- **password** (string) - Required - admin password
- **email** (string) - Optional - admin email
### Response
#### Success Response (204)
- No content
#### Error Responses
- 400: Setup already completed
```
--------------------------------
### Initialize CommaFeed Development Environment
Source: https://github.com/athou/commafeed/blob/master/_autodocs/README.md
Commands to start the Quarkus backend and the frontend development server.
```bash
# Backend
cd commafeed-server
./mvnw quarkus:dev
# Frontend
cd commafeed-client
npm install
npm run dev
```
--------------------------------
### Define InitialSetupRequest interface
Source: https://github.com/athou/commafeed/blob/master/_autodocs/02-types.md
Used for the initial server setup process to create the admin user account.
```typescript
interface InitialSetupRequest {
name: string
password: string
email?: string
}
```
--------------------------------
### useAppLoading Usage Example
Source: https://github.com/athou/commafeed/blob/master/_autodocs/06-react-hooks.md
Shows how to use the hook to display a global progress bar during async operations.
```typescript
import { useAppLoading } from "@/hooks/useAppLoading"
export function AppLayout() {
const isLoading = useAppLoading()
return (
{isLoading && }
{/* Main content */}
)
}
```
--------------------------------
### Extended Custom CSS Example for CommaFeed
Source: https://github.com/athou/commafeed/blob/master/documentation/CUSTOMCSS.md
A comprehensive example demonstrating various CSS customizations for CommaFeed, including general styling, header, sidebar, and feed entry modifications. This snippet illustrates direct class styling and complex selector rules.
```css
/* GENERAL (changes applied to everything) */
main {font-size: 14px; font-family: sans-serif; line-height: 1.35; padding-top: calc(1rem * 2.5) !important;}
/* Don't force font-size on blockquotes and make them italic */
blockquote {font-size: unset !important; font-style: italic;}
/* Make all the button icons black */
header svg {stroke: black !important; }
main > svg {stroke: black !important; }
/* Make links in articles light blue with a hover underline */
article a:not([class]) { color:#428bca; text-decoration:none; }
article a:not([class]):hover { text-decoration:underline; }
/* Make HTML headers the (same) reasonable size */
h3 {font-size: 16px !important;}
h2 {font-size: 16px !important;}
h1 {font-size: 16px !important;}
/* Make buttons actual size */
main > button {min-width: unset !important; min-height: unset !important;}
```
```css
/* HEADER (tool bar at the top of the page) */
/* Make the header more compact */
header > div > div {padding-bottom: 0 !important; padding-top: 0 !important;}
/* Let the toolbar pull to the left */
.cf-toolbar-wrapper {justify-content: unset !important;}
/* Minimize height of the toolbar */
header {height: unset !important;}
/* Move buttons closer together */
header img {width: calc(1rem) !important;}
/* No button labels, even if there's room. */
.cf-toolbar-wrapper .mantine-Button-label {display: none;}
```
```css
/* SIDEBAR (where the feeds are listed) */
/* Specific font and layout changes for the entire sidebar */
.cf-tree {font-size: 14px; font-weight: 700; font-family: sans-serif; line-height: 150%; top: 30px !important;}
.cf-treenode {margin-right: 0}
/* Make unread category names black */
.cf-treenode-category {color: black !important;}
/* Remove the favicons for the feeds in the sidebar */
.cf-treenode-icon {display: none;}
/* Make the unread counts lighter, gray and in parens */
.cf-badge {display: flex; font-weight: 300; color: gray; background-color: unset; align-items: unset;}
.cf-badge::before {content: "(";}
.cf-badge::after {content: ")";}
```
```css
/* FEED ENTRIES */
/* Only changes Detailed and Expanded display */
/* Remove subtitle and details in feed entries, just leaving the title */
.cf-header-subtitle {display: none;}
.cf-header-details {display: none;}
/* Remove the divider and button bar at the bottom of feed entries */
.cf-footer-divider {display: none;}
.cf-footer {display: none;}
```
```css
/* MISCELLANEOUS */
/* An example of changing the content: Add an extra space before the submitted line on Reddit feed entries. */
article span > div::after {content: "\A"; white-space: pre;}
```
--------------------------------
### Get Server Information
Source: https://github.com/athou/commafeed/blob/master/_autodocs/01-client-api.md
Retrieves server configuration, versioning, and feature availability.
```typescript
const response = await client.server.getServerInfos()
const serverInfo = response.data
if (serverInfo.allowRegistrations) {
// show registration option
}
```
--------------------------------
### Get Settings Async Thunk
Source: https://github.com/athou/commafeed/blob/master/_autodocs/05-client-state-management.md
Fetches user settings from the server.
```typescript
export const getSettings = createAsyncThunk(
'user/getSettings',
async (_, { rejectWithValue }) => Settings
)
```
```typescript
dispatch(getSettings())
```
--------------------------------
### MariaDB JDBC URL Configuration
Source: https://github.com/athou/commafeed/blob/master/commafeed-server/src/main/docker/README.md
Example JDBC URL for configuring CommaFeed to use a MariaDB database. Verify that the connection details match your MariaDB setup.
```text
QUARKUS_DATASOURCE_JDBC_URL=jdbc:mariadb://localhost/commafeed?autoReconnect=true&failOverReadOnly=false&maxReconnects=20&rewriteBatchedStatements=true&timezone=UTC
```
--------------------------------
### Define production-specific properties
Source: https://github.com/athou/commafeed/blob/master/_autodocs/04-configuration.md
Example configuration for an application-prod.properties file to override default settings.
```properties
commafeed.hide-from-web-crawlers=true
commafeed.http-client.block-local-addresses=true
commafeed.users.allow-registrations=false
quarkus.log.level=WARN
```
--------------------------------
### View configuration validation warnings
Source: https://github.com/athou/commafeed/blob/master/_autodocs/04-configuration.md
Example of a warning log generated when an invalid configuration option is detected at startup.
```text
WARN: Unknown configuration option 'commafeed.invalid-option'
```
--------------------------------
### Configure Database JDBC URLs
Source: https://github.com/athou/commafeed/blob/master/README.md
Examples of JDBC connection strings for various supported database systems.
```properties
jdbc:h2:./data/db;DEFRAG_ALWAYS=TRUE
```
```properties
jdbc:postgresql://localhost:5432/commafeed
```
```properties
jdbc:mysql://localhost/commafeed?autoReconnect=true&failOverReadOnly=false&maxReconnects=20&rewriteBatchedStatements=true&timezone=UTC
```
```properties
jdbc:mariadb://localhost/commafeed?autoReconnect=true&failOverReadOnly=false&maxReconnects=20&rewriteBatchedStatements=true&timezone=UTC
```
--------------------------------
### useColorScheme Usage Example
Source: https://github.com/athou/commafeed/blob/master/_autodocs/06-react-hooks.md
Demonstrates applying theme-specific styles based on the current color scheme.
```typescript
import { useColorScheme } from "@/hooks/useColorScheme"
export function ThemedComponent() {
const colorScheme = useColorScheme()
return (
Current theme: {colorScheme}
)
}
```
--------------------------------
### Registration Form Usage Example
Source: https://github.com/athou/commafeed/blob/master/_autodocs/06-react-hooks.md
Demonstrates integrating useValidationRules with Mantine form.
```typescript
import { useValidationRules } from "@/hooks/useValidationRules"
import { useForm } from "@mantine/form"
export function RegistrationForm() {
const rules = useValidationRules()
const form = useForm({
initialValues: {
username: "",
email: "",
password: "",
},
validate: {
username: rules.username,
email: rules.email,
password: rules.password,
},
})
return (
)
}
```
--------------------------------
### GET /admin/user/getAll
Source: https://github.com/athou/commafeed/blob/master/_autodocs/03-rest-endpoints.md
Retrieves a list of all users registered in the system.
```APIDOC
## GET /admin/user/getAll
### Description
Get list of all users.
### Method
GET
### Endpoint
/rest/admin/user/getAll
### Response
#### Success Response (200)
- **UserModel[]** (array) - Array of users
```
--------------------------------
### Get all users
Source: https://github.com/athou/commafeed/blob/master/_autodocs/03-rest-endpoints.md
Retrieves a list of all users registered in the system.
```typescript
UserModel[] // array of users
```
--------------------------------
### Feed entry filter DSL example
Source: https://github.com/athou/commafeed/blob/master/_autodocs/07-backend-services.md
Demonstrates the query DSL syntax used for defining entry filtering rules.
```text
title contains "tech" AND (author = "John" OR starred = true)
```
--------------------------------
### GET /user/settings
Source: https://github.com/athou/commafeed/blob/master/_autodocs/03-rest-endpoints.md
Retrieves the current user's settings and preferences.
```APIDOC
## GET /user/settings
### Description
Retrieve user settings and preferences.
### Method
GET
### Endpoint
/rest/user/settings
### Response
#### Success Response (200)
- **settings** (object) - User settings object containing language, reading preferences, and notification settings.
```
--------------------------------
### useWebSocket Usage Example
Source: https://github.com/athou/commafeed/blob/master/_autodocs/06-react-hooks.md
Basic implementation of the useWebSocket hook within a React component.
```typescript
import { useWebSocket } from "@/hooks/useWebSocket"
export function App() {
useWebSocket()
return (
{/* App content */}
)
}
```
--------------------------------
### GET /admin/metrics
Source: https://github.com/athou/commafeed/blob/master/_autodocs/03-rest-endpoints.md
Retrieves current server performance metrics.
```APIDOC
## GET /admin/metrics
### Description
Get server performance metrics.
### Method
GET
### Endpoint
/rest/admin/metrics
### Response
#### Success Response (200)
- **counters** (Record) - Metric counters
- **gauges** (Record) - Metric gauges
- **meters** (Record) - Metric meters
- **timers** (Record) - Metric timers
```
--------------------------------
### Dispatch getServerInfos thunk
Source: https://github.com/athou/commafeed/blob/master/_autodocs/05-client-state-management.md
Usage example for triggering the server info fetch.
```typescript
dispatch(getServerInfos())
```
--------------------------------
### Implement useMousetrap Hook Usage
Source: https://github.com/athou/commafeed/blob/master/_autodocs/06-react-hooks.md
Examples of registering various keyboard shortcuts including single keys, modifiers, and sequences.
```typescript
import { useMousetrap } from "@/hooks/useMousetrap"
export function AppNavigationShortcuts() {
const dispatch = useAppDispatch()
// Single key shortcut
useMousetrap('j', () => {
dispatch(selectNextEntry())
})
// Modifier key combination
useMousetrap('shift+u', () => {
dispatch(markAllAsRead())
})
// Keyboard sequence
useMousetrap('g a', () => {
dispatch(navigateToAll())
})
// Save action with Ctrl/Cmd compatibility
useMousetrap('ctrl+s cmd+s', () => {
dispatch(saveSettings())
})
return null // Shortcut-only component
}
```
--------------------------------
### useBrowserExtension Usage Example
Source: https://github.com/athou/commafeed/blob/master/_autodocs/06-react-hooks.md
Demonstrates how to use the hook to conditionally render a subscription alert based on extension state.
```typescript
import { useBrowserExtension } from "@/hooks/useBrowserExtension"
import { client } from "@/app/client"
export function QuickSubscribe() {
const { installed, subscribedFeed } = useBrowserExtension()
const dispatch = useAppDispatch()
if (!installed || !subscribedFeed) {
return null
}
const handleSubscribe = async () => {
await dispatch(subscribe({
url: subscribedFeed.url,
title: subscribedFeed.title,
}))
}
return (
Subscribe to {subscribedFeed.title}?
)
}
```
--------------------------------
### Configure CommaFeed via Environment Variables
Source: https://github.com/athou/commafeed/blob/master/_autodocs/README.md
Set these variables to define database connections, refresh intervals, security keys, and notification settings. These settings are typically applied in the shell environment before starting the application.
```bash
# Database
export QUARKUS_DATASOURCE_JDBC_URL=jdbc:postgresql://localhost/commafeed
export QUARKUS_DATASOURCE_USERNAME=commafeed
export QUARKUS_DATASOURCE_PASSWORD=secretpassword
# Feed refresh
export COMMAFEED_FEED_REFRESH_INTERVAL=20m
export COMMAFEED_FEED_REFRESH_HTTP_THREADS=5
# Security
export QUARKUS_HTTP_AUTH_SESSION_ENCRYPTION_KEY=mysecurekey16
# WebSocket
export COMMAFEED_WEBSOCKET_ENABLED=true
# Push notifications
export COMMAFEED_PUSH_NOTIFICATIONS_NTFY_SERVER_URL=https://ntfy.sh
```
--------------------------------
### Get Profile Async Thunk
Source: https://github.com/athou/commafeed/blob/master/_autodocs/05-client-state-management.md
Fetches the user profile from the server.
```typescript
export const getProfile = createAsyncThunk(
'user/getProfile',
async (_, { rejectWithValue }) => UserModel
)
```
```typescript
dispatch(getProfile())
```
--------------------------------
### Get Entries Async Thunk
Source: https://github.com/athou/commafeed/blob/master/_autodocs/05-client-state-management.md
Fetches entries from a feed or category.
```typescript
export const getEntries = createAsyncThunk(
'entries/getEntries',
async (
req: GetEntriesPaginatedRequest,
{ rejectWithValue }
) => Entries
)
```
```typescript
dispatch(getEntries({
id: "5",
offset: 0,
limit: 20,
readType: "unread",
order: "desc"
}))
```
--------------------------------
### WebSocket Message Example
Source: https://github.com/athou/commafeed/blob/master/_autodocs/08-architecture.md
Format for real-time notifications sent over the WebSocket endpoint.
```text
new-feed-entries:42:5
```
--------------------------------
### GET /user/profile
Source: https://github.com/athou/commafeed/blob/master/_autodocs/03-rest-endpoints.md
Retrieves the profile information for the authenticated user.
```APIDOC
## GET /user/profile
### Description
Get user profile information.
### Method
GET
### Endpoint
/rest/user/profile
### Response
#### Success Response (200)
- **userModel** (object) - User profile details including ID, name, email, and account status.
```
--------------------------------
### Implement common selector patterns
Source: https://github.com/athou/commafeed/blob/master/_autodocs/05-client-state-management.md
Examples of using useAppSelector to retrieve state slices, including performance optimization with shallowEqual.
```typescript
// From component
import { useAppSelector } from "@/app/store"
// Get user profile
const user = useAppSelector(state => state.user.user)
// Get entries
const entries = useAppSelector(state => state.entries.entries)
// Get category tree
const root = useAppSelector(state => state.tree.root)
// Get server info
const serverInfo = useAppSelector(state => state.server.serverInfos)
// Get with shallow equality comparison (performance optimization)
const localSettings = useAppSelector(
state => state.user.localSettings,
shallowEqual
)
```
--------------------------------
### Dispatch setRedirect action
Source: https://github.com/athou/commafeed/blob/master/_autodocs/05-client-state-management.md
Usage example for setting a redirect target.
```typescript
dispatch(setRedirect("/app"))
```
--------------------------------
### useActionButton Usage Example
Source: https://github.com/athou/commafeed/blob/master/_autodocs/06-react-hooks.md
Demonstrates how to use the useActionButton hook to manage a delete feed action with loading and error states.
```typescript
import { useActionButton } from "@/hooks/useActionButton"
import { client } from "@/app/client"
export function DeleteFeedButton({ feedId }) {
const { loading, error, execute, reset } = useActionButton(
() => client.feed.unsubscribe({ id: feedId })
)
return (
{error && (
{error.message}
)}
)
}
```
--------------------------------
### useBrowserExtension()
Source: https://github.com/athou/commafeed/blob/master/_autodocs/06-react-hooks.md
A hook that detects and communicates with the CommaFeed browser extension to retrieve installation status and feed information.
```APIDOC
## useBrowserExtension()
### Description
Detects and communicates with the CommaFeed browser extension.
### Signature
`export const useBrowserExtension = (): BrowserExtensionState`
### Returns
- **installed** (boolean) - Whether extension is installed
- **version** (string, optional) - Extension version if installed
- **subscribedFeed** (object, optional) - Feed URL and title from extension context menu
### Usage Example
```typescript
import { useBrowserExtension } from "@/hooks/useBrowserExtension"
export function QuickSubscribe() {
const { installed, subscribedFeed } = useBrowserExtension();
// ...
}
```
```
--------------------------------
### Run CommaFeed with H2 Database (Docker)
Source: https://github.com/athou/commafeed/blob/master/commafeed-server/src/main/docker/README.md
Starts CommaFeed using a Docker container with an embedded H2 database. The application will be accessible at http://localhost:8082/. Ensure the data volume is correctly mapped.
```bash
docker run --name commafeed --detach --publish 8082:8082 --restart unless-stopped --volume /path/to/commafeed/data:/commafeed/data --memory 256M athou/commafeed:latest-h2
```
--------------------------------
### useNow Usage Example
Source: https://github.com/athou/commafeed/blob/master/_autodocs/06-react-hooks.md
Displays a relative time string that updates based on the current timestamp provided by the hook.
```typescript
import { useNow } from "@/hooks/useNow"
import dayjs from "dayjs"
export function RelativeDateDisplay() {
const now = useNow()
const formatRelativeTime = (timestamp: number) => {
return dayjs(timestamp).from(dayjs(now))
}
return (
Article published {formatRelativeTime(articleTime)}
)
}
```
--------------------------------
### Dispatch clearRedirect action
Source: https://github.com/athou/commafeed/blob/master/_autodocs/05-client-state-management.md
Usage example for clearing the redirect target.
```typescript
dispatch(clearRedirect())
```
--------------------------------
### Style Feed Entry Headers
Source: https://github.com/athou/commafeed/blob/master/documentation/CUSTOMCSS.md
Use the .cf-header class to select and style feed entry headers. This example changes the background color.
```css
.cf-header {
background-color: lightblue;
}
```
--------------------------------
### MySQL JDBC URL Configuration
Source: https://github.com/athou/commafeed/blob/master/commafeed-server/src/main/docker/README.md
Example JDBC URL for configuring CommaFeed to use a MySQL database. Ensure the connection parameters are correctly set for your MySQL instance.
```text
QUARKUS_DATASOURCE_JDBC_URL=jdbc:mysql://localhost/commafeed?autoReconnect=true&failOverReadOnly=false&maxReconnects=20&rewriteBatchedStatements=true&timezone=UTC
```
--------------------------------
### Get server metrics
Source: https://github.com/athou/commafeed/blob/master/_autodocs/03-rest-endpoints.md
Retrieves performance metrics including counters, gauges, meters, and timers.
```typescript
Metrics {
counters: Record
gauges: Record
meters: Record
timers: Record
}
```
--------------------------------
### FeedRefreshEngine Interface
Source: https://github.com/athou/commafeed/blob/master/_autodocs/07-backend-services.md
Coordinates the background feed refresh process with start and stop methods.
```java
public class FeedRefreshEngine {
public void start() // Start refresh background threads
public void stop() // Stop threads gracefully
}
```
--------------------------------
### GET /feed/entries
Source: https://github.com/athou/commafeed/blob/master/_autodocs/03-rest-endpoints.md
Retrieves entries from a specific feed.
```APIDOC
## GET /feed/entries
### Description
Get entries from a feed.
### Method
GET
### Endpoint
/rest/feed/entries
### Response
#### Success Response (200)
- **Entries** (object) - Feed entries
```
--------------------------------
### Implement useMobile Hook Usage
Source: https://github.com/athou/commafeed/blob/master/_autodocs/06-react-hooks.md
Example of using the useMobile hook to conditionally render components based on device type.
```typescript
import { useMobile } from "@/hooks/useMobile"
export function MyComponent() {
const isMobile = useMobile()
return (
{isMobile ? (
) : (
)}
)
}
```
--------------------------------
### Server Information Response Structure
Source: https://github.com/athou/commafeed/blob/master/_autodocs/03-rest-endpoints.md
Defines the schema for the GET /server/get endpoint, providing server capabilities and configuration settings.
```typescript
ServerInfo {
announcement?: string
version: string
gitCommit: string
allowRegistrations: boolean
emailAddressRequired: boolean
smtpEnabled: boolean
demoAccountEnabled: boolean
websocketEnabled: boolean
websocketPingInterval: number
treeReloadInterval: number
forceRefreshCooldownDuration: number
initialSetupRequired: boolean
minimumPasswordLength: number
pushNotificationsEnabled: boolean
}
```
--------------------------------
### Handling login errors
Source: https://github.com/athou/commafeed/blob/master/_autodocs/01-client-api.md
Example usage of errorToStrings within a try-catch block to process and log error messages from the login client method.
```typescript
try {
await client.user.login(credentials)
} catch (error) {
const messages = errorToStrings(error)
messages.forEach(msg => console.error(msg))
}
```
--------------------------------
### Build CommaFeed from source
Source: https://github.com/athou/commafeed/blob/master/README.md
Use the Maven wrapper to compile the project with specific database and native profile configurations.
```bash
./mvnw clean package [-P [-Pnative]] [-DskipTests]
```
--------------------------------
### Typical Service Usage with Dependency Injection
Source: https://github.com/athou/commafeed/blob/master/_autodocs/07-backend-services.md
Demonstrates constructor-based dependency injection in a singleton-scoped REST resource.
```java
@Path("/rest/user")
@Singleton
public class UserREST {
private final UserService userService;
private final UserDAO userDAO;
@Inject
UserREST(UserService userService, UserDAO userDAO) {
this.userService = userService;
this.userDAO = userDAO;
}
public void register(RegistrationRequest req) {
User user = userService.findOrCreate(req.getName());
user.setPassword(req.getPassword());
userDAO.save(user);
}
}
```
--------------------------------
### GET /feed/refreshAll
Source: https://github.com/athou/commafeed/blob/master/_autodocs/03-rest-endpoints.md
Triggers a refresh of all feeds for the current user.
```APIDOC
## GET /feed/refreshAll
### Description
Trigger refresh of all feeds for current user.
### Method
GET
### Endpoint
/rest/feed/refreshAll
### Response
#### Success Response (204)
- No content
```
--------------------------------
### Implement a Custom Service in Java
Source: https://github.com/athou/commafeed/blob/master/_autodocs/08-architecture.md
Extend domain logic by creating a singleton service with injected dependencies.
```java
@Singleton
public class MyService {
// Injected dependencies
private final UserDAO userDAO;
private final FeedEntryService feedEntryService;
// Custom business logic
}
```
--------------------------------
### GET /entry/tags
Source: https://github.com/athou/commafeed/blob/master/_autodocs/03-rest-endpoints.md
Retrieve all tags associated with the user's entries.
```APIDOC
## GET /entry/tags
### Description
Get all tags used in user's entries.
### Method
GET
### Endpoint
/rest/entry/tags
### Response
#### Success Response (200)
- **tags** (string[]) - Array of tag strings
```
--------------------------------
### client.user.register
Source: https://github.com/athou/commafeed/blob/master/_autodocs/01-client-api.md
Creates a new user account.
```APIDOC
## register(req: RegistrationRequest)
### Description
Create a new user account.
### Parameters
- **req.name** (string) - Required - Username
- **req.password** (string) - Required - Password
- **req.email** (string) - Required - Email address
### Example
```typescript
await client.user.register({
name: "newuser",
password: "secure123",
email: "user@example.com"
})
```
```
--------------------------------
### getServerInfos()
Source: https://github.com/athou/commafeed/blob/master/_autodocs/01-client-api.md
Retrieves the server configuration and capabilities.
```APIDOC
## getServerInfos()
### Description
Retrieves the server configuration and capabilities.
### Signature
`getServerInfos(): Promise>`
### Example
```typescript
const response = await client.server.getServerInfos()
const serverInfo = response.data
if (serverInfo.allowRegistrations) {
// show registration option
}
```
```
--------------------------------
### Select Database Backend via Maven Profiles
Source: https://github.com/athou/commafeed/blob/master/_autodocs/README.md
Specify the target database during the build process using Maven profiles. H2 is the default if no profile is specified.
```bash
./mvnw clean package -Ph2 # H2 (default)
./mvnw clean package -Ppostgresql
./mvnw clean package -Pmysql
./mvnw clean package -Pmariadb
```
--------------------------------
### Configure CommaFeed with .env
Source: https://github.com/athou/commafeed/blob/master/_autodocs/04-configuration.md
Use a .env file in the working directory to define database credentials and application settings.
```properties
# .env file in working directory
QUARKUS_DATASOURCE_JDBC_URL=jdbc:postgresql://localhost/commafeed
QUARKUS_DATASOURCE_USERNAME=commafeed
QUARKUS_DATASOURCE_PASSWORD=secretpassword
COMMAFEED_HIDE_FROM_WEB_CRAWLERS=true
COMMAFEED_WEBSOCKET_ENABLED=true
QUARKUS_HTTP_AUTH_SESSION_ENCRYPTION_KEY=mystrongkey16
```
--------------------------------
### Get feed entries
Source: https://github.com/athou/commafeed/blob/master/_autodocs/01-client-api.md
Retrieves a paginated list of entries from a specific feed.
```typescript
const response = await client.feed.getEntries({
id: "42",
offset: 0,
limit: 20,
readType: "unread"
})
```
--------------------------------
### Configure Database Credentials
Source: https://github.com/athou/commafeed/blob/master/_autodocs/04-configuration.md
Sets the username and password for database authentication.
```properties
quarkus.datasource.username=commafeed
```
```properties
quarkus.datasource.password=secretpassword
```
--------------------------------
### GET /feed/get/{id}
Source: https://github.com/athou/commafeed/blob/master/_autodocs/03-rest-endpoints.md
Retrieves the details of a specific feed subscription by its ID.
```APIDOC
## GET /feed/get/{id}
### Description
Get feed subscription details.
### Method
GET
### Endpoint
/rest/feed/get/{id}
### Parameters
#### Path Parameters
- **id** (string) - Required - Feed subscription ID
### Response
#### Success Response (200)
- **Subscription** (object) - Subscription details object
```
--------------------------------
### client.user.getSettings
Source: https://github.com/athou/commafeed/blob/master/_autodocs/01-client-api.md
Retrieves the current user's settings and preferences.
```APIDOC
## getSettings()
### Description
Retrieve user settings and preferences.
### Example
```typescript
const response = await client.user.getSettings()
const settings = response.data
```
```
--------------------------------
### Dispatch setWebSocketConnected action
Source: https://github.com/athou/commafeed/blob/master/_autodocs/05-client-state-management.md
Usage example for updating the WebSocket connection status.
```typescript
dispatch(setWebSocketConnected(true))
```
--------------------------------
### Register a new user account
Source: https://github.com/athou/commafeed/blob/master/_autodocs/01-client-api.md
Creates a new user account with the provided credentials and email.
```typescript
await client.user.register({
name: "newuser",
password: "secure123",
email: "user@example.com"
})
```
--------------------------------
### Get feed subscription details
Source: https://github.com/athou/commafeed/blob/master/_autodocs/01-client-api.md
Retrieves subscription details for a specific feed ID.
```typescript
const response = await client.feed.get("42")
const subscription = response.data
```
--------------------------------
### GET /rest/category/entries
Source: https://github.com/athou/commafeed/blob/master/_autodocs/03-rest-endpoints.md
Retrieves entries from a specific category, supporting pagination, filtering, and sorting.
```APIDOC
## GET /rest/category/entries
### Description
Get entries from a category. Authentication is required (ROLE_USER).
### Method
GET
### Endpoint
/rest/category/entries
### Parameters
#### Query Parameters
- **id** (string) - Required - Category ID, 'all', or 'starred'
- **readType** (ReadingMode) - Optional - 'all' or 'unread' (default: unread)
- **newerThan** (number) - Optional - Only entries newer than this (ms)
- **offset** (number) - Optional - Pagination offset (default: 0)
- **limit** (number) - Optional - Pagination limit (max 1000) (default: 20)
- **order** (ReadingOrder) - Optional - 'asc' or 'desc' (default: desc)
- **keywords** (string) - Optional - Space-separated search terms
- **excludedSubscriptionIds** (string) - Optional - Comma-separated feed IDs to exclude
- **tag** (string) - Optional - Filter by tag
### Response
#### Success Response (200)
- **name** (string) - category name
- **message** (string) - error message
- **errorCount** (number) - fetch error count
- **feedLink** (string) - website URL (if category is single feed)
- **timestamp** (number) - response time (ms)
- **hasMore** (boolean) - more entries available
- **offset** (number) - actual offset used
- **limit** (number) - actual limit used
- **entries** (Entry[]) - array of entries
- **ignoredReadStatus** (boolean) - true if read status was ignored
```
--------------------------------
### Run CommaFeed with a specific profile
Source: https://github.com/athou/commafeed/blob/master/_autodocs/04-configuration.md
Specify a profile at runtime to load corresponding application properties files.
```bash
# Run with 'prod' profile
java -Dquarkus.profile=prod -jar quarkus-run.jar
# This loads both:
# - config/application.properties
# - config/application-prod.properties
```
--------------------------------
### Configure JVM Memory and GC
Source: https://github.com/athou/commafeed/blob/master/_autodocs/README.md
JVM arguments for heap size and garbage collection, along with cache reduction for memory management.
```bash
-Xmx512m
-XX:+UseG1GC
```
```properties
commafeed.http-client.cache.maximum-memory-size=5M
```
--------------------------------
### Define Initial Local Settings
Source: https://github.com/athou/commafeed/blob/master/_autodocs/05-client-state-management.md
Sets the default values for local browser-specific user settings.
```typescript
const initialLocalSettings: LocalSettings = {
viewMode: "detailed",
sidebarWidth: 320,
announcementHash: "",
fontSizePercentage: 100,
}
```
--------------------------------
### Configure Redux Store
Source: https://github.com/athou/commafeed/blob/master/_autodocs/05-client-state-management.md
Initializes the Redux store with slice reducers and preloaded local settings.
```typescript
export const store = configureStore({
reducer: {
entries: entriesSlice.reducer,
redirect: redirectSlice.reducer,
tree: treeSlice.reducer,
server: serverSlice.reducer,
user: userSlice.reducer,
},
preloadedState: {
user: {
localSettings: loadLocalSettings(),
},
},
})
```
--------------------------------
### Get all user tags
Source: https://github.com/athou/commafeed/blob/master/_autodocs/03-rest-endpoints.md
Retrieves an array of all tags currently used in the user's entries.
```typescript
string[] // array of tag strings
```
--------------------------------
### Enable WebSocket Support
Source: https://github.com/athou/commafeed/blob/master/_autodocs/README.md
Configuration property to enable WebSocket functionality.
```properties
commafeed.websocket.enabled=true
```
--------------------------------
### Configure CommaFeed via Environment Variables
Source: https://github.com/athou/commafeed/blob/master/_autodocs/04-configuration.md
Map configuration keys to environment variables by converting dots to underscores, using uppercase, and replacing hyphens with underscores.
```bash
# Web configuration
export COMMAFEED_HIDE_FROM_WEB_CRAWLERS=true
export COMMAFEED_IMAGE_PROXY_ENABLED=false
# Database
export QUARKUS_DATASOURCE_JDBC_URL=jdbc:postgresql://db:5432/commafeed
export QUARKUS_DATASOURCE_USERNAME=commafeed
export QUARKUS_DATASOURCE_PASSWORD=secretpassword
# HTTP client
export COMMAFEED_HTTP_CLIENT_MAX_RESPONSE_SIZE=10M
export COMMAFEED_HTTP_CLIENT_CACHE_ENABLED=true
# Feed refresh
export COMMAFEED_FEED_REFRESH_INTERVAL=20m
export COMMAFEED_FEED_REFRESH_HTTP_THREADS=4
```
--------------------------------
### Get current timestamp in TypeScript
Source: https://github.com/athou/commafeed/blob/master/_autodocs/03-rest-endpoints.md
Use this to generate a Unix epoch timestamp in milliseconds for API requests.
```typescript
const timestamp = Date.now() // milliseconds
```
--------------------------------
### Register Async Thunk
Source: https://github.com/athou/commafeed/blob/master/_autodocs/05-client-state-management.md
Creates a new user account.
```typescript
export const register = createAsyncThunk(
'user/register',
async (req: RegistrationRequest, { rejectWithValue }) => void
)
```
```typescript
dispatch(register({
name: "newuser",
password: "secure123",
email: "user@example.com"
}))
```
--------------------------------
### Define Settings Interface
Source: https://github.com/athou/commafeed/blob/master/_autodocs/02-types.md
Represents the complete user configuration and preferences object.
```typescript
interface Settings {
language?: string
readingMode: ReadingMode
readingOrder: ReadingOrder
showRead: boolean
scrollMarks: boolean
customCss?: string
customJs?: string
scrollSpeed: number
scrollMode: ScrollMode
entriesToKeepOnTopWhenScrolling: number
starIconDisplayMode: IconDisplayMode
externalLinkIconDisplayMode: IconDisplayMode
markAllAsReadConfirmation: boolean
markAllAsReadNavigateToNextUnread: boolean
customContextMenu: boolean
mobileFooter: boolean
unreadCountTitle: boolean
unreadCountFavicon: boolean
disablePullToRefresh: boolean
primaryColor?: string
sharingSettings: SharingSettings
pushNotificationSettings: PushNotificationSettings
}
```
--------------------------------
### UserService Methods
Source: https://github.com/athou/commafeed/blob/master/_autodocs/07-backend-services.md
Methods for managing user accounts, including creation, password updates, and account deletion.
```java
public User findOrCreate(String username)
```
```java
public void changePassword(User user, String newPassword)
```
```java
public void deleteAccount(User user)
```
--------------------------------
### Configure CommaFeed via application.properties
Source: https://github.com/athou/commafeed/blob/master/_autodocs/04-configuration.md
Use this file to define core application settings including database connections, feed refresh intervals, and security parameters.
```properties
# Web configuration
commafeed.hide-from-web-crawlers=true
commafeed.announcement=Welcome to our CommaFeed instance
# HTTP client
commafeed.http-client.max-response-size=10M
commafeed.http-client.block-local-addresses=true
commafeed.http-client.cache.enabled=true
commafeed.http-client.cache.maximum-memory-size=20M
# Feed refresh
commafeed.feed-refresh.interval=15m
commafeed.feed-refresh.max-interval=6h
commafeed.feed-refresh.http-threads=5
commafeed.feed-refresh.interval-empirical=true
# Error handling
commafeed.feed-refresh.errors.initial-backoff=2m
commafeed.feed-refresh.errors.max-backoff=2h
# Push notifications
commafeed.push-notifications.ntfy.server-url=https://ntfy.sh
# Database (PostgreSQL)
quarkus.datasource.jdbc.url=jdbc:postgresql://db.example.com:5432/commafeed
quarkus.datasource.username=commafeed
quarkus.datasource.password=secretpassword
# Users
commafeed.users.allow-registrations=false
commafeed.users.email-required=true
commafeed.users.demo-account-enabled=false
# WebSocket
commafeed.websocket.enabled=true
commafeed.websocket.ping-interval=30s
# Session encryption (prevents logout on restart)
quarkus.http.auth.session.encryption-key=mystrongencryptionkey16
# Server
quarkus.http.port=8082
quarkus.http.host=0.0.0.0
quarkus.log.level=INFO
```
--------------------------------
### Configure Gotify Server URL
Source: https://github.com/athou/commafeed/blob/master/_autodocs/04-configuration.md
Sets the base URL for the Gotify push notification service.
```properties
commafeed.push-notifications.gotify.server-url=https://gotify.example.com
```
--------------------------------
### Implement Local Settings Persistence
Source: https://github.com/athou/commafeed/blob/master/_autodocs/05-client-state-management.md
Loads settings from localStorage on initialization and subscribes to store updates to persist changes.
```typescript
const loadLocalSettings = (): LocalSettings => {
const json = localStorage.getItem("commafeed-local-settings")
return {
...initialLocalSettings,
...(json ? JSON.parse(json) : {}),
}
}
store.subscribe(() => {
const localSettings = store.getState().user.localSettings
localStorage.setItem("commafeed-local-settings", JSON.stringify(localSettings))
})
```
--------------------------------
### Configure Security Settings
Source: https://github.com/athou/commafeed/blob/master/_autodocs/README.md
Application properties for session encryption, user registration, SSRF protection, and web crawler visibility.
```properties
quarkus.http.auth.session.encryption-key=...
commafeed.users.allow-registrations=false
commafeed.http-client.block-local-addresses=true
commafeed.hide-from-web-crawlers=true
```
--------------------------------
### Configure Dynamic JVM Memory Sizing
Source: https://github.com/athou/commafeed/blob/master/README.md
Parameters to optimize memory release to the operating system for the JVM.
```bash
-Xms20m -XX:+UseG1GC -XX:+UseStringDeduplication -XX:-ShrinkHeapInSteps -XX:G1PeriodicGCInterval=10000 -XX:-G1PeriodicGCInvokesConcurrent -XX:MinHeapFreeRatio=5 -XX:MaxHeapFreeRatio=10
```
--------------------------------
### Configure Google Auth Key
Source: https://github.com/athou/commafeed/blob/master/_autodocs/04-configuration.md
Provides the API key required for fetching YouTube channel favicons.
```properties
commafeed.google-auth-key=AIzaSyD...
```
--------------------------------
### client.feed.importOpml(req: File)
Source: https://github.com/athou/commafeed/blob/master/_autodocs/01-client-api.md
Imports feeds into the user's account from an OPML file.
```APIDOC
## client.feed.importOpml(req: File)
### Description
Import feeds from OPML file.
### Parameters
- **req** (File) - Required - OPML file object
### Example
```typescript
const fileInput = document.querySelector('input[type="file"]')
await client.feed.importOpml(fileInput.files[0])
```
```
--------------------------------
### Theme Configuration Access
Source: https://github.com/athou/commafeed/blob/master/_autodocs/06-react-hooks.md
Shows how primary color settings are retrieved from the application state.
```typescript
const settings = useAppSelector(state => state.user.settings)
// settings.primaryColor can be customized
```
--------------------------------
### client.user.login
Source: https://github.com/athou/commafeed/blob/master/_autodocs/01-client-api.md
Authenticates a user with a username and password.
```APIDOC
## login(req: LoginRequest)
### Description
Authenticate user with username and password.
### Parameters
- **req.name** (string) - Required - Username
- **req.password** (string) - Required - Password
### Example
```typescript
await client.user.login({ name: "john", password: "secret123" })
```
```
--------------------------------
### POST /user/register
Source: https://github.com/athou/commafeed/blob/master/_autodocs/03-rest-endpoints.md
Creates a new user account if registrations are enabled.
```APIDOC
## POST /user/register
### Description
Create a new user account.
### Method
POST
### Endpoint
/rest/user/register
### Request Body
- **name** (string) - Required - username
- **password** (string) - Required - password
- **email** (string) - Required - email
### Response
#### Success Response (204)
- No content
#### Error Responses
- 400: Registration disabled or validation failure
- 409: Username already exists
```
--------------------------------
### Configure Quarkus Logging
Source: https://github.com/athou/commafeed/blob/master/_autodocs/04-configuration.md
Set log levels and enable file-based logging for the application.
```properties
# Log level
quarkus.log.level=INFO
quarkus.log.file.level=DEBUG
# File logging
quarkus.log.file.enable=true
quarkus.log.file.path=logs/commafeed.log
```
--------------------------------
### useMousetrap(keyPattern, callback, action)
Source: https://github.com/athou/commafeed/blob/master/_autodocs/06-react-hooks.md
A hook to register keyboard shortcuts using the Mousetrap library, with automatic cleanup on unmount.
```APIDOC
## useMousetrap(keyPattern, callback, action)
### Description
Registers keyboard shortcuts that trigger a callback function. The hook automatically cleans up bindings when the component unmounts.
### Signature
`const useMousetrap = (keyPattern: string, callback: () => void, action?: 'keyup' | 'keydown' | 'keypress'): void`
### Parameters
- **keyPattern** (string) - Required - The keyboard shortcut pattern (e.g., 'ctrl+s', 'j', 'g i').
- **callback** (function) - Required - The function to execute when the shortcut is triggered.
- **action** (string) - Optional - The keyboard event type ('keyup', 'keydown', or 'keypress'). Defaults to 'keydown'.
```
--------------------------------
### useAppLoading()
Source: https://github.com/athou/commafeed/blob/master/_autodocs/06-react-hooks.md
A hook that provides the application-level loading state from the Redux store.
```APIDOC
## useAppLoading()
### Description
Provides application-level loading state from Redux.
### Signature
`export const useAppLoading = (): boolean`
### Returns
- **boolean** - Returns `true` if any critical async operation is in progress.
### Usage Example
```typescript
import { useAppLoading } from "@/hooks/useAppLoading"
export function AppLayout() {
const isLoading = useAppLoading();
// ...
}
```
```
--------------------------------
### Configure User Agent
Source: https://github.com/athou/commafeed/blob/master/_autodocs/04-configuration.md
Sets a custom User-Agent string for outgoing HTTP requests.
```properties
commafeed.http-client.user-agent=CommaFeed/1.0
```
--------------------------------
### Configure Server-Side Performance
Source: https://github.com/athou/commafeed/blob/master/_autodocs/README.md
Settings for adjusting thread counts, timeouts, and cache sizes in the application configuration.
```properties
commafeed.feed-refresh.http-threads=10
commafeed.feed-refresh.database-threads=2
commafeed.http-client.response-timeout=30s
commafeed.http-client.cache.maximum-memory-size=50M
```
--------------------------------
### Configure robots.txt visibility
Source: https://github.com/athou/commafeed/blob/master/_autodocs/04-configuration.md
Set to false to allow web crawlers and search engine indexers to access the site.
```properties
commafeed.hide-from-web-crawlers=false
```
--------------------------------
### POST /feed/import
Source: https://github.com/athou/commafeed/blob/master/_autodocs/03-rest-endpoints.md
Imports feeds from an OPML file.
```APIDOC
## POST /feed/import
### Description
Import feeds from OPML file.
### Method
POST
### Endpoint
/rest/feed/import
### Parameters
#### Form Parameters
- **file** (File) - Required - OPML file
### Response
#### Success Response (204)
- No content
```
--------------------------------
### client.user.getSettings / client.user.saveSettings
Source: https://github.com/athou/commafeed/blob/master/_autodocs/README.md
Retrieves or updates the current user's application settings.
```APIDOC
## client.user.getSettings
### Description
Fetches the current user's configuration settings.
## client.user.saveSettings
### Description
Persists updated user settings to the server.
```
--------------------------------
### Configure JVM Memory Settings
Source: https://github.com/athou/commafeed/blob/master/_autodocs/04-configuration.md
Pass JVM arguments to control memory allocation and garbage collection behavior when running the JAR.
```bash
# Limit JVM memory
java -Xmx256m -Xms128m -jar quarkus-run.jar
# Dynamic memory release
java -Xms20m -XX:+UseG1GC -XX:+UseStringDeduplication \
-XX:-ShrinkHeapInSteps -XX:G1PeriodicGCInterval=10000 \
-XX:-G1PeriodicGCInvokesConcurrent -XX:MinHeapFreeRatio=5 \
-XX:MaxHeapFreeRatio=10 -jar quarkus-run.jar
```
--------------------------------
### client.feed.fetchFeed(req: FeedInfoRequest)
Source: https://github.com/athou/commafeed/blob/master/_autodocs/01-client-api.md
Fetches and previews feed information from a URL before subscribing.
```APIDOC
## client.feed.fetchFeed(req: FeedInfoRequest)
### Description
Fetch and preview a feed URL before subscribing.
### Parameters
- **req.url** (string) - Required - Feed URL to fetch
### Return Type
- **url** (string) - The feed URL
- **title** (string) - Feed title extracted from source
### Example
```typescript
const response = await client.feed.fetchFeed({ url: "https://example.com/feed" })
const feedInfo = response.data
```
```
--------------------------------
### Save Settings Async Thunk
Source: https://github.com/athou/commafeed/blob/master/_autodocs/05-client-state-management.md
Persists user settings to the server.
```typescript
export const saveSettings = createAsyncThunk(
'user/saveSettings',
async (settings: Settings, { rejectWithValue }) => void
)
```
```typescript
const settings = store.getState().user.settings
settings.readingMode = "all"
dispatch(saveSettings(settings))
```
--------------------------------
### POST /user/settings
Source: https://github.com/athou/commafeed/blob/master/_autodocs/03-rest-endpoints.md
Updates the current user's settings and preferences.
```APIDOC
## POST /user/settings
### Description
Save user settings and preferences.
### Method
POST
### Endpoint
/rest/user/settings
### Request Body
- **settings** (object) - Complete settings object
### Response
#### Success Response (204)
- No content
```
--------------------------------
### Connect to WebSocket Endpoint
Source: https://github.com/athou/commafeed/blob/master/_autodocs/03-rest-endpoints.md
Establishes a connection to the WebSocket server and parses incoming notification messages.
```typescript
const ws = new WebSocket('ws://localhost:8082/ws')
ws.onmessage = (event) => {
const [type, feedId, count] = event.data.split(':')
if (type === 'new-feed-entries') {
console.log(`${count} new entries in feed ${feedId}`)
}
}
```
--------------------------------
### Optimize PostgreSQL Database Indexes
Source: https://github.com/athou/commafeed/blob/master/_autodocs/README.md
SQL commands to create indexes for improving query performance on feed subscriptions and entry statuses.
```sql
CREATE INDEX idx_user_id ON feed_subscription(user_id);
CREATE INDEX idx_feed_id ON feed_entry_status(feed_id);
CREATE INDEX idx_entry_date ON feed_entry_status(entry_date DESC);
```
--------------------------------
### client.user.saveSettings
Source: https://github.com/athou/commafeed/blob/master/_autodocs/01-client-api.md
Saves the provided user settings and preferences.
```APIDOC
## saveSettings(settings: Settings)
### Description
Save user settings and preferences.
### Parameters
- **settings** (Settings) - Required - Complete settings object
### Example
```typescript
const settings = await client.user.getSettings()
settings.data.readingMode = "all"
settings.data.customCss = "body { font-size: 16px; }"
await client.user.saveSettings(settings.data)
```
```
--------------------------------
### Enable image proxying
Source: https://github.com/athou/commafeed/blob/master/_autodocs/04-configuration.md
Proxies feed entry images through the server to bypass restrictive network proxies.
```properties
commafeed.image-proxy-enabled=true
```
--------------------------------
### Find or create a feed
Source: https://github.com/athou/commafeed/blob/master/_autodocs/07-backend-services.md
Retrieves an existing feed by URL or creates a new one by fetching and parsing. Throws FeedFetchException if the operation fails.
```java
public Feed findOrCreate(String url) throws FeedFetchException
```
--------------------------------
### Configure Axios Instance for CommaFeed
Source: https://github.com/athou/commafeed/blob/master/_autodocs/01-client-api.md
Sets up the base URL and enables credential support for API requests. This configuration is required for the client to communicate with the REST endpoints.
```typescript
const axiosInstance = axios.create({
baseURL: "./rest",
withCredentials: true
})
```
--------------------------------
### Define getServerInfos async thunk
Source: https://github.com/athou/commafeed/blob/master/_autodocs/05-client-state-management.md
Async thunk signature for fetching server configuration and capabilities.
```typescript
export const getServerInfos = createAsyncThunk(
'server/getServerInfos',
async (_, { rejectWithValue }) => ServerInfo
)
```
--------------------------------
### POST /admin/user/save
Source: https://github.com/athou/commafeed/blob/master/_autodocs/03-rest-endpoints.md
Creates a new user or updates an existing user profile.
```APIDOC
## POST /admin/user/save
### Description
Create or update a user.
### Method
POST
### Endpoint
/rest/admin/user/save
### Request Body
- **id** (number) - Optional - user ID (omit for new)
- **name** (string) - Required - username
- **email** (string) - Optional - email
- **password** (string) - Optional - password (required for new)
- **enabled** (boolean) - Required - enabled flag
- **admin** (boolean) - Required - admin flag
### Response
#### Success Response (200)
- **id** (number) - user ID
```