Would it be possible to make `NextjsSite` work wit...
# help
l
Would it be possible to make
NextjsSite
work within my sst API, i.e. run by one of my serverless functions? Use case: I want a route on my API which sets up a new Next.js site for a customer when they request it. In other words, I need an sst construct to be run dynamically within my API. Any tips on how to do this would be much appreciated! Some more explanation: • My SaaS sets up Cloudfront distributions for its customers • I have demand from certain customers to create fully-fledged Next.js apps for them, and I'd like to create these using Cloudfront distributions (for cost reasons and because I already create Cloudfront distributions for my customers) • Seems like
NextjsSite
might do a lot of the hard work of setting up a Next.js app at a Cloudfront distribution if I can get my (sst) API to be able to run it
t
You can do this but it's fairly complicated. You can't use the resource directly from the API. You'd need to setup a new sst app for your customers sites. Then in main, you should load a list of customers from a database or something and initialize a stack with their site per customer. Then in your API you can add the customer to the database and then retrigger CI/CD for the app
This seems a bit weird but is typical in a multitenant workflow
Haha I just realized I use your service and we have an email thread where you manually had to setup my site, I'm assuming you're trying to automate now?
l
OK awesome, thanks so much for this. Just trying to parse your first message better to understand how I'd do that
Completely correct, am trying to automate things much better now
t
ok so basically you can try creating a new SST app, and I believe you can make the main function async
Copy code
export default async function main(app: <http://sst.App|sst.App>) {
  // Load customer data
  const sites = await database.getCustomerSites()

  for (let site of sites) {
    new SiteStack(app, site.id, site.options)
  }
}

class SiteStack extends sst.Stack {
  constructor(app: <http://sst.App|sst.App>, id: string, options) {
    super(app, id)
    
    const site = new NextJsSite(this, "site", {
      optionA: "sadasd",
      optionB: "sadasd",
      ...options
    })
  }
}
You can run these deploys manually to start whenever someone creates or updates their site. Then you can automate it by putting it in Seed and triggering a build whenever something changes
This will work but if you have a large number of sites you might need to get more clever and optimize
In this example it's one app with a stack per customer. You might want to do 1 app and a stage per site which would look something like this
Copy code
sst deploy --stage siteid
export default async function main(app: <http://sst.App|sst.App>) {
  // Load customer data
  const site = await database.getCustomerSite(app.stage)
  new SiteStack(app, site.id, site.options)
}

class SiteStack extends sst.Stack {
  constructor(app: <http://sst.App|sst.App>, id: string, options) {
    super(app, id)

    const site = new NextJsSite(this, "site", {
      optionA: "sadasd",
      optionB: "sadasd",
      ...options
    })
  }
}
l
This sounds pretty cool. I'm thinking to be as efficient as possible I could do something like: • Get only sites that are 'pending' status (i.e. not yet created) in my database • Trigger deployment (via Seed) whenever a new 'pending' site is created. I assume Seed can handle a deployment trigger happening via some kind of call to its API. Deployment will then happen, and any 'pending' sites will be set up • Somehow set site status to 'created' in database, i.e. no longer 'pending' • In effect, only ever create one Next.js app at a time I wouldn't often need to update these, I think, but if I did it would be pretty easy, manually or by simply setting a site back to 'pending' in my database.
This will work but if you have a large number of sites you might need to get more clever and optimize (edited)
OOI why would this become problematic as the number of sites increases?
t
With the first approach you have to get all the sites otherwise it thinks it needs to delete them because some won't be there anymore
The second approach is probably the right way, then you can control which one is updated at a time
l
Got it. That's awesome. Thanks so much