mirror of
https://github.com/yusing/godoxy.git
synced 2026-04-01 14:43:07 +02:00
chore(docs): update package docs for internal/homepage
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
# Homepage
|
# Homepage
|
||||||
|
|
||||||
The homepage package provides the GoDoxy WebUI dashboard with support for categories, favorites, widgets, and dynamic item configuration.
|
The homepage package provides the GoDoxy WebUI dashboard with support for categories, favorites, widgets, dynamic item configuration, and icon management.
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
@@ -194,18 +194,6 @@ Widgets can display various types of information:
|
|||||||
- **Links**: Quick access links
|
- **Links**: Quick access links
|
||||||
- **Custom**: Provider-specific data
|
- **Custom**: Provider-specific data
|
||||||
|
|
||||||
## Icon Handling
|
|
||||||
|
|
||||||
Icons are handled via `IconURL` type:
|
|
||||||
|
|
||||||
```go
|
|
||||||
type IconURL struct {
|
|
||||||
// Icon URL with various sources
|
|
||||||
}
|
|
||||||
|
|
||||||
// Automatic favicon fetching from item URL
|
|
||||||
```
|
|
||||||
|
|
||||||
## Categories
|
## Categories
|
||||||
|
|
||||||
### Default Categories
|
### Default Categories
|
||||||
|
|||||||
491
internal/homepage/icons/README.md
Normal file
491
internal/homepage/icons/README.md
Normal file
@@ -0,0 +1,491 @@
|
|||||||
|
# Icons Package
|
||||||
|
|
||||||
|
Icon URL parsing, fetching, and listing for the homepage dashboard.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The icons package manages icon resources from multiple sources with support for light/dark variants and multiple image formats. It provides a unified API for parsing icon URLs, checking icon availability, fetching icon data, and searching available icons from CDN repositories.
|
||||||
|
|
||||||
|
### Purpose
|
||||||
|
|
||||||
|
- Parse and validate icon URLs from various sources
|
||||||
|
- Fetch icon data with caching and fallback strategies
|
||||||
|
- Maintain a searchable index of available icons from walkxcode and selfh.st CDNs
|
||||||
|
- Support light/dark theme variants and multiple image formats (SVG, PNG, WebP)
|
||||||
|
|
||||||
|
### Primary Consumers
|
||||||
|
|
||||||
|
- `internal/homepage/` - Homepage route management and icon assignment
|
||||||
|
- `internal/api/` - Icon search and listing API endpoints
|
||||||
|
- `internal/route/` - Route icon resolution for proxy targets
|
||||||
|
|
||||||
|
### Non-goals
|
||||||
|
|
||||||
|
- Icon generation or modification (only fetching)
|
||||||
|
- Authentication for remote icon sources (public CDNs only)
|
||||||
|
- Icon validation beyond format checking
|
||||||
|
|
||||||
|
### Stability
|
||||||
|
|
||||||
|
This package exposes a stable public API. Internal implementations (caching strategies, fetch logic) may change without notice.
|
||||||
|
|
||||||
|
## Concepts and Terminology
|
||||||
|
|
||||||
|
| Term | Definition |
|
||||||
|
| ------------ | ------------------------------------------------------------------------------------- |
|
||||||
|
| **Source** | The origin type of an icon (absolute URL, relative path, walkxcode CDN, selfh.st CDN) |
|
||||||
|
| **Variant** | Theme variant: none, light, or dark |
|
||||||
|
| **Key** | Unique identifier combining source and reference (e.g., `@walkxcode/nginx`) |
|
||||||
|
| **Meta** | Metadata describing available formats and variants for an icon |
|
||||||
|
| **Provider** | Interface for checking icon existence without fetching data |
|
||||||
|
|
||||||
|
## Public API
|
||||||
|
|
||||||
|
### Exported Types
|
||||||
|
|
||||||
|
#### Source
|
||||||
|
|
||||||
|
Source identifies the origin of an icon. Use the constants defined below.
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Source string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// SourceAbsolute is a full URL (http:// or https://)
|
||||||
|
SourceAbsolute Source = "https://"
|
||||||
|
|
||||||
|
// SourceRelative is a path relative to the target service (@target or leading /)
|
||||||
|
SourceRelative Source = "@target"
|
||||||
|
|
||||||
|
// SourceWalkXCode is the walkxcode dashboard-icons CDN
|
||||||
|
SourceWalkXCode Source = "@walkxcode"
|
||||||
|
|
||||||
|
// SourceSelfhSt is the selfh.st icons CDN
|
||||||
|
SourceSelfhSt Source = "@selfhst"
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Variant
|
||||||
|
|
||||||
|
Variant indicates the theme preference for icons that support light/dark modes.
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Variant string
|
||||||
|
|
||||||
|
const (
|
||||||
|
VariantNone Variant = "" // Default, no variant suffix
|
||||||
|
VariantLight Variant = "light" // Light theme variant (-light suffix)
|
||||||
|
VariantDark Variant = "dark" // Dark theme variant (-dark suffix)
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### URL
|
||||||
|
|
||||||
|
URL represents a parsed icon URL with its source and metadata.
|
||||||
|
|
||||||
|
```go
|
||||||
|
type URL struct {
|
||||||
|
// Source identifies the icon origin
|
||||||
|
Source `json:"source"`
|
||||||
|
|
||||||
|
// FullURL contains the resolved URL for absolute/relative sources
|
||||||
|
FullURL *string `json:"value,omitempty"`
|
||||||
|
|
||||||
|
// Extra contains metadata for CDN sources (walkxcode/selfhst)
|
||||||
|
Extra *Extra `json:"extra,omitempty"`
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**URL Methods:**
|
||||||
|
|
||||||
|
- `Parse(v string) error` - Parses an icon URL string (implements `strutils.Parser`)
|
||||||
|
- `URL() string` - Returns the absolute URL for fetching
|
||||||
|
- `HasIcon() bool` - Checks if the icon exists (requires Provider to be set)
|
||||||
|
- `WithVariant(variant Variant) *URL` - Returns a new URL with the specified variant
|
||||||
|
- `String() string` - Returns the original URL representation
|
||||||
|
- `MarshalText() ([]byte, error)` - Serializes to text (implements `encoding.TextMarshaler`)
|
||||||
|
- `UnmarshalText(data []byte) error` - Deserializes from text (implements `encoding.TextUnmarshaler`)
|
||||||
|
|
||||||
|
#### Extra
|
||||||
|
|
||||||
|
Extra contains metadata for icons from CDN sources.
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Extra struct {
|
||||||
|
// Key is the unique icon key
|
||||||
|
Key Key `json:"key"`
|
||||||
|
|
||||||
|
// Ref is the icon reference name (without variant suffix)
|
||||||
|
Ref string `json:"ref"`
|
||||||
|
|
||||||
|
// FileType is the image format: "svg", "png", or "webp"
|
||||||
|
FileType string `json:"file_type"`
|
||||||
|
|
||||||
|
// IsLight indicates if this is a light variant
|
||||||
|
IsLight bool `json:"is_light"`
|
||||||
|
|
||||||
|
// IsDark indicates if this is a dark variant
|
||||||
|
IsDark bool `json:"is_dark"`
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Key
|
||||||
|
|
||||||
|
Key is a unique identifier for an icon from a specific source.
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Key string
|
||||||
|
|
||||||
|
// NewKey creates a key from source and reference
|
||||||
|
func NewKey(source Source, reference string) Key
|
||||||
|
|
||||||
|
// SourceRef extracts the source and reference from a key
|
||||||
|
func (k Key) SourceRef() (Source, string)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Meta
|
||||||
|
|
||||||
|
Meta stores availability metadata for an icon.
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Meta struct {
|
||||||
|
// Available formats
|
||||||
|
SVG bool `json:"SVG"` // SVG format available
|
||||||
|
PNG bool `json:"PNG"` // PNG format available
|
||||||
|
WebP bool `json:"WebP"` // WebP format available
|
||||||
|
|
||||||
|
// Available variants
|
||||||
|
Light bool `json:"Light"` // Light variant available
|
||||||
|
Dark bool `json:"Dark"` // Dark variant available
|
||||||
|
|
||||||
|
// DisplayName is the human-readable name (selfh.st only)
|
||||||
|
DisplayName string `json:"-"`
|
||||||
|
|
||||||
|
// Tag is the category tag (selfh.st only)
|
||||||
|
Tag string `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filenames returns all available filename variants for this icon
|
||||||
|
func (icon *Meta) Filenames(ref string) []string
|
||||||
|
```
|
||||||
|
|
||||||
|
### Exported Functions
|
||||||
|
|
||||||
|
```go
|
||||||
|
// NewURL creates a URL for a CDN source with the given reference and format
|
||||||
|
func NewURL(source Source, refOrName, format string) *URL
|
||||||
|
|
||||||
|
// ErrInvalidIconURL is returned when icon URL parsing fails
|
||||||
|
var ErrInvalidIconURL = gperr.New("invalid icon url")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Provider Interface
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Provider interface {
|
||||||
|
// HasIcon returns true if the icon exists in the provider's catalog
|
||||||
|
HasIcon(u *URL) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetProvider sets the global icon provider for existence checks
|
||||||
|
func SetProvider(p Provider)
|
||||||
|
```
|
||||||
|
|
||||||
|
The provider pattern allows the icons package to check icon existence without fetching data. The `list` subpackage registers a provider that checks against the cached icon list.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### Core Components
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
graph TD
|
||||||
|
subgraph icons/
|
||||||
|
URL["URL"] --> Parser[URL Parser]
|
||||||
|
URL --> VariantHandler[Variant Handler]
|
||||||
|
Key --> Provider
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph fetch/
|
||||||
|
FetchFavIconFromURL --> FetchIconAbsolute
|
||||||
|
FetchFavIconFromURL --> FindIcon
|
||||||
|
FindIcon --> fetchKnownIcon
|
||||||
|
FindIcon --> findIconSlow
|
||||||
|
fetchKnownIcon --> FetchIconAbsolute
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph list/
|
||||||
|
InitCache --> updateIcons
|
||||||
|
updateIcons --> UpdateWalkxCodeIcons
|
||||||
|
updateIcons --> UpdateSelfhstIcons
|
||||||
|
SearchIcons --> fuzzyRank[Fuzzy Rank Match]
|
||||||
|
HasIcon --> ListAvailableIcons
|
||||||
|
end
|
||||||
|
|
||||||
|
style URL fill:#22553F,color:#fff
|
||||||
|
style list fill:#22553F,color:#fff
|
||||||
|
style fetch fill:#22553F,color:#fff
|
||||||
|
```
|
||||||
|
|
||||||
|
### Component Interactions
|
||||||
|
|
||||||
|
1. **URL Parsing** (`url.go`): Parses icon URL strings and validates format
|
||||||
|
2. **Icon Existence** (`provider.go`): Delegates to registered Provider
|
||||||
|
3. **Icon Fetching** (`fetch/fetch.go`): Fetches icon data with caching
|
||||||
|
4. **Icon Listing** (`list/list_icons.go`): Maintains cached index of available icons
|
||||||
|
|
||||||
|
### Data Flow
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
sequenceDiagram
|
||||||
|
participant Client
|
||||||
|
participant URLParser
|
||||||
|
participant Provider
|
||||||
|
participant FetchCache
|
||||||
|
participant ExternalCDN
|
||||||
|
|
||||||
|
Client->>URLParser: Parse("@walkxcode/nginx.svg")
|
||||||
|
URLParser->>Provider: HasIcon(icon)
|
||||||
|
Provider->>FetchCache: Check cached list
|
||||||
|
FetchCache-->>Provider: exists
|
||||||
|
Provider-->>URLParser: true
|
||||||
|
URLParser-->>Client: URL object
|
||||||
|
|
||||||
|
Client->>FetchCache: FetchFavIconFromURL(url)
|
||||||
|
FetchCache->>ExternalCDN: GET https://...
|
||||||
|
ExternalCDN-->>FetchCache: icon data
|
||||||
|
FetchCache-->>Client: Result{Icon: [...], StatusCode: 200}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Subpackages
|
||||||
|
|
||||||
|
### fetch/
|
||||||
|
|
||||||
|
Icon fetching implementation with caching and fallback strategies.
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Result struct {
|
||||||
|
Icon []byte // Raw icon image data
|
||||||
|
StatusCode int // HTTP status code from fetch
|
||||||
|
}
|
||||||
|
|
||||||
|
// FetchFavIconFromURL fetches an icon from a parsed URL
|
||||||
|
func FetchFavIconFromURL(ctx context.Context, iconURL *URL) (Result, error)
|
||||||
|
|
||||||
|
// FindIcon finds an icon for a route with variant support
|
||||||
|
func FindIcon(ctx context.Context, r route, uri string, variant Variant) (Result, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Key behaviors:**
|
||||||
|
|
||||||
|
- `FetchIconAbsolute` is cached with 200 entries and 4-hour TTL
|
||||||
|
- `findIconSlow` has infinite retries with 15-second backoff
|
||||||
|
- HTML parsing fallback extracts `<link rel=icon>` from target pages
|
||||||
|
|
||||||
|
### list/
|
||||||
|
|
||||||
|
Icon catalog management with search and caching.
|
||||||
|
|
||||||
|
```go
|
||||||
|
type IconMap map[Key]*Meta
|
||||||
|
type IconMetaSearch struct {
|
||||||
|
*Meta
|
||||||
|
Source Source `json:"Source"`
|
||||||
|
Ref string `json:"Ref"`
|
||||||
|
rank int
|
||||||
|
}
|
||||||
|
|
||||||
|
// InitCache loads icon metadata from cache or remote sources
|
||||||
|
func InitCache()
|
||||||
|
|
||||||
|
// ListAvailableIcons returns the current icon catalog
|
||||||
|
func ListAvailableIcons() IconMap
|
||||||
|
|
||||||
|
// SearchIcons performs fuzzy search on icon names
|
||||||
|
func SearchIcons(keyword string, limit int) []*IconMetaSearch
|
||||||
|
|
||||||
|
// HasIcon checks if an icon exists in the catalog
|
||||||
|
func HasIcon(icon *URL) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
**Key behaviors:**
|
||||||
|
|
||||||
|
- Updates from walkxcode and selfh.st CDNs every 2 hours
|
||||||
|
- Persists cache to disk for fast startup
|
||||||
|
- Fuzzy search uses Levenshtein distance ranking
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### Cache Location
|
||||||
|
|
||||||
|
Icons cache is stored at the path specified by `common.IconListCachePath`.
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
|
||||||
|
No direct environment variable configuration. Cache is managed internally.
|
||||||
|
|
||||||
|
### Reloading
|
||||||
|
|
||||||
|
Icon cache updates automatically every 2 hours in the background. Manual refresh requires program restart.
|
||||||
|
|
||||||
|
## Observability
|
||||||
|
|
||||||
|
### Logs
|
||||||
|
|
||||||
|
- `failed to load icons` - Cache load failure at startup
|
||||||
|
- `icons loaded` - Successful cache load with entry count
|
||||||
|
- `updating icon data` - Background update started
|
||||||
|
- `icons list updated` - Successful cache refresh with entry count
|
||||||
|
- `failed to save icons` - Cache persistence failure
|
||||||
|
|
||||||
|
### Metrics
|
||||||
|
|
||||||
|
No metrics exposed directly. Status codes in `Result` can be monitored via HTTP handlers.
|
||||||
|
|
||||||
|
### Tracing
|
||||||
|
|
||||||
|
Standard `context.Context` propagation is used throughout. Fetch operations respect context cancellation and deadlines.
|
||||||
|
|
||||||
|
## Security Considerations
|
||||||
|
|
||||||
|
- **Input Validation**: Icon URLs are strictly validated for format and source
|
||||||
|
- **SSRF Protection**: Only absolute URLs passed directly; no arbitrary URL construction
|
||||||
|
- **Content-Type**: Detected from response headers or inferred from SVG magic bytes
|
||||||
|
- **Size Limits**: Cache limited to 200 entries; no explicit size limit on icon data
|
||||||
|
- **Timeouts**: 3-second timeout on favicon fetches, 5-second timeout on list updates
|
||||||
|
|
||||||
|
## Performance Characteristics
|
||||||
|
|
||||||
|
- **Parsing**: O(1) string parsing with early validation
|
||||||
|
- **Caching**: LRU-style cache with TTL for fetched icons
|
||||||
|
- **Background Updates**: Non-blocking updates every 2 hours
|
||||||
|
- **Search**: O(n) fuzzy match with early exit at rank > 3
|
||||||
|
- **Memory**: Icon list typically contains ~2000 entries
|
||||||
|
|
||||||
|
## Failure Modes and Recovery
|
||||||
|
|
||||||
|
| Failure | Behavior | Recovery |
|
||||||
|
| ---------------------- | ---------------------------------------- | -------------------------------- |
|
||||||
|
| CDN fetch timeout | Return cached data or fail | Automatic retry with backoff |
|
||||||
|
| Cache load failure | Attempt legacy format, then remote fetch | Manual cache reset if persistent |
|
||||||
|
| Icon not found in list | Return error from Parse | User must select valid icon |
|
||||||
|
| HTML parse failure | Return "icon element not found" | Manual icon selection |
|
||||||
|
|
||||||
|
## Usage Examples
|
||||||
|
|
||||||
|
### Basic: Parse and Generate URL
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/yusing/godoxy/internal/homepage/icons"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Parse a CDN icon URL
|
||||||
|
url := &icons.URL{}
|
||||||
|
err := url.Parse("@walkxcode/nginx.svg")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the actual fetchable URL
|
||||||
|
fmt.Println(url.URL())
|
||||||
|
// Output: https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/svg/nginx.svg
|
||||||
|
|
||||||
|
// Get string representation
|
||||||
|
fmt.Println(url.String())
|
||||||
|
// Output: @walkxcode/nginx.svg
|
||||||
|
|
||||||
|
// Create with dark variant
|
||||||
|
darkUrl := url.WithVariant(icons.VariantDark)
|
||||||
|
fmt.Println(darkUrl.URL())
|
||||||
|
// Output: https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/svg/nginx-dark.svg
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Advanced: Fetch Icon Data
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/yusing/godoxy/internal/homepage/icons/fetch"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Initialize the icon list cache first
|
||||||
|
iconlist.InitCache()
|
||||||
|
|
||||||
|
// Parse icon URL
|
||||||
|
url := &icons.URL{}
|
||||||
|
if err := url.Parse("@walkxcode/nginx.svg"); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch icon data
|
||||||
|
ctx := context.Background()
|
||||||
|
result, err := fetch.FetchFavIconFromURL(ctx, url)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Fetch failed: %v\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if result.StatusCode != http.StatusOK {
|
||||||
|
fmt.Printf("HTTP %d\n", result.StatusCode)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Fetched %d bytes, Content-Type: %s\n",
|
||||||
|
len(result.Icon), result.ContentType())
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Integration: Search Available Icons
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/yusing/godoxy/internal/homepage/icons/list"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Initialize cache
|
||||||
|
list.InitCache()
|
||||||
|
|
||||||
|
// Search for icons matching a keyword
|
||||||
|
results := list.SearchIcons("nginx", 5)
|
||||||
|
|
||||||
|
for _, icon := range results {
|
||||||
|
source, ref := icon.Key.SourceRef()
|
||||||
|
fmt.Printf("[%s] %s - SVG:%v PNG:%v WebP:%v\n",
|
||||||
|
source, ref, icon.SVG, icon.PNG, icon.WebP)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing Notes
|
||||||
|
|
||||||
|
- Unit tests in `url_test.go` validate parsing and serialization
|
||||||
|
- Test mode (`common.IsTest`) bypasses existence checks
|
||||||
|
- Mock HTTP in list tests via `MockHTTPGet()`
|
||||||
|
- Golden tests not used; test fixtures embedded in test cases
|
||||||
|
|
||||||
|
## Icon URL Formats
|
||||||
|
|
||||||
|
| Format | Example | Output URL |
|
||||||
|
| ------------- | ------------------------------ | --------------------------------------------------------------------- |
|
||||||
|
| Absolute | `https://example.com/icon.png` | `https://example.com/icon.png` |
|
||||||
|
| Relative | `@target/favicon.ico` | `/favicon.ico` |
|
||||||
|
| WalkXCode | `@walkxcode/nginx.svg` | `https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/svg/nginx.svg` |
|
||||||
|
| Selfh.st | `@selfhst/adguard-home.webp` | `https://cdn.jsdelivr.net/gh/selfhst/icons/webp/adguard-home.webp` |
|
||||||
|
| Light variant | `@walkxcode/nginx-light.png` | `.../nginx-light.png` |
|
||||||
|
| Dark variant | `@walkxcode/nginx-dark.svg` | `.../nginx-dark.svg` |
|
||||||
13
internal/homepage/types/README.md
Normal file
13
internal/homepage/types/README.md
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# Types Package
|
||||||
|
|
||||||
|
Configuration types for the homepage package.
|
||||||
|
|
||||||
|
## Config
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Config struct {
|
||||||
|
UseDefaultCategories bool `json:"use_default_categories"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var ActiveConfig atomic.Pointer[Config]
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user