Technical Documentation: getfider/fider
โน๏ธ Provenance: Multi-Tier Ingestion ยท CodeWiki Reference
Overview (`README.md`)
Fider is a feedback portal for feature requests and suggestions.
Give your customers a voice and let them tell you what they need. Spend less time guessing and more time building the right product.
Getting Started
โ๏ธ **Fider Cloud**
The easiest and quickest way to get started. A fully managed services by the creators of Fider to help you get started in minutes. Forget about managing software updates and patches, we do it all for you! Sign up now
๐ข **Self-Hosted**
Install Fider on your own servers, in your own infrastructure. It's totally free, but of course you're responsible for everything. Learn how
If you do self-host and enjoy Fider, please let us know where you're using it - we really appreciate it ๐
๐ฐ Donations and Sponsors
Support the development of Fider to help us make it the best feedback tool! You can set up donations as small or large as you want to help us keep Fider going. Donate
If your organization uses Fider, consider becoming a sponsor - set up a monthly donation and get your logo and link on the README. Become a sponsor
Contributors
This project exists thanks to all the amazing people who contribute!
Read our CONTRIBUTING guide to learn how you can contribute to Fider.
Overview (`locale/README.md`)
Adding a New Language to Fider ๐ช
This guide explains how to add a new language/locale to Fider.
Overview
All locale definitions are centralized in app/models/enum/locale.go. This is the single source of truth for backend locale metadata including locale codes, display names, pluralization rules, PostgreSQL text search configurations, and language detection mappings.
Step 1: Create Translation Files
Create a new directory in
/localewith the locale code (e.g.,kofor Korean,pt-BRfor Brazilian Portuguese)Create two JSON files in the new directory:
client.json- Frontend translations (UI strings)server.json- Backend translations (emails, server-side messages)
The easiest way to do this is copy the english files, and remove all the translations, replacing them with ones in your language.
Step 2: Add Locale to Backend (Go)
Edit app/models/enum/locale.go:
Add a new locale constant:
goLocaleKorean = Locale{ Code: "ko", // Locale code Name: "Korean", // Display name MessageFormatCode: "ko", // Pluralization library culture code PostgresConfig: "simple", // PostgreSQL text search config LinguaLanguage: lingua.Korean, // Lingua-go language enum IsRTL: false, // Right-to-left text direction }Add the new locale to the
AllLocalesslice:goAllLocales = []Locale{ LocaleEnglish, LocalePortugueseBR, // ... other locales LocaleKorean, // Add your new locale here }
Field Explanations
- Code: The locale code (e.g.,
"en","pt-BR","ko") - Name: Human-readable name shown in language selector
- MessageFormatCode: Culture code for the messageformat library (used for pluralization)
- PostgresConfig: PostgreSQL text search configuration name (see PostgreSQL docs)
- Available configs:
"english","german","french","spanish","portuguese","italian","dutch","russian","swedish","turkish","arabic" - Use
"simple"if PostgreSQL doesn't have native support for your language
- Available configs:
- LinguaLanguage: The lingua-go enum for automatic language detection
- See lingua-go documentation for available languages
- IsRTL: Set to
truefor right-to-left languages (Arabic, Hebrew, Persian, etc.)
Step 3: Add Locale to Frontend
- Update
locale/locales.ts
Add your locale to the locales object:
const locales: { [key: string]: Locale } = {
en: {
text: "English",
},
// ... other locales
ko: {
text: "Korean",
},
}- Update
lingui.config.js
Add your locale code to the locales array:
locales: ["pt-BR", "es-ES", "nl", /* ... other locales, */ "ko"],- Update
public/ssr.tsx
Add your locale to the messages object for server-side rendering:
const messages: { [key: string]: any } = {
en: require(`../locale/en/client`),
// ... other locales
ko: require(`../locale/ko/client`),
}Step 4: Generate and Compile Translations
After adding the locale to all configuration files:
Check that everything works..
bashmake buildRun the server:
bashmake runVerify:
- The new language appears in the language selector
- Translations display correctly
- Right-to-left rendering works (if applicable)
- Search functionality works with the correct PostgreSQL configuration
Open a pull request
When New Translation Strings Are Added
Fider uses LinguiJS for i18n management. When new features are added:
- New translation keys are automatically extracted and added to all locale files (
client.json/server.json) - A GitHub Action uses Google Cloud Translate to automatically translate missing keys
- Machine translations are submitted as a pull request for review
While the automated translations work well for most cases, you may want to refine them for accuracy and cultural context. Feel free to submit pull requests with improved translations at any time.
Overview (`app/services/sqlstore/dbEntities/README.md`)
dbEntities Package
This package contains database entity mapping structs that convert PostgreSQL query results to domain models.
Purpose
The dbEntities package provides a centralized location for database-to-model conversion logic, separating data mapping concerns from the business logic in the postgres package.
Exported Types
User (and UserProvider)
The User type is exported so it can be used across packages:
import "github.com/getfider/fider/app/services/sqlstore/dbEntities"
var user dbEntities.User
err := trx.Get(&user, "SELECT id, name, email... FROM users WHERE id = $1", userID)
if err != nil {
return err
}
// Convert to entity.User
entityUser := user.ToModel(ctx)Unexported Types
All other types (comment, post, tag, tenant, etc.) are unexported (lowercase) and only used internally by the postgres package. They can be exported later if needed by simply capitalizing the type name and its toModel method.
Testing
The package includes unit tests for the exported User type. Run them with:
godotenv -f .test.env go test ./app/services/sqlstore/dbEntities/...OAUTH ROLE RESTRICTION (`docs/OAUTH_ROLE_RESTRICTION.md`)
OAuth Role-Based Access Control
This feature allows you to restrict OAuth login to users who have specific roles provided by your OAuth provider.
Role restrictions are configured per custom OAuth provider in the Admin UI.
This means different providers can have completely independent role requirements.
Configuration
Admin Panel
- Go to Site Settings โ Authentication โ OAuth Providers
- Edit or create a custom OAuth provider
- Configure two fields together:
- JSON User Roles Path โ the path in the provider's profile JSON where roles are found
- Allowed Roles โ a comma-separated list of roles that are permitted to sign in
Both fields must be set for the role check to run. If either is empty, all users are allowed through for that provider.
Allowed Roles field format
- Comma-separated list of role names, e.g.
ROLE_ADMIN,ROLE_TEACHER - Case-sensitive: role names are matched exactly as they appear in the OAuth response
- Leave empty to allow all users (default)
Examples
Allow only admins:
ROLE_ADMINAllow admins and teachers:
ROLE_ADMIN,ROLE_TEACHERAllow all users (default):
Leave the Allowed Roles field empty.
JSON User Roles Path
The roles path tells Fider where to find roles in the OAuth profile response.
Examples
Single role as string:
{
"id": "12345",
"role": "ROLE_ADMIN"
}JSON User Roles Path: role
Comma-separated string:
{
"id": "12345",
"roles": "ROLE_ADMIN,ROLE_TEACHER"
}JSON User Roles Path: roles
Array of strings:
{
"id": "12345",
"name": "John Doe",
"email": "[email protected]",
"roles": ["ROLE_ADMIN", "ROLE_TEACHER"]
}JSON User Roles Path: roles
Array of objects (extract specific field):
{
"id": "12345",
"roles": [
{ "id": "ROLE_ADMIN", "displayName": "Administrator" },
{ "id": "ROLE_TEACHER", "displayName": "Teacher" }
]
}JSON User Roles Path: roles[].id
This extracts the id field from each object in the roles array.
Nested array:
{
"user": {
"profile": {
"roles": ["ROLE_ADMIN"]
}
}
}JSON User Roles Path: user.profile.roles
Nested array of objects:
{
"id": "12345",
"user": {
"groups": [
{ "name": "ROLE_ADMIN" },
{ "name": "ROLE_USER" }
]
}
}JSON User Roles Path: user.groups[].name
--- METRICS ---
- Files Extracted: 4
- Estimated Token Budget: ~2615 tokens
- Canonical Reference: https://codewiki.google/github.com/getfider/fider