How to Extend FckSignups with Custom Features: A Complete Developer Guide
You extend FckSignups (now NoSignups) by modifying its modular React + TypeScript layers—data schema, state hooks, UI components, and Cloudflare Worker endpoints—following a six-step workflow from type definition to backend persistence.
FckSignups is a Vite-powered React application designed for extensibility. Its architecture separates concerns into discrete layers, making it straightforward to add custom features without destabilizing existing functionality. This guide walks through the exact file paths and code patterns used in the BraveOPotato/FckSignups repository to extend the platform.
Understanding FckSignups Architecture
The codebase organizes functionality into seven distinct layers. Each layer exposes specific entry points for extension:
| Layer | Purpose | Key Entry Point |
|---|---|---|
| Data model | Defines tool metadata structure | src/data/schema.js |
| State hooks | Manages client-side tool state | src/hooks/useTools.ts |
| UI components | Renders catalogue and interactions | src/components/Home/Tools/Tools.tsx |
| Modal system | Handles pop-up flows | src/constants/ModalConfigs.tsx |
| Backend | Persists data via Cloudflare Worker | cloudflare-worker/worker.ts |
| Styling | Scoped CSS modules | Component .module.css files |
| Utilities | Helper functions | src/utils/highlight.tsx, src/utils/formatters.ts |
This separation means you can add a rating system, custom filters, or new submission workflows by touching only the relevant files.
Six-Step Workflow for Adding Custom Features
Step 1: Extend the Data Schema in src/data/schema.js
The schema file defines every field available for tool records. Required fields include id, name, url, and category. Optional metadata covers tags, github, stars, and featured.
To add a new property, append it directly to the schema objects:
// src/data/schema.js
export const schema = [
{
id: "example-tool",
name: "Example Tool",
description: "A demo tool",
url: "https://example.com",
category: "productivity",
// NEW FIELD
rating: 4.5,
tags: ["demo", "example"],
},
];
This change makes the data available immediately, though TypeScript will flag type errors until you complete Step 2.
Step 2: Update Type Definitions in src/types/index.ts
TypeScript enforces compile-time safety across the codebase. Mirror your schema changes in the central types file:
// src/types/index.ts
export interface Tool {
id: string;
name: string;
description: string;
url: string;
category: string;
tags?: string[];
github?: string;
license?: string;
stars?: number;
featured?: boolean;
// NEW PROPERTY
rating?: number;
}
Failing to update types will produce errors in useTools.ts and any components consuming tool data.
Step 3: Expose New State Logic in src/hooks/useTools.ts
The useTools() hook in src/hooks/useTools.ts fetches the tool list, merges submissions, and exposes mutation methods. For custom behaviors like sorting by rating or caching ratings locally, modify this hook directly.
The hook provides:
addTool()— for new submissionsupdateTool()— for editing existing entries- Filter and search state management
Inject your custom logic here before components access the data.
Step 4: Render the Feature in UI Components
Display in cards: Modify src/components/Home/Tools/ToolCard/ToolCard.tsx to show new fields:
// src/components/Home/Tools/ToolCard/ToolCard.tsx
export function ToolCard({ tool }: { tool: Tool }) {
return (
<div className={styles.card}>
<h3>{tool.name}</h3>
<p>{tool.description}</p>
{tool.rating && <span className={styles.rating}>⭐ {tool.rating}</span>}
</div>
);
}
Update container mapping: The Tools.tsx container at src/components/Home/Tools/Tools.tsx maps your tool array to ToolCard instances. No changes needed unless you're adding new container-level behavior.
Add filters: If your feature needs filtering, extend src/components/Home/ToolFilters/ToolFilters.tsx with new UI controls, then wire the filter logic back through useTools.ts.
Style changes: Edit the corresponding .module.css file—ToolCard.module.css for card styling, or create new scoped modules for additional components.
Step 5: Create Backend Handlers in cloudflare-worker/urlHandlers/
The Cloudflare Worker persists data through modular handlers. Existing handlers include:
handleSubmitTool.ts— stores new toolshandleSuggestTool.ts— returns autocompletehandleReportTool.ts— records problems
Create a new handler following this pattern:
// cloudflare-worker/urlHandlers/handleRateTool.ts
import { jsonResponse } from "../utils";
export async function handleRateTool(request: Request) {
const { id, rating } = await request.json();
// Store rating in Cloudflare KV
await TOOLS_KV.put(`tool:${id}:rating`, rating.toString());
return jsonResponse({ success: true });
}
Then register the route in cloudflare-worker/worker.ts:
// cloudflare-worker/worker.ts
import { handleRateTool } from "./urlHandlers/handleRateTool";
router.post("/rate-tool", handleRateTool);
Ensure your KV store schema accommodates the new property before deploying.
Step 6: Configure Modals for User Interaction
The modal system uses declarative configuration in src/constants/ModalConfigs.tsx. To add a "Rate this tool" modal:
- Add an entry to
ModalConfigs.tsxdefining the modal type and props - Create the component under
src/components/Shared/Modals/ - Trigger via the modal provider in
src/hooks/useModal/*
This pattern keeps modal logic consistent with the existing "Submit a tool" flow.
Key Files for Extension Reference
| File Path | Extension Purpose |
|---|---|
src/data/schema.js |
Define new data fields |
src/types/index.ts |
Maintain TypeScript safety |
src/hooks/useTools.ts |
Custom state behaviors |
src/components/Home/Tools/Tools.tsx |
Container rendering |
src/components/Home/ToolFilters/ToolFilters.tsx |
Filter UI controls |
src/constants/ModalConfigs.tsx |
Modal registration |
cloudflare-worker/worker.ts |
API routing |
cloudflare-worker/urlHandlers/ |
Backend endpoint modules |
Summary
- FckSignups extension follows a clear path through schema, types, hooks, components, and backend handlers
src/data/schema.jsandsrc/types/index.tsmust stay synchronized for type safetysrc/hooks/useTools.tscentralizes state mutations and custom behaviors- UI changes target specific component files with scoped CSS modules
- Backend extensions add handler modules to
cloudflare-worker/urlHandlers/and register routes inworker.ts - Modal additions use declarative configuration in
ModalConfigs.tsx
The modular architecture ensures custom features integrate cleanly without cascading changes across the codebase.
Frequently Asked Questions
What technology stack does FckSignups use?
FckSignups runs on React with TypeScript, built via Vite for fast development. The backend uses Cloudflare Workers with KV storage for persistence. This stack provides type safety, rapid builds, and edge-distributed hosting.
Do I need to modify the Cloudflare Worker for every custom feature?
Only for features requiring data persistence or server-side processing. Pure UI changes—like displaying existing fields differently or adding client-side filters—require no backend modifications. Features storing new data or accepting user submissions need handler modules in cloudflare-worker/urlHandlers/.
How does the modal system work in FckSignups?
The modal system combines React Context in src/hooks/useModal/* with declarative configuration in src/constants/ModalConfigs.tsx. You define modal types centrally, then implement components under src/components/Shared/Modals/. This separates modal state management from individual modal content.
Where should I add utility functions for data formatting?
Place reusable helpers in src/utils/. The repository includes highlight.tsx for text highlighting and formatters.ts for data transformations. Import these into components or hooks that need custom display logic for new fields.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →