| Crates.io | sfx |
| lib.rs | sfx |
| version | 0.1.1 |
| created_at | 2025-07-22 12:22:32.199539+00 |
| updated_at | 2026-01-14 05:39:30.051698+00 |
| description | SFX is a streamlined, full-stack Rust framework for building small web services with integrated authentication, localization, and config-driven UI components |
| homepage | https://fds.rs/sfx/ |
| repository | https://github.com/Field-of-Dreams-Studio/sfx |
| max_upload_size | |
| id | 1763472 |
| size | 253,258 |
SFX is a streamlined, full-stack Rust framework for building small web services with integrated authentication, localization, and config-driven UI components
SFX is a simplified framework for building full-stack, small service.
The framework now allows external auth, local auth and we will soon add OAuth into it
The framework is built using hotaru. Read more about hotaru in https://fds.rs/hotaru/.
You may import hotaru directly from use sfx::prelude or use sfx::hotaru
Use sfx --help to learn how to use built-in tools in sfx, while run sfx init in the target dir to initialize a new project
https://fds.rs/sfx/tutorial/0.1.3/
/op/lang/<lang>Change the user's language by setting a cookie and redirecting to the same page This may not work if running in http but not https
GET /op/lang/<lang>
EMPTY
A HttpResponse that redirects to the same page with the new language set in a cookie
Serves the static files
**/static/<path>
GET /static/<path>
EMPTY
A HttpResponse containing the static file or a 404 error if not found
/redirect?url=<url>Redirects to a given URL
GET /redirect?url=<url>
EMPTY
A HttpResponse that redirects to the specified URL
The framework loads critical configuration files at startup from programfiles/op/ and programfiles/admin_info/ directories. These include:
navbar.json and footer.json define site-wide UI elements localized by language keys.
Navbar.json is located at ./programfiles/op/navbar.json
The root is a dictionary. The keys are languages, while the values are the content of navbar for different languages
{
"language-key": {"content"},
"en": {".."},
"zh-tw": {".."}
}
For the content, there must be 2 content, name and itemlist. Name will be shown in the Logo area while the item lists are the items shown on the navbar
{
"en": {
"name": "ICON",
"itemlist": [
["..."],
["..."]
]
}
}
For items in the item list, there are two kinds. The first kind is a single link item
{
"display": "Single",
"url": "/",
"is_dropdown": false // Indicates here
},
Another kind is dropdown, if you click the item the subitems contained in this item will be shown
{
"display": "List",
"url": "/", // Useless, but safer to keep it
"is_dropdown": true, // Indicates it is a dropdown link
"dropdown": [ // Dropdown items
{
"item": "Item 1",
"iurl": "/"
},
{
"item": "Item 2",
"iurl": "/hotaru/news/"
}
]
}
footer.json)Located at ./programfiles/op/footer.json, this file defines localized footer content. The root is a dictionary where keys are language codes and values are footer configurations.
{
"language-key": {
"items": [FooterColumn],
"footer": "HTML string"
}
}
Footer Column (items array):
name: Column title (e.g., "Support", "Resources")itemlist: Array of link objects:
{
"display": "Link Text",
"url": "/path-or-external-url"
}
Footer HTML (footer):
"footer": "© 2025 <a href=\"/about\">Company</a>"
{
"en": {
"items": [
{
"name": "Support",
"itemlist": [
{"display": "Help Center", "url": "/support"},
{"display": "Contact", "url": "/contact"}
]
},
{
"name": "Language",
"itemlist": [
{"display": "English", "url": "/op/lang/en"},
{"display": "日本語", "url": "/op/lang/ja"}
]
}
],
"footer": "© 2025 MyApp | <a href='/privacy'>Privacy Policy</a>"
}
}
l10n.json stores translated strings, support_lang.json lists supported languages (first entry is default).
l10n.json)Located at ./programfiles/op/l10n.json, this file provides localized string translations. The root is a dictionary where keys are phrase identifiers and values are language-specific translations.
{
"phrase_key": {
"language-code": "translated_text",
"en": "English text",
"zh": "中文文本",
"ja": "日本語テキスト"
}
}
// In template rendering:
op::get_localized_string("login", &lang) // Returns "登录" for zh
"nav_home" vs "homepage_link")support_lang.json first\n, \", \\)// Minimal complete example
{
"welcome": {
"en": "Welcome back!",
"zh": "欢迎回来!",
"ja": "おかえりなさい"
},
"error_404": {
"en": "Page not found",
"zh": "页面不存在",
"ja": "ページが見つかりません"
}
}
hosts.json contains trusted origins (checked via is_trusted()), admins.json holds administrator data.
Hosts.json located at ./programfiles/op/hosts.json
It is a Json List. The order in the list will change the order different hosts present in Login, the 0th element will be the default host
A special string "local" indecates we use local host
Minimal example:
["auth.fds.moe", "local"]
binding.txt specifies server binding address (default: localhost:3003).
Directly write your location in programfiles/op/binding.txt
GET /user/login
Renders login page with language-specific content
Response: HTML page with:
hosts.json)POST /user/login
Authenticates user credentials
Parameters (URL-encoded form):
host: Authentication server ("local" for localhost)username: User identifierpassword: Plaintext passwordResponses:
// Success response is generated the backend. Please refer to the Local Auth
// Failure
{
"success": false,
"message": "Invalid credentials"
}
Sets Cookies:
access_token: JWT for authenticated sessionshost: Base authentication serverGET /user/logout
Invalidates current session
Clears: Access token cookie
Redirects: To login page
GET /user/refresh?redirect=<url>
Refreshes access token
Redirects: To specified URL after refresh
GET /user/refresh_api (Testing)
Returns new access token
Response:
{ "access_token": "new.jwt.token" }
GET /user/cached_info
Returns cached user data from session
Response:
{
"uid": "user-id",
"server": "auth.fds.moe",
"username": "john_doe",
"email": "user@example.com",
"is_active": true,
"is_verified": true,
"cached_time": 1712345678
}
GET /user/info (Testing)
Fetches fresh user info from auth server
Response: Raw user object
GET /user/home
User dashboard (requires valid session)
Redirects: To /user/login if unauthenticated
Renders: user/home.html with:
GET /user/unauthorized
Access denied page
Renders: user/unauthorized.html
POST /user/home/change_password
Updates user password
Parameters (URL-encoded form):
old_password: Current passwordnew_password: New passwordhost: Authentication serverResponses:
// Success
{ "success": true }
// Failure
{
"success": false,
"message": "Current password invalid"
}
This module provides core utilities for managing user sessions, authentication tokens, and interactions with the authentication server.
set_auth_token(req: &mut HttpReqCtx, token: &str)"auth_token".get_auth_token(req: &HttpReqCtx) -> Option<String>set_host(req: &mut HttpReqCtx, host: &str)"auth.fds.moe" or "local") in the session.get_host(req: &HttpReqCtx) -> ServerServer::Local if missing.fetch_user_info(host: Server, auth: String) -> Option<User>/users/me endpoint.{
"user": {
"uid": "user-id",
"username": "john_doe",
"email": "user@example.com",
"is_active": true,
"is_verified": true
}
}
refresh_user_token(req: &mut HttpReqCtx) -> Value/auth/refresh. Updates session token on success.{ "success": true, "access_token": "new.jwt.token" }
cache_user_info(req: &mut HttpReqCtx, user: User)logout(req: &mut HttpReqCtx) -> HttpResponsedisable_token(host: Server, token: String) -> Value/auth/logout.request_with_auth_token()Authorization: Bearer <token> header to requests.get_user()auth_server_health()/health endpoint (returns true for { "status": "ok" }).http_only flag to prevent XSS access./auth/refresh maintains session validity without re-login.User::guest().TBD