MoreRSS

site iconThe Practical DeveloperModify

A constructive and inclusive social network for software developers.
Please copy the RSS to your reader, or quickly subscribe to:

Inoreader Feedly Follow Feedbin Local Reader

Rss preview of Blog of The Practical Developer

PromptShield AI – An AI Cost & Risk Firewall Built with Xano

2025-12-15 00:51:17

This is a submission for the Xano AI-Powered Backend Challenge: Full-Stack, AI-First Application

PromptShield AI – An AI Cost & Risk Firewall for LLM Applications

As teams rapidly build agentic apps and AI-powered features, one problem shows up almost immediately:

LLM costs explode, usage becomes opaque, and there are no guardrails.

Developers lack:

  • Per-user and per-feature budgets
  • Visibility into token and cost usage
  • Protection against risky prompts (PII, secrets)
  • Smart routing to cheaper models when budgets are exceeded

PromptShield AI solves this by acting as an intelligent backend control plane that sits between applications and LLM providers.

It enforces:

  • Cost budgets (tenant / user / feature)
  • Usage analytics and spend visibility
  • Safety and routing policies
  • Multi-provider cost control

The result is a production-ready AI infrastructure backend, not just a wrapper around LLM APIs.

🧱 Architecture Overview

  • Backend: Xano (Postgres, APIs, background jobs, AI workflows)
  • Frontend: Lovable.dev (low-code SaaS dashboard)
  • AI-first approach: Backend generated with AI, refined by hand
  • Public API + Admin UI: Production-ready by design

🎬 Demo

🔗 Live Application:

https://promptshield.lovable.app/

💻 Source Code (GitHub):

https://github.com/Manikant92/promptshield_ai

🎥 Demo Walkthrough Video:

📸 Product Screenshots
Xano Dev
Xano Dev
Xano Dev
Xano Dev
Xano Dev

Dashboard Overview
API Key Management
Tenant Management
Budget Management
Provider Management
Usage and Analytics
Policy Management

🔎 Swagger / Public API:

https://x8ki-letl-twmt.n7.xano.io/api:q5xLch4v

The dashboard shows real API keys, budgets, policies, providers, and usage analytics powered entirely by Xano.

🧠 The AI Prompt I Used (Backend Generation)

All backend workflows, API definitions, and schema refinements are tracked in the GitHub repository below for transparency and reproducibility:

👉 https://github.com/Manikant92/promptshield_ai

I used XanoScript with an AI-first workflow to generate the initial backend.

Below is the original prompt used to bootstrap the system:

You are an expert backend architect building a production-ready, multi-tenant AI infrastructure backend using Xano.

Build a backend called "PromptShield AI" — an AI Cost & Risk Firewall that sits between applications and multiple LLM providers (OpenAI, Anthropic, etc.) to enforce budgets, rate limits, and safety policies before requests reach the LLM.

The backend must be secure, scalable, and suitable for public API consumption.


Create the initial backend for PromptShield AI with the following requirements:

1. Core Concept
PromptShield AI acts as a proxy API for LLM calls. Applications send standard chat/completion payloads to PromptShield, which enforces usage policies, budgets, and risk checks before forwarding requests to LLM providers.

2. Database Schema (Postgres)
Design tables for:
- tenants (org_id, name, plan, created_at)
- api_keys (key, tenant_id, status, last_used_at)
- users (user_id, tenant_id, role)
- llm_providers (provider, model, cost_per_1k_tokens)
- usage_logs (tenant_id, user_id, feature, provider, model, tokens_in, tokens_out, cost, timestamp)
- budgets (tenant_id, scope_type [tenant/user/feature], scope_id, daily_limit, monthly_limit)
- policies (tenant_id, preferred_models, fallback_model, blocked_categories)

3. API Endpoints
Create the following APIs:

POST /llm/proxy
- Accepts OpenAI-compatible chat/completion payload
- Authenticates using API key
- Identifies tenant, user, and feature
- Performs budget checks and policy enforcement
- Routes request to the selected LLM provider
- Logs token usage and cost

POST /limits/configure
- Allows tenants to define per-user, per-feature, or per-tenant budgets
- Supports daily and monthly limits

GET /usage/summary
- Returns aggregated usage by tenant, user, feature, and model
- Optimized for dashboards

4. AI Logic
Use AI workflows to:
- Classify prompts for risky categories (PII, secrets, unsafe content)
- Block or redact requests that violate policy
- Automatically downgrade to cheaper models when nearing budget limits
- Detect anomalous usage spikes (e.g., sudden 10x increase)

5. Background Jobs
- Aggregate daily and monthly usage
- Recalculate remaining budgets
- Run anomaly detection periodically

6. Security & Scalability
- Multi-tenant isolation
- Rate limiting per API key
- Clean error responses
- Extensible provider abstraction

7. Output
Generate:
- Database tables
- API endpoint logic
- AI workflows
- Background jobs
Use clean, maintainable naming and comments suitable for a production backend.

Do NOT generate frontend code.
Focus entirely on the backend implementation in Xano.

This prompt allowed AI to quickly generate a solid baseline backend, which I then refined heavily inside Xano.

## 🛠️ How I Refined the AI-Generated Backend in Xano

AI gave me a starting point — **human refinement made it production-ready**.

### Key Improvements I Made in Xano

#### 🔐 Security & Multi-Tenancy
- Introduced tenant isolation across all tables
- Added API key lifecycle management (create, revoke, rotate)
- Hardened error handling and rate limits

#### 💰 Cost & Budget Enforcement
- Added scoped budgets (tenant / user / feature)
- Implemented background aggregation jobs for daily & monthly usage
- Enabled budget thresholds and warning states

#### 🧠 AI Logic Enhancements
- Added prompt classification for risky categories (PII, secrets)
- Implemented policy-based model fallback when budgets are exceeded
- Designed provider abstraction for future expansion

#### 📊 Observability & Analytics
- Normalized usage logs for dashboards
- Enabled cost-by-model and cost-by-feature views
- Optimized APIs for frontend consumption

Before: AI-generated CRUD-style endpoints

After: A scalable, secure AI infrastructure backend suitable for real-world use

🎨 Frontend: Turning APIs into a Product

I connected the Xano backend to Lovable.dev to build a clean, enterprise-style dashboard.

The UI allows users to:

  • Manage API keys securely
  • Define and monitor budgets
  • Configure routing and safety policies
  • Analyze token and cost usage with filters and charts

This step demonstrated how Xano’s backend capabilities translate directly into product value.

🚀 My Experience with Xano

What I Loved

  • AI + Human workflow: AI for speed, Xano for control
  • Background jobs: Perfect for cost aggregation and analytics
  • Clean API design: Easy to connect to any frontend
  • Production mindset: Xano encourages scalable patterns by default

Challenges

  • Thinking through multi-tenant isolation correctly (worth the effort)
  • Designing APIs that balance flexibility and simplicity

Overall, Xano made it incredibly easy to go from idea → AI-generated backend → production-grade system in a very short time.

🏁 Final Thoughts

PromptShield AI is not just a demo — it’s a realistic example of how AI-assisted backend development, combined with thoughtful human refinement, can produce scalable, secure, and maintainable systems.

Xano was the perfect platform to bring this idea to life.

Thanks for checking it out! 🚀

Blazor SaaS Starter Kits Compared: When to Choose Brick Starter for Full‑Stack C#

2025-12-15 00:49:00

Blazor SaaS starter kits give .NET teams a faster path to multi‑tenant, subscription‑based applications, but they differ a lot in focus, features, and how much they handle beyond UI. Brick Starter sits in the category of full‑stack C# SaaS foundations, combining a Blazor UI option with a feature‑rich ASP.NET Core backend built specifically for SaaS and multi‑tenancy.

Why Blazor SaaS starter kits exist

Blazor lets developers build rich web UIs in C# instead of JavaScript, which is attractive to .NET teams who want full‑stack C# across client and server. However, building a serious SaaS app still demands multi‑tenant architecture, authentication, billing, localization, admin tools, and deployment plumbing—far beyond what “File → New Blazor App” provides.​

Blazor‑focused SaaS starter kits exist to package those repetitive capabilities into reusable templates, so teams can start from a running Blazor + ASP.NET Core SaaS skeleton instead of reinventing every infrastructure piece.

Types of Blazor SaaS starter kits

Most Blazor SaaS kits fall into three broad types.​

  • Blazor UI‑first templates: focus on page layouts, components, and auth for single‑tenant apps; ideal for internal tools and basic CRUD but light on multi‑tenancy and billing.
  • Blazor‑centric multi‑tenant kits: add tenant awareness, localization, and better authorization on top of Blazor, often with opinionated architectures like Clean Architecture.​
  • Full SaaS boilerplates: combine Blazor (optionally among other UIs) with a mature .NET backend that includes tenant management, recurring payments, MFA, email templates, background jobs, and more.​

Brick Starter fits into the third category, where the goal is to ship production SaaS, not just a nice Blazor front end.​

Notable Blazor SaaS starter kits

Several Blazor‑based SaaS kits are frequently mentioned in .NET and SaaS communities.​

  • BlazorPlate: a multi‑tenant and multilingual Blazor template that targets SaaS scenarios with support for Blazor Server and WebAssembly, MudBlazor UI, authentication/authorization, and shared database multi‑tenancy.​​
  • Clean Architecture‑style Blazor kits (including samples and open templates): focus on DDD, modularity, and clean layering with Blazor front ends, but often require you to add billing, tenant lifecycle, and operational features yourself.​
  • Custom Blazor SaaS templates on GitHub and marketplaces: many offer auth, basic roles, and Stripe integration, but coverage of admin, email, localization, and multi‑tenant configuration varies significantly.​

These can be excellent for teams comfortable extending infrastructure, but they still expect you to fill gaps, especially around multi‑tenant billing and operations.​

Brick Starter: full‑stack C# boilerplate with a Blazor option

Brick Starter is a .NET SaaS boilerplate that supports multiple front‑end stacks—including Blazor—on top of a single, feature‑rich ASP.NET Core backend. The same backend powers Blazor, Angular, React, Vue, Next.js, and Razor, so C# teams can stay in .NET on both client and server while choosing the best UI for each project.​

Out of the box, Brick provides SaaS‑critical building blocks:​

  • Multi‑tenancy: tenant creation, isolation, subdomain‑based tenant routing, and a full tenant management panel.
  • Authentication and authorization: email, social, and Entra ID sign‑in; role and permission framework; multi‑factor authentication via email OTP and authenticator apps.
  • Billing and subscriptions: integrated Stripe‑based recurring payments with tenant‑level plans and automated handling of renewals, cancellations, and failures.
  • Operational features: email template management, multi‑language UI, database data encryption, background jobs, and admin dashboards for users, tenants, and settings.

All of this ships with full source code so teams can extend patterns, integrate with their own services, and audit everything.​

Blazor‑specific benefits in Brick Starter

When you choose the Blazor option in Brick Starter, you get a Blazor front end that is designed to sit on top of that SaaS‑ready backend rather than being a one‑off UI. That means your Blazor components immediately benefit from tenant context, permission checks, billing state, and localization that are already implemented server‑side.​

Advantages for full‑stack C# teams include:​

  • Single language end‑to‑end: C# for Blazor components, business logic, and backend services, reducing context switching and making it easier to share models and validation.
  • Consistent patterns across clients: if you later add a React or Angular client, they call the same APIs and reuse the same multi‑tenant logic, making Brick a long‑term foundation rather than a Blazor‑only experiment.
  • Faster onboarding: Blazor and .NET developers can work within familiar patterns while leveraging Brick’s opinionated modules for security, tenants, and payments.

How Brick compares to other Blazor SaaS kits

Placed alongside other Blazor SaaS templates, Brick can be summarized like this.

Kit / template Primary focus Multi‑tenant & SaaS depth Front‑end scope
BlazorPlate Blazor‑only multi‑tenant template Strong Blazor‑centric multi‑tenancy and localization; you add more SaaS ops as needed.​ Blazor WebAssembly/Server
Clean‑arch Blazor kits Architecture and code quality Clean layering; enterprise SaaS features mostly DIY.​ Blazor only
Custom GitHub Blazor SaaS templates Niche SaaS use cases or demos Varies; often Stripe + auth, but limited admin and tenant tooling.​ Blazor only
Brick Starter (Blazor) Full SaaS boilerplate with multi‑front‑end support Tenant management, auth/MFA, Stripe billing, email templates, localization, encryption, admin panels.​ Blazor plus Angular, React, Vue, Next.js, Razor​

For teams that want not just a UI template but a reusable SaaS platform, Brick’s broader scope and shared backend architecture are important differentiators.​

When to choose Brick Starter for full‑stack C

Brick Starter is usually the right Blazor SaaS kit when:​

  • You want full‑stack C# but do not want to design multi‑tenant, subscription, and security infrastructure yourself.
  • You may need to support additional clients (SPA, mobile, or another JS framework) later, and you want a backend that is already built for that.
  • You are a founder, product team, or agency that needs to standardize on a single .NET SaaS foundation across multiple apps, with predictable architecture and commercial support.​

In those cases, Brick Starter’s combination of Blazor front end, multi‑tenant SaaS backend, and full source code makes it a strong choice among Blazor SaaS starter kits for 2026 and beyond.

Dev tools Hub API

2025-12-15 00:46:34

This is a submission for the Xano AI-Powered Backend Challenge: Production-Ready Public API

What I Built

Title: DevTools Resource Hub API
Available: True
DevTools API's:

  1. Xano Hub API: https://xwog-4ywl-hcgl.n7e.xano.io/api:Om3nin98
  2. Xano Assisted Production API: https://devtools-hub-api.onrender.com/

Software Backend Architecture

The backend follows a layered, modular design suitable for an MVP.
API endpoints expose REST interfaces, protected by authentication, rate limiting, and validation. Core business logic is isolated into services like search, recommendations, and scoring. A data access layer handles queries, caching, and transactions on PostgreSQL.
Event handling and background jobs enable scalable, asynchronous integrations.


This will give a simple representation of caching Strategy

Databases

tools

Column Name Type Constraints / Description
id SERIAL Primary Key
name VARCHAR(255) Unique, Not Null
slug VARCHAR(255) Unique, URL-safe
category_id INTEGER FK → categories.id
description TEXT Tool description
tagline VARCHAR(500) Short marketing line
website_url VARCHAR(500) Official website
logo_url VARCHAR(500) Logo image URL
founded_date DATE Company founding date
company_name VARCHAR(255) Company behind the tool
is_active BOOLEAN Default: true
query_count INTEGER Default: 0 (trending score)
last_queried_at TIMESTAMP Last API query time
created_at TIMESTAMP Default: now()
updated_at TIMESTAMP Default: now()

Indexes

  • category_id
  • slug
  • is_active
  • (query_count, last_queried_at)

categories

Column Name Type Constraints / Description
id SERIAL Primary Key
name VARCHAR(255) Unique, Not Null
slug VARCHAR(255) Unique
parent_id INTEGER Self FK → categories.id
description TEXT Category description
icon VARCHAR(100) Icon identifier
display_order INTEGER Default: 0
created_at TIMESTAMP Created timestamp

Indexes

  • parent_id
  • slug

pricing_tiers

Column Name Type Constraints / Description
id SERIAL Primary Key
tool_id INTEGER FK → tools.id (CASCADE)
tier_name VARCHAR(100) Free, Starter, Pro
monthly_price DECIMAL(10,2) Nullable
annual_price DECIMAL(10,2) Nullable
currency VARCHAR(3) Default: USD
billing_cycle ENUM monthly, annual, one-time
features_json JSONB Flexible features list
limits_json JSONB API limits, users, storage
is_current BOOLEAN Default: true
effective_from TIMESTAMP Pricing start
effective_to TIMESTAMP Nullable
created_at TIMESTAMP Created timestamp

Indexes

  • (tool_id, is_current)
  • (effective_from, effective_to)

alternatives

Column Name Type Constraints / Description
id SERIAL Primary Key
tool_id INTEGER FK → tools.id
alternative_id INTEGER FK → tools.id
similarity_score DECIMAL(5,2) Range: 0–100
match_basis ENUM features, pricing, category
comparison_notes TEXT Comparison details
upvotes INTEGER Default: 0
created_at TIMESTAMP Created timestamp
updated_at TIMESTAMP Updated timestamp

Constraints

  • UNIQUE(tool_id, alternative_id)
  • tool_id ≠ alternative_id

Indexes

  • tool_id
  • similarity_score DESC

reviews_aggregate

Column Name Type Constraints / Description
id SERIAL Primary Key
tool_id INTEGER FK → tools.id
source VARCHAR(50) g2, capterra, producthunt
avg_rating DECIMAL(3,2) Range: 0–5
total_reviews INTEGER Review count
rating_breakdown JSONB {5:120,4:45,...}
source_url VARCHAR(500) Review page URL
last_scraped_at TIMESTAMP Scraping time
created_at TIMESTAMP Created timestamp

Indexes

  • (tool_id, source)
  • avg_rating DESC

features

Column Name Type Constraints / Description
id SERIAL Primary Key
tool_id INTEGER FK → tools.id
feature_name VARCHAR(255) Feature title
feature_category VARCHAR(100) Auth, API, Database
is_available BOOLEAN Default: true
tier_availability VARCHAR(50) free, pro, all
description TEXT Feature details
created_at TIMESTAMP Created timestamp

Indexes

  • tool_id
  • feature_category
  • is_available

changelog

Column Name Type Constraints / Description
id SERIAL Primary Key
tool_id INTEGER FK → tools.id
change_type ENUM pricing, feature, update
change_summary VARCHAR(500) Short summary
change_details TEXT Detailed change
old_value JSONB Previous value
new_value JSONB Updated value
changed_at TIMESTAMP When change occurred
created_at TIMESTAMP Created timestamp

Indexes

  • (tool_id, changed_at DESC)
  • change_type

integrations

Column Name Type Constraints / Description
id SERIAL Primary Key
tool_id INTEGER FK → tools.id
integrates_with INTEGER FK → tools.id
integration_type ENUM native, api, webhook, zapier
ease_of_setup ENUM easy, medium, complex
documentation_url VARCHAR(500) Docs link
is_official BOOLEAN Default: false
created_at TIMESTAMP Created timestamp

Indexes

  • tool_id
  • integrates_with

API Documentation

Got it 👍
Below is a dev.to–friendly Markdown version of your API documentation without tables, using clean headings, bullet points, and code blocks. You can paste this directly into a dev.to article.

🚀 DevTools Resource Hub API

A public API to discover, compare, price-check, and find alternatives for developer tools.

🧰 Tools API

1️⃣ Get All Tools

Endpoint

GET /tools/

Query Parameters

  • category (string, optional) – Filter by category
  • price_min (number, optional) – Minimum price
  • price_max (number, optional) – Maximum price
  • features (array of strings, optional) – Required features
  • sort (string, default: "name") – Sorting field
  • page (number, default: 1) – Page number
  • size (number, default: 10) – Page size

Response

{
  "items": [
    {
      "id": 1,
      "name": "VS Code",
      "description": "Code editor redefined...",
      "price": 0,
      "category": "Development"
    }
  ],
  "total": 1,
  "page": 1,
  "size": 10
}

2️⃣ Get Tool by ID

Endpoint

GET /tools/{tool_id}

Response

{
  "id": 1,
  "name": "VS Code",
  "description": "Visual Studio Code is a lightweight but powerful source code editor...",
  "price": 0,
  "category": "Development",
  "features": ["IntelliSense", "Debugging", "Git Control"]
}

3️⃣ Get Tool Alternatives

Endpoint

GET /tools/{tool_id}/alternatives

Query Parameters

  • min_similarity (number, default: 50)
  • limit (number, default: 10)

Response

{
  "alternatives": [
    {
      "id": 2,
      "name": "Sublime Text",
      "similarity_score": 85
    }
  ]
}

4️⃣ Get Tool Pricing

Endpoint

GET /tools/{tool_id}/pricing

Query Parameters

  • include_history (boolean, default: false)

Response

{
  "tool_id": 1,
  "current_price": 0,
  "pricing_plans": [
    { "plan": "Free", "price": 0, "features": ["Basic Features"] },
    { "plan": "Pro", "price": 5, "features": ["All Features"] }
  ]
}

5️⃣ Get Tool Reviews

Endpoint

GET /tools/{tool_id}/reviews

Response

{
  "tool_id": 1,
  "average_rating": 4.8,
  "reviews": [
    {
      "user": "Developer123",
      "rating": 5,
      "comment": "Best editor I've used!",
      "date": "2023-11-15"
    }
  ]
}

6️⃣ Compare Tools

Endpoint

POST /tools/compare

Request Body

{
  "tool_ids": [1, 2, 3]
}

Response

{
  "tools": [
    {
      "id": 1,
      "name": "VS Code",
      "price": 0,
      "features": ["IntelliSense", "Debugging", "Git Control"]
    },
    {
      "id": 2,
      "name": "Sublime Text",
      "price": 99,
      "features": ["Goto Anything", "Multiple Selections", "Command Palette"]
    }
  ],
  "comparison": {
    "price_range": { "min": 0, "max": 99 },
    "common_features": [],
    "unique_features": {
      "1": ["IntelliSense", "Debugging", "Git Control"],
      "2": ["Goto Anything", "Multiple Selections", "Command Palette"]
    }
  }
}

Perfect 👍
Here is the Categories API documentation converted into clean dev.to Markdown, without tables, matching the style of your Tools & Search docs.

You can paste this directly into dev.to.

/api/v1/categories

1️⃣ Get All Categories

Retrieve all categories or filter by a parent category.

Endpoint

GET /api/v1/categories/

Query Parameters

  • parent_id (number, optional) – Filter by parent category ID

Response

{
  "items": [
    {
      "id": 1,
      "name": "Development",
      "slug": "development",
      "parent_id": null,
      "description": "Development tools and IDEs",
      "icon": "code",
      "display_order": 1
    }
  ],
  "total": 1,
  "page": 1,
  "size": 10
}

2️⃣ Get Category by ID

Fetch details of a single category using its ID.

Endpoint

GET /api/v1/categories/{category_id}

Response

{
  "id": 1,
  "name": "Development",
  "slug": "development",
  "parent_id": null,
  "description": "Development tools and IDEs",
  "icon": "code",
  "display_order": 1,
  "created_at": "2023-01-01T00:00:00Z",
  "updated_at": "2023-01-01T00:00:00Z"
}

3️⃣ Get Tools in a Category

Retrieve all tools belonging to a category.
Optionally include tools from subcategories.

Endpoint

GET /api/v1/categories/{slug}/tools

Query Parameters

  • include_subcategories (boolean, default: true) – Include tools from child categories

Response

{
  "category": {
    "id": 1,
    "name": "Development",
    "slug": "development"
  },
  "tools": [
    {
      "id": 1,
      "name": "VS Code",
      "description": "Code editor redefined...",
      "price": 0,
      "category": "Development"
    }
  ],
  "total": 1
}

4️⃣ Create a Category

Create a new category.
Requires authentication.

Endpoint

POST /api/v1/categories/

Request Body

{
  "name": "Web Development",
  "slug": "web-dev",
  "parent_id": 1,
  "description": "Web development tools and frameworks",
  "icon": "globe",
  "display_order": 2
}

💡 slug will be auto-generated if not provided.

Response

{
  "id": 2,
  "name": "Web Development",
  "slug": "web-dev",
  "parent_id": 1,
  "description": "Web development tools and frameworks",
  "icon": "globe",
  "display_order": 2,
  "created_at": "2023-01-02T00:00:00Z",
  "updated_at": "2023-01-02T00:00:00Z"
}

5️⃣ Update a Category

Update an existing category.
Requires authentication.

Endpoint

PUT /api/v1/categories/{category_id}

Request Body

{
  "name": "Web Development Tools",
  "description": "Updated description",
  "icon": "browser"
}

Response

{
  "id": 2,
  "name": "Web Development Tools",
  "slug": "web-dev",
  "parent_id": 1,
  "description": "Updated description",
  "icon": "browser",
  "display_order": 2,
  "created_at": "2023-01-02T00:00:00Z",
  "updated_at": "2023-01-03T00:00:00Z"
}

6️⃣ Delete a Category

Delete a category by ID.
Requires authentication.

Endpoint

DELETE /api/v1/categories/{category_id}

Response

{
  "success": true,
  "message": "Category deleted successfully"
}

📌 Example Usage

Get All Root Categories

GET /api/v1/categories/
Accept: application/json

Get Subcategories of a Parent Category

GET /api/v1/categories/?parent_id=1
Accept: application/json

Get Tools in a Category

GET /api/v1/categories/development/tools?include_subcategories=true
Accept: application/json

Create a New Category

POST /api/v1/categories/
Content-Type: application/json
Authorization: Bearer your_access_token_here
{
  "name": "Mobile Development",
  "description": "Mobile app development tools",
  "icon": "smartphone"
}

Update a Category

PUT /api/v1/categories/3
Content-Type: application/json
Authorization: Bearer your_access_token_here
{
  "name": "Mobile App Development",
  "description": "Tools for mobile application development"
}

Delete a Category

DELETE /api/v1/categories/3
Authorization: Bearer your_access_token_here

🔍 Search API

1️⃣ Search Tools

Endpoint

GET /search/tools

Query Parameters

  • q (string, required) – Search query
  • category (string, optional)
  • price_min (number, optional)
  • price_max (number, optional)
  • features (array of strings, optional)
  • sort_by (string, default: "relevance")

Response

{
  "results": [
    {
      "id": 1,
      "name": "VS Code",
      "description": "Code editor redefined...",
      "price": 0,
      "category": "Development"
    }
  ],
  "filters": {
    "categories": ["Development", "Design"],
    "price_range": { "min": 0, "max": 199.99 }
  }
}

2️⃣ Get Search Suggestions

Endpoint

GET /search/suggestions

Query Parameters

  • q (string, required)
  • limit (number, default: 5)

Response

{
  "suggestions": [
    "code editor",
    "development tools",
    "IDE"
  ]
}

3️⃣ Get Search Filters

Endpoint

GET /search/filters

Response

{
  "categories": [
    { "id": 1, "name": "Development", "count": 45 },
    { "id": 2, "name": "Design", "count": 32 }
  ],
  "price_ranges": [
    { "min": 0, "max": 0, "count": 25 },
    { "min": 0, "max": 50, "count": 30 }
  ],
  "features": [
    { "name": "Free Plan", "count": 42 },
    { "name": "Open Source", "count": 35 }
  ]
}

❤️ Health Check

Health Status

Endpoint

GET /health

Response

{
  "status": "ok",
  "version": "1.0.0",
  "environment": "production"
}

Demo

api/v1/tools!


The AI Prompt I Used

Generate a complete backend system for a DevTools Resource Hub API, a public API to discover, compare, price-check, and recommend developer tools.

PART 1 – Database Schema (PostgreSQL / Xano-compatible)
Create 8 core tables: tools, categories, pricing_tiers, alternatives, reviews_aggregate, features, changelog, integrations.
Each table must include proper primary keys, foreign keys, enums, JSONB fields, defaults, constraints, and timestamps.
Support hierarchical categories, pricing history, similarity scoring, integrations, reviews aggregation, and changelog tracking.
Add all required indexes for performance (search, trending, filters, sorting).
Output schema as SQL CREATE TABLE statements or XanoScript-compatible JSON.

PART 2 – REST API Endpoints (15 total)
Implement endpoints for tools listing, tool details, alternatives, pricing, reviews, comparison, categories, category tools, search, trending, recently updated, recommendations, integrations graph, tool integrations, and pricing analytics.
All responses must follow a unified JSON format with success, data, and meta.
Support pagination, filtering, sorting, relevance ranking, and similarity-based recommendations.
Include proper error handling with standard error codes (400, 401, 404, 429, 500).
Output endpoints as Xano API configurations or endpoint definitions.

PART 3 – Authentication & Security
Create users, api_keys, and request_logs tables.
Implement API key–based authentication with bcrypt password hashing and SHA-256 API key storage.
Add rate limiting by tier (anonymous, free, paid) with hourly and daily tracking.
Create auth endpoints: /auth/register, /auth/login, /auth/usage.
Include CORS config, input validation, SQL injection protection, and tier-based authorization rules.
Output as Xano auth middleware or function definitions.

PART 4 – Business Logic Functions
Implement functions for similarity scoring, trending score calculation, query tracking, recommendations, price change detection, and full-text search.
Use weighted algorithms combining features, pricing, categories, integrations, popularity, and reviews.
Support background jobs and webhook triggers.
Output as XanoScript or JavaScript/TypeScript Lambda functions.

PART 5 – Sample Data Seeding
Generate realistic seed data for 20 tools across 5 categories (Backend, Frontend, Hosting, Auth, Database).
Include full tool info, pricing tiers, features, reviews, alternatives, and integrations.
Use real-world tools like Xano, Supabase, Firebase, React, Vercel, Auth0, PostgreSQL, etc.
Output as SQL INSERT statements or Xano-importable JSON.

How I Refined the AI-Generated Code

Master Backend Intelligence Prompt (SQL + Lambda)

Build advanced backend intelligence for a Developer Tools Platform using PostgreSQL SQL + JavaScript Lambda functions.

PART A – Similarity Scoring (SQL)
Create an optimized SQL query for calculate_similarity_score(tool_a, tool_b) that:
Computes feature overlap using array intersection
Calculates price similarity (NULL-safe)
Adds category exact-match bonus

Calculates integration overlap using EXISTS subqueries
Includes review rating similarity
Final weighted score:
Features 40%, Price 20%, Category 15%, Integrations 15%, Reviews 10%
Use CTEs, avoid N+1 queries, optimized joins only

PART B – Trending Algorithm (SQL)
Write a SQL query for /trending endpoint:
trending_score = query_count × EXP(-hours_since_last_query / 168) × ((avg_rating / 5) × LN(total_reviews + 1))
Filter is_active = true
Optional category filter
Time filters: 24h | 7d | 30d
Return top 20 (custom limit allowed)
Output: tool info, trending_score, query_count, avg_rating
Optimize for read-heavy workloads

PART C – Tool Comparison (SQL)
Create a single SQL query for /tools/compare:
Accept 2–5 tool IDs
Return structured JSON:
Basic info (name, logo, website)
Cheapest pricing tier
Feature matrix (all unique features, tool-wise availability)
Common vs unique features
Integration counts
Aggregated ratings
Handle NULLs as "Not Available"
No loops, JSON aggregation only

PART D – Pricing Trends Analytics (SQL)
Write SQL for /analytics/pricing-trends:
Last 12 months, grouped by month + category
Cheapest paid tier per tool
Average price per category per month
Month-over-month percentage change
Identify biggest price increases/decreases
Optional category filter
Output format optimized for charts

These all things have generated via xanoscript the TASKS, JOBS that trigger all fetch recent prices, analytics and trending score for products

My Experience with Xano

As you can see below images, As a Dev creating Database and using them on production is kind of headache task as we need to take care of availability, Rollbacks, Replication and a lot of task that xano has reduced a lot, along with scheduling the jobs and using serverless functions for this application is made easy, Even for pricing analysis for the tools i have used a Task as you can see below
The API Endpoint
https://price-change-9x01.onrender.com/pricing/{tool_id}?upload=true will track the price for tool and post it in pricing_tier and it is scheduled every day. It is made so much easy


We can use the database directly via API endpoints created automatically is plus point on top of which we can use the API, the actually Prod deployed application of mine is using the same

AI, TASK, DATABASE, API are the best things what i could able to use here. Small glimpse of Xanoscript as it is huge.
`// Triggers pricing uploads for all tools via external API
task trigger_pricing_uploads {
stack {
// Retrieve all records from the tool table
// Get all tools
db.query tool {
return = {type: "list"}
output = ["id"]
} as $tools

// Iterate through the list of tools returned by the database query
foreach ($tools) {
  each as $tool {
    // Construct the URL dynamically and make the request
    api.request {
      url = "https://price-change-9x01.onrender.com/pricing/" ~ $tool.id ~ "?upload=true"
      method = "GET"
    } as $api_response
  }
}

// Log task completion status
debug.log {
  value = {success: true, processed_count: $tools|count}
}

}

schedule = [{starts_on: 2026-01-01 00:00:00+0000, freq: 86400}]
tags = ["price tag", "tools"]
}`
Github Repo Link: https://github.com/its-shashankY/Devtools_hub_api

Token Validation

2025-12-15 00:42:38


I came across this line of code in an authentication tutorial but didn’t fully understand what it was doing under the hood, and the tutorial didn’t explain it either. So, I researched how it actually works internally and documented my findings here in the simplest way possible.

Firstly:
func ValidateToken(tokenString string)(*Claims , error)

  1. Takes a JWT string called tokenString
  2. Returns a pointer to a Claims struct containing the decoded payload if valid
  3. Returns an error if the token is invalid

my Claims Struct is as follow:

type Claims struct {
    UserID string json:"user_id"
    jwt.StandardClaims
}

Secondly:

secretKey := GetJWTKey()
  1. Fetches the global secret key used for signing and validating JWTs
  2. This is the same key for all users in my case since it is HS256
  3. Stored as []byte internally

Thirdly (This is the part that I had problem understanding)

jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
    return secretKey, nil
})

Just a couple of things to understand: [
a. &Claims{} -> so Claims{} creates a new empty Claims struct first and we pass in the pointer to this created Claims struct. If we pass in just Claims{} (value), Go would copy the struct and fill in the token details in that copied struct instead of the original struct so the original struct remains unchanged

b. interface{} here is referring to generic type which can hold []byte (HS256) or RSA keys (RS256) etc...
]

  1. So when this function gets called, the jwt.ParseWithClaims does: -> Splits the token string into three parts -> , ,

Header:
-> Encoded in Base64
-> Contains metadata about the token, usually:
{
"alg": "HS256", // algorithm used to sign the token
"typ": "JWT" // type of token
}
alg → tells the server how to verify the signature (HMAC SHA256, RSA, etc.)
typ → usually "JWT", indicates the type of token
-> information used to verify the signature.

Payload (Claims):
-> Also encoded in Base64
-> Contains the data about the user and token
-> Payload in my case here corresponds to the Claims structure I defined above
-> An example payload JSON:

   {
  "user_id": "12345",
  "exp": 1712345678,  // expiration timestamp
  "iat": 1712342000,  // issued at timestamp
  "iss": "my-app",    // issuer
  "sub": "12345"      // subject (optional)
}

and this payload is what gets parsed into &Claims{} struct

Signature
-> Calculated as:
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secretKey
)
Purpose: ensures token hasn’t been tampered with
-> Only valid if the server knows the secretKey

  1. Decodes header and payload into a temporary jwt.Token struct:
type Token struct {
    Raw       string
    Method    SigningMethod
    Header    map[string]interface{} -> alg types
    Claims    Claims
    Signature string
    Valid     bool
}
  1. Call the function:
func(token *jwt.Token)(interface{}, error) {return secretKey,nil}

.
Here, we pass in the temporary jwt.Token struct formed in Step 2 into the function
-> Since this jwt.Token contains the header, we can dynamically choose which key to choose based on the method, but in my case as mentioned earlier I am using the same secretKey all the time so no dynamic selection is needed
-> Return the secretKey

  1. After the key function returns secretKey, jwt.ParseWithClaims does the following internally: -> Recalculate the expected signature: a. Uses the decoded + + secretKey b. Algorithm is determined by token.Method from the header(HS256, etc.)

-> Compare with the signature in the token:

type Token struct {
    Raw       string
    Method    SigningMethod
    Header    map[string]interface{} -> alg types
    Claims    Claims
    **Signature string** <- Compare with this
    Valid     bool
}
 a. If they match → token is valid and untampered
 b. If they don’t → token is invalid

As mentioned above:
Signature
-> Calculated as:
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secretKey
)

-> Fill the Claims struct (&Claims{}):
a. Decoded payload is written into your Claims struct pointer
b. Standard claims (exp, iat, iss, etc.) and custom claims (user_id) are all set

-> token.Valid is set to true if signature matches and standard claims (e.g., expiration) are valid

  1. After jwt.ParseWithClaims returns
if claims, ok := token.Claims.(*Claims); ok && token.Valid {
    return claims, nil
}

-> We type assert the generic token.Claims to my concrete *Claims struct
-> If type assertion succeeds then return the value (claims of type *Claims) and ok (type boolean true)
-> Then we can safely access:
claims.UserID
claims.ExpiresAt
claims.Issuer

TLDR Flow:

  1. jwt.ParseWithClaims receives tokenString
  2. Splits token → header, payload, signature
  3. Decodes header + payload → temporary jwt.Token struct
  4. Calls key function with jwt.Token → returns secretKey
  5. Recalculates signature using secretKey
  6. Compares with token’s signature
    • Match → valid
    • No match → invalid
  7. Fills &Claims{} struct with payload data
  8. Returns token with token.Valid = true

How to Build a Real-Time SEC Filing Monitor in Python (Under 50 Lines)

2025-12-15 00:41:18

Ever wonder how hedge funds know about insider trades before you do?

They're not psychic. They just have systems monitoring SEC filings in real-time. The moment a Form 4 hits EDGAR, they know.

Today, we're building that system. In Python. In under 50 lines.

Why Monitor SEC Filings?

Three filings move markets:

  • 8-K: Unscheduled material events (CEO quits, merger announced, lawsuit filed)
  • 10-K/10-Q: Annual and quarterly financials
  • Form 4: Insider trading — when executives buy or sell their own stock

That last one is interesting. When a CEO buys $2M of their own company's stock, that's a signal. They know something.

What We're Building

A Python script that:

  1. Checks for new filings every 5 minutes
  2. Filters by your watchlist (specific tickers)
  3. Prints alerts to console (easily extendable to Slack, email, etc.)

No scraping. No parsing HTML. No dealing with EDGAR's... quirks.

First, grab a free API key.

The Code

import requests
import time
from datetime import datetime

# Config
API_KEY = "your_api_key"  # Free tier at earningsfeed.com
BASE_URL = "https://earningsfeed.com/api/v1"
WATCHLIST = ["AAPL", "TSLA", "NVDA", "MSFT", "GOOGL"]
CHECK_INTERVAL = 300  # 5 minutes

# Track what we've already seen
seen_filings = set()

def get_recent_filings():
    """Fetch recent SEC filings for watchlist tickers."""
    headers = {"Authorization": f"Bearer {API_KEY}"}
    filings = []

    for ticker in WATCHLIST:
        response = requests.get(
            f"{BASE_URL}/filings",
            headers=headers,
            params={"ticker": ticker, "limit": 10}
        )
        if response.ok:
            filings.extend(response.json().get("items", []))

    return filings

def check_for_new_filings():
    """Check for new filings and alert on any we haven't seen."""
    filings = get_recent_filings()

    for filing in filings:
        filing_id = filing.get("accessionNumber")

        if filing_id and filing_id not in seen_filings:
            seen_filings.add(filing_id)
            alert(filing)

def alert(filing):
    """Print alert for new filing. Swap this for Slack/email/SMS."""
    company = filing.get("companyName", "Unknown")
    form_type = filing.get("formType", "???")
    filed_at = filing.get("filedAt", "")
    url = filing.get("url", "")

    print(f"""
🚨 NEW FILING DETECTED
━━━━━━━━━━━━━━━━━━━━━
Company:   {company}
Form:      {form_type}
Filed:     {filed_at}
Link:      {url}
━━━━━━━━━━━━━━━━━━━━━
    """)

def main():
    print(f"👀 Monitoring {len(WATCHLIST)} tickers: {', '.join(WATCHLIST)}")
    print(f"⏱️  Checking every {CHECK_INTERVAL // 60} minutes")
    print("Press Ctrl+C to stop\n")

    # Initial check
    check_for_new_filings()

    while True:
        time.sleep(CHECK_INTERVAL)
        print(f"[{datetime.now().strftime('%H:%M:%S')}] Checking...")
        check_for_new_filings()

if __name__ == "__main__":
    main()

That's it. Under 50 lines.

Running It

pip install requests
python sec_monitor.py

Output:

👀 Monitoring 5 tickers: AAPL, TSLA, NVDA, MSFT, GOOGL
⏱️  Checking every 5 minutes
Press Ctrl+C to stop

🚨 NEW FILING DETECTED
━━━━━━━━━━━━━━━━━━━━━
Company:   NVIDIA Corp
Form:      4
Filed:     2024-12-14T16:32:00.000Z
Link:      https://www.sec.gov/Archives/edgar/data/1045810/...
━━━━━━━━━━━━━━━━━━━━━

Make It Actually Useful

The alert() function is where you customize. Some ideas:

Slack notifications:

def alert(filing):
    requests.post(SLACK_WEBHOOK, json={
        "text": f"🚨 {filing['companyName']} just filed a {filing['formType']}"
    })

Filter by form type (only insider trades):

if filing.get("formType") == "4":
    alert(filing)

Only material events:

# In get_recent_filings(), add forms filter
params={"ticker": ticker, "forms": "8-K,4", "limit": 10}

Why I Built This

Full disclosure: I built Earnings Feed because I got tired of the alternatives.

EDGAR's direct API has rate limits that'll get you blocked. Most commercial APIs charge hundreds per month. I wanted something with a free tier that just... works.

The database covers every public company filing with the SEC. Every 10-K, every Form 4, every 8-K.

If you're building something in the fintech space, it might save you some headaches.

What Would You Build?

I'm curious what you'd do with real-time SEC data:

  • Trading signals based on insider buys?
  • Alerts when competitors file 8-Ks?
  • Tracking institutional ownership changes via 13F?

Drop a comment!

Mike’s 36th Birthday Cake – CSS Candle Wick Edition

2025-12-15 00:39:20

Check out this Pen I made!