When symbol updated, revalidate dependant pages

Website is built using Next.js

I have two models:

  • Page - results in a next.js page, rendered using [[…slug]] route
  • Symbol - a single model for storing all the website reusable symbols

I’m trying to implement On Demand Revalidation (Data Fetching: Revalidating | Next.js) to avoid website rebuild after every change and decrease content update time.

Everything works fine when I update the page itself: page webhook sends request to my next.js server and the data from body is enough to identify correct route to revalidate.

The issue I have is when I publish update on Symbol and I want to revalidate all the pages that use this symbol. I think, that it’s also might be possible that another symbol can contain the updated symbol. Either way I need to identify affected pages.

The most obvious solution would be to fetch all the pages and test each one if it contains the symbol. Same goes with higher level symbols to find all the usage places of the content.

This solution seems to be quite data heavy especially if you have large amount of pages and related models. Maybe you can recommend any other solution or smart REST API query that will help with this one?

Hi @alex.krasikau,

Welcome back to the builder.io forum.

Currently, we don’t have any better solution but you can expect the feature to be added in future updates.

But here is the sample script that you can possibly use

const API_KEY = "BUILDER_API_KEY";

// Get builder data using model name 
async function getBuilderDataByModelName(modelName){
    let url = `https://cdn.builder.io/api/v2/content/${modelName}?apiKey=${API_KEY}&includeRefs=true`;
    try{
        let res = await fetch(url);
        return await res.json();
    }catch(err) {
        console.error(err);
    };
}
async function getAllSymbolIds(){
    let symbols = await getBuilderDataByModelName("symbol-card");
    //console.log(symbols);
    let symbolIds = [];
    [...symbols.results].forEach(symbol => {
        symbolIds.push(symbol.id);
    });

    return symbolIds;
}

async function getAllContents(){
    let content = await getBuilderDataByModelName("page");
    
    // Get all symbol Ids
    const symboldIds = await getAllSymbolIds();

    // Filter content based on symbol ids 
    let filteredResults = content.results.filter((each) => {
        let stringResult = JSON.stringify(each);
        for (let symbolId of symboldIds) {
            if (stringResult.includes(symbolId)) {
                return true;
            }
        }
        return false;
    });  
    
    console.log("filterred Results" , filteredResults);
}

// Get all contents symbols 
getAllContents();
1 Like