Nishil Faldu
Nishil Faldu4w ago

Lets say there are a lot of apps...

Lets assume that there are 5 apps with their individual databases on Convex. Now lets say later in the future I realize that I want to suggested recommendations on one app based on the data in other apps - would that be possible with convex? (5 apps would have 5 databases as I think it would be scalable for each of those individual services/apps). Also is it possible to share auth data amongst all 5 apps?
9 Replies
Convex Bot
Convex Bot4w ago
Thanks for posting in <#1088161997662724167>. Reminder: If you have a Convex Pro account, use the Convex Dashboard to file support tickets. - Provide context: What are you trying to achieve, what is the end-user interaction, what are you seeing? (full error message, command output, etc.) - Use search.convex.dev to search Docs, Stack, and Discord all at once. - Additionally, you can post your questions in the Convex Community's <#1228095053885476985> channel to receive a response from AI. - Avoid tagging staff unless specifically instructed. Thank you!
ballingt
ballingt4w ago
You can have multiple Convex clients in one webapp each reading data from separate databases. But probably what you'd want to do would be to combine some of these, if you want them to be able to get data from each other with very low latency (ie in the same transaction) Components would be a nice way to do this, so they can still be separate codebases Components have their own schema and functions and data, but run in the same deployment
Nishil Faldu
Nishil FalduOP4w ago
so you are saying - each app is a component with its own schema but all of them are still in the same deployment? that would be very good actually. is there a write-up / docs page to create custom components? I tried finding but couldn't find one
ballingt
ballingt4w ago
Yeah, that'd be the end goal. Although combining them without components is viable too, but it's easiest if they're all the same repo for this You can define schemas in pieces already without components, but eventually you have to combine them into a single schema.ts file (even if it imports the tables or the validators from other places), and htis is how our laregest customers structure their apps; lots of broken up pieces of schema, with the relevant functions in the same directory, then convex/schema.ts just combines all these pieces But at a certain size you want to split this up for TypeScript performance and so they can be separate codebases you iterate on independently so yeah custom components @Nishil Faldu Splitting things in into components isn't something we're officially recommending yet because we want to improve the interface for authoring components
Nishil Faldu
Nishil FalduOP4w ago
that is very helpful to know. thank you so much Tom would you happen to know an example repo released by you guys for that?
ballingt
ballingt3w ago
GitHub
ai-town/convex/agent/schema.ts at main · a16z-infra/ai-town
A MIT-licensed, deployable starter kit for building and customizing your own version of AI town - a virtual town where AI characters live, chat and socialize. - a16z-infra/ai-town
Nishil Faldu
Nishil FalduOP3w ago
perfect! thank you very much! also another question, I am using the R2 component and getting this error:
✖ Error: Unable to start push to https://neighborly-dogfish-454.convex.cloud
✖ Error fetching POST https://neighborly-dogfish-454.convex.cloud/api/deploy2/start_push 400 Bad Request: Error: Hit an error while pushing:
Hit an error while evaluating your schema:
Uncaught Error: Environment variables unsupported when evaluating schema
at performOp (../../udf-syscall-ffi/src/index.ts:81:0)
at get [as get] (../../udf-runtime/src/setup.ts:120:22)
at new R2 (../../../node_modules/@convex-dev/r2/src/client/index.ts:81:48)
at <anonymous> (../convex/socialMedia/storage.ts:6:13)
✖ Error: Unable to start push to https://neighborly-dogfish-454.convex.cloud
✖ Error fetching POST https://neighborly-dogfish-454.convex.cloud/api/deploy2/start_push 400 Bad Request: Error: Hit an error while pushing:
Hit an error while evaluating your schema:
Uncaught Error: Environment variables unsupported when evaluating schema
at performOp (../../udf-syscall-ffi/src/index.ts:81:0)
at get [as get] (../../udf-runtime/src/setup.ts:120:22)
at new R2 (../../../node_modules/@convex-dev/r2/src/client/index.ts:81:48)
at <anonymous> (../convex/socialMedia/storage.ts:6:13)
import { R2 } from "@convex-dev/r2";
import { components } from "../_generated/api";
import { DataModel } from "../_generated/dataModel";

export const r2 = new R2(components.r2);

export const {
generateUploadUrl,
syncMetadata,
// These aren't used in the example, but can be exported this way to utilize
// the permission check callbacks.
getMetadata,
listMetadata,
deleteObject,
} = r2.clientApi<DataModel>({
// The checkUpload callback is used for both `generateUploadUrl` and
// `syncMetadata`.
checkUpload: async (ctx, bucket) => {
// const user = await userFromAuth(ctx);
// ...validate that the user can upload to this bucket
},
checkReadKey: async (ctx, bucket, key) => {
// const user = await userFromAuth(ctx);
// ...validate that the user can read this key
},
checkReadBucket: async (ctx, bucket) => {
// const user = await userFromAuth(ctx);
// ...validate that the user can read this bucket
},
checkDelete: async (ctx, bucket, key) => {
// const user = await userFromAuth(ctx);
// ...validate that the user can delete this key
},
onUpload: async (ctx, bucket, key) => {
// ...do something with the key
// This technically runs in the `syncMetadata` mutation, as the upload
// is performed from the client side. Will run if using the `useUploadFile`
// hook, or if `syncMetadata` function is called directly. Runs after the
// `checkUpload` callback.
//
// Note: If you want to associate the newly uploaded file with some other
// data, like a message, useUploadFile returns the key in the client so you
// can do it there.
},
onDelete: async (ctx, bucket, key) => {
// Delete related data from your database, etc.
// Runs after the `checkDelete` callback.
// Alternatively, you could have your own `deleteImage` mutation that calls
// the r2 component's `deleteObject` function.
},
});;
import { R2 } from "@convex-dev/r2";
import { components } from "../_generated/api";
import { DataModel } from "../_generated/dataModel";

export const r2 = new R2(components.r2);

export const {
generateUploadUrl,
syncMetadata,
// These aren't used in the example, but can be exported this way to utilize
// the permission check callbacks.
getMetadata,
listMetadata,
deleteObject,
} = r2.clientApi<DataModel>({
// The checkUpload callback is used for both `generateUploadUrl` and
// `syncMetadata`.
checkUpload: async (ctx, bucket) => {
// const user = await userFromAuth(ctx);
// ...validate that the user can upload to this bucket
},
checkReadKey: async (ctx, bucket, key) => {
// const user = await userFromAuth(ctx);
// ...validate that the user can read this key
},
checkReadBucket: async (ctx, bucket) => {
// const user = await userFromAuth(ctx);
// ...validate that the user can read this bucket
},
checkDelete: async (ctx, bucket, key) => {
// const user = await userFromAuth(ctx);
// ...validate that the user can delete this key
},
onUpload: async (ctx, bucket, key) => {
// ...do something with the key
// This technically runs in the `syncMetadata` mutation, as the upload
// is performed from the client side. Will run if using the `useUploadFile`
// hook, or if `syncMetadata` function is called directly. Runs after the
// `checkUpload` callback.
//
// Note: If you want to associate the newly uploaded file with some other
// data, like a message, useUploadFile returns the key in the client so you
// can do it there.
},
onDelete: async (ctx, bucket, key) => {
// Delete related data from your database, etc.
// Runs after the `checkDelete` callback.
// Alternatively, you could have your own `deleteImage` mutation that calls
// the r2 component's `deleteObject` function.
},
});;
and that's my storage.ts file
ballingt
ballingt3w ago
@Nishil Faldu this error, "Environment variables unsupported when evaluating schema," means you're importing a file from your schema.ts that tries to read an environment variable
Nishil Faldu
Nishil FalduOP3w ago
figured it out. thanks again Tom!

Did you find this page helpful?