Circus
Circus
Explore posts from servers
TTCTheo's Typesafe Cult
Created by Circus on 4/26/2024 in #questions
VSCode Import Autocomplete Purgatory (Relative, absolute, and barrel paths)
No description
2 replies
TTCTheo's Typesafe Cult
Created by Circus on 4/22/2024 in #questions
Appropriate Use of Modals - Attach to mapped components or pass modal logic down?
Is there considerable downside to attaching a modal to individual mapped components? Is it better/preferred to have a centralized Modal on the page and then pass down modal logic to the mapped components? Example 1: Modal on each mapped component
const ToDoComponent = ({ todo }) => {
// logic for modal here
return (
<div>
{todo}
<ModalThatDoesSomething />
</div>
);
};

const Page = () => {
const todos = [todo1, todo2, todo3, ...];

return <div>
{todos.map((todo) => (
<ToDoComponent todo={todo} />
)}
</div>;
};

export default Page;
const ToDoComponent = ({ todo }) => {
// logic for modal here
return (
<div>
{todo}
<ModalThatDoesSomething />
</div>
);
};

const Page = () => {
const todos = [todo1, todo2, todo3, ...];

return <div>
{todos.map((todo) => (
<ToDoComponent todo={todo} />
)}
</div>;
};

export default Page;
Example 2: Centralized Modal
const ToDoComponent = ({ todo, modalLogic }) => {
// modal logic is triggered and passed up to parent
return (
<div>
{todo}
</div>
);
};

const Page = () => {
const todos = [todo1, todo2, todo3, ...];
// MODAL LOGIC HERE


return <div>
{todos.map((todo) => (
<ToDoComponent todo={todo} modalLogic={modalLogic} />
)}

<ModalThatDoesSomething />
</div>;
};

export default Page;
const ToDoComponent = ({ todo, modalLogic }) => {
// modal logic is triggered and passed up to parent
return (
<div>
{todo}
</div>
);
};

const Page = () => {
const todos = [todo1, todo2, todo3, ...];
// MODAL LOGIC HERE


return <div>
{todos.map((todo) => (
<ToDoComponent todo={todo} modalLogic={modalLogic} />
)}

<ModalThatDoesSomething />
</div>;
};

export default Page;
8 replies
TtRPC
Created by Circus on 4/16/2024 in #❓-help
Revalidate / invalidate in server components
Is there a solution for TRPC query invalidation (or revalidating), passing the actions from the client component where the action happens to server components? So far, I've only seen examples where you have to turn the respective server components into client components. Are there any better solutions?
2 replies
TTCTheo's Typesafe Cult
Created by Circus on 3/26/2024 in #questions
T3, Intellisense, & Alias Path/Module
Using the latest T3 stack, I've been having issues getting Intellisense autocomplete to recognize any custom alias modules. It's not really an error, so no error message to give. Does anyone have any ideas? Screenshot for folder structure (src/app/_components/index for barrel importing)
//tsconfig.json
{"compilerOptions":{
...
/* Path Aliases */
"baseUrl": ".",
"paths": {
"~/*": ["./src/*"],
"@/components/*": ["./src/app/_components/*"],
},
"include": [
".eslintrc.cjs",
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
"**/*.cjs",
"**/*.js",
".next/types/**/*.ts"
],
}
//tsconfig.json
{"compilerOptions":{
...
/* Path Aliases */
"baseUrl": ".",
"paths": {
"~/*": ["./src/*"],
"@/components/*": ["./src/app/_components/*"],
},
"include": [
".eslintrc.cjs",
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
"**/*.cjs",
"**/*.js",
".next/types/**/*.ts"
],
}
2 replies
TTCTheo's Typesafe Cult
Created by Circus on 3/21/2024 in #questions
Is it worth updating from the old T3 stack to new?
Hi, I was hoping to get some consensus on a decision about whether I should upgrade my application to the latest T3 stack and would love your input Current stack Next pages router, Clerk, Planetscale, Prisma, TRPC. Not a huge or complex app (my experience is mid-senior on frontend, early-mid on backend) Current Issues Planetscale's free tier has made switching to a different database a nightmare. I've heard Supabase is nice but it doesn't play well with Prisma. There's a widening gap between new technologies that are only being set up for app router and I'm worried about the lifetime of pages router. Trepidations Clerk and app router notoriously don't work well together, and NextAuth is notoriously horrifying as well. I have very little users and data overall, so all the work needed to do the update. Is it worth upgrading to the latest T3 stack? There seem to be tradeoffs going both ways, and right now it's very tempting to just spend $40/month at Planetscale to handle my whopping 100 rows of data even though my app makes no money just to not deal with the pain and frustration, but would love to get your input for a currently jaded developer
10 replies
TTCTheo's Typesafe Cult
Created by Circus on 3/19/2024 in #questions
Migrating away from Planetscale (expiring hobby plan)
Due to Planetscale deprecating their hobby plan, I'm taking a very basic database of my hobby project and seeking to move it over. I've seen Supabase recommended, but the transfer of Planetscale's MySQL base to Supabase's Postgres is a nightmare for something that should be very simple. For those of us that just want an easy migration, does anyone know of the most pain-free experience to migrate data?
12 replies
TTCTheo's Typesafe Cult
Created by Circus on 3/1/2024 in #questions
Using getStaticProps with TRPC (Fetching data via mutate)
Hi, I'm trying to do a TRPC fetch that requires a mutation (not possible to do a query, GET request not allowed) just once on a page. It would make sense to have it in getStaticProps, but I can't get it to work properly. Either the ssg helpers aren't recognized as with other fetch routes or trying to retrieve the data in a hook in the component leads to infinite mutates. I've left small notes in the codes to show as much. What would you say is the optimal way to handle this?
import { createServerSideHelpers } from "@trpc/react-query/server";
import { GetStaticProps, InferGetServerSidePropsType, InferGetStaticPropsType } from "next";
import superjson from "superjson";
import { appRouter } from "~/server/api/root";
import { prisma } from "~/server/db";
import { api } from "~/utils/api";

export const generateSSGHelper = () =>
createServerSideHelpers({
router: appRouter,
ctx: { prisma, userId: null },
transformer: superjson, // optional - adds superjson serialization
});

export const getStaticProps: GetStaticProps = async (context) => {
const cityName = context.params?.slug;
const ssg = generateSSGHelper();
// This line works because of the `prefetch` call in the `getStaticProps` of the page
await ssg.city.getCityDataByName.prefetch({ name: cityName });
//await ssg.routerThatRequiresMutation << Intellisense says this doesn't exist either

return {
props: {
trpcState: ssg.dehydrate(),
cityName,
},
};
};

const SlugPage = (
props: InferGetStaticPropsType<typeof getStaticProps>
) => {
const { data: cityData } = api.city.getCityDataByName.useQuery({
name: cityName as string,
});

// Calling fetchData will trigger the mutation infinitely
const fetchData = api.apiRouterThatRequiresMutation.useMutation();

return null;
};

export default SlugPage;
import { createServerSideHelpers } from "@trpc/react-query/server";
import { GetStaticProps, InferGetServerSidePropsType, InferGetStaticPropsType } from "next";
import superjson from "superjson";
import { appRouter } from "~/server/api/root";
import { prisma } from "~/server/db";
import { api } from "~/utils/api";

export const generateSSGHelper = () =>
createServerSideHelpers({
router: appRouter,
ctx: { prisma, userId: null },
transformer: superjson, // optional - adds superjson serialization
});

export const getStaticProps: GetStaticProps = async (context) => {
const cityName = context.params?.slug;
const ssg = generateSSGHelper();
// This line works because of the `prefetch` call in the `getStaticProps` of the page
await ssg.city.getCityDataByName.prefetch({ name: cityName });
//await ssg.routerThatRequiresMutation << Intellisense says this doesn't exist either

return {
props: {
trpcState: ssg.dehydrate(),
cityName,
},
};
};

const SlugPage = (
props: InferGetStaticPropsType<typeof getStaticProps>
) => {
const { data: cityData } = api.city.getCityDataByName.useQuery({
name: cityName as string,
});

// Calling fetchData will trigger the mutation infinitely
const fetchData = api.apiRouterThatRequiresMutation.useMutation();

return null;
};

export default SlugPage;
2 replies
TTCTheo's Typesafe Cult
Created by Circus on 2/27/2024 in #questions
TRPC with Google Places API (New)
Has anyone had any luck using TRPC with Google's Places API (New) that only has cURL examples? Here is my attempted router for nearby search using the example from Google's docs (https://developers.google.com/maps/documentation/places/web-service/nearby-search) that gets a generic 400 status. The cURL works, so there's something wrong with the router...or possibly the API 🙃
const apiKey = process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY ?? "";

searchPlacesByLocationNew: publicProcedure
.input(z.object({ location: z.string() }))
.mutation(async ({ input }) => {
const apiUrl = `https://places.googleapis.com/v1/places:searchNearby`;
const body = JSON.stringify({
includedTypes: ["restaurant"],
maxResultCount: 10,
locationRestriction: {
circle: {
center: {
latitude: 51.5074,
longitude: -0.1278,
},
radius: 500.0,
},
},
});

try {
const options = {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Goog-Api-Key": apiKey,
"X-Goog-FieldMask": "places.displayName",
},
body,
};

const response = await fetch(apiUrl, options);
console.log("This is response", response);
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const data = (await response.json()) as NearbySearchResponse;
console.log("This is data", data);
return data;
} catch (error) {
console.error("Error fetching data from Google Places API:", error);
return { error: "Failed to fetch data from Google" };
}
}),
const apiKey = process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY ?? "";

searchPlacesByLocationNew: publicProcedure
.input(z.object({ location: z.string() }))
.mutation(async ({ input }) => {
const apiUrl = `https://places.googleapis.com/v1/places:searchNearby`;
const body = JSON.stringify({
includedTypes: ["restaurant"],
maxResultCount: 10,
locationRestriction: {
circle: {
center: {
latitude: 51.5074,
longitude: -0.1278,
},
radius: 500.0,
},
},
});

try {
const options = {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Goog-Api-Key": apiKey,
"X-Goog-FieldMask": "places.displayName",
},
body,
};

const response = await fetch(apiUrl, options);
console.log("This is response", response);
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const data = (await response.json()) as NearbySearchResponse;
console.log("This is data", data);
return data;
} catch (error) {
console.error("Error fetching data from Google Places API:", error);
return { error: "Failed to fetch data from Google" };
}
}),
4 replies
TTCTheo's Typesafe Cult
Created by Circus on 2/9/2024 in #questions
Using TRPC with Google's Place Details
Has anyone been able to properly set up a TRPC router with Google's Place Details API? (https://developers.google.com/maps/documentation/places/web-service/place-details) Doing the curl command from the link works fine, so it's something with the TRPC request (Status 400 HTTP error). I've also tried passing the parameters as headers in the options field to no avail
export const googleRouter = createTRPCRouter({
getPlaceDetails: publicProcedure
.input(z.object({ placeId: z.string() }))
.query(async ({ input }) => {
const placeId = "ChIJN1t_tDeuEmsRUsoyG83frY4";
const apiKey = process.env.GOOGLE_DETAILS_API_KEY ?? ""; // Ensure this is set in your environment
const apiUrl = `https://places.googleapis.com/v1/places/ChIJj61dQgK6j4AR4GeTYWZsKWw?fields=id,displayName&key=${apiKey}`;


try {
const options = {
method: "GET",
headers: {
"Content-Type": "application/json",
"X-Goog-Api-Key": apiKey,
"X-Goog-FieldMask":
"id,displayName,formattedAddress,plusCode,rating",
},
};

const response = await fetch(apiUrl, options);
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const data = (await response.json()) as PlaceResult;
return data; // Ensure that the data is returned
} catch (error) {
console.error(
"Error fetching data from Google Place Details API:",
error
);
return { error: "Failed to fetch data from Google" }; // Return an error object instead of throwing
}
}),
});

// ChIJ2dGMjMMEdkgRqVqkuXQkj7c Big Ben
// ChIJN1t_tDeuEmsRUsoyG83frY4 Google Office Sydney
// ChIJj61dQgK6j4AR4GeTYWZsKWw from example on https://developers.google.com/maps/documentation/places/web-service/place-details
export const googleRouter = createTRPCRouter({
getPlaceDetails: publicProcedure
.input(z.object({ placeId: z.string() }))
.query(async ({ input }) => {
const placeId = "ChIJN1t_tDeuEmsRUsoyG83frY4";
const apiKey = process.env.GOOGLE_DETAILS_API_KEY ?? ""; // Ensure this is set in your environment
const apiUrl = `https://places.googleapis.com/v1/places/ChIJj61dQgK6j4AR4GeTYWZsKWw?fields=id,displayName&key=${apiKey}`;


try {
const options = {
method: "GET",
headers: {
"Content-Type": "application/json",
"X-Goog-Api-Key": apiKey,
"X-Goog-FieldMask":
"id,displayName,formattedAddress,plusCode,rating",
},
};

const response = await fetch(apiUrl, options);
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const data = (await response.json()) as PlaceResult;
return data; // Ensure that the data is returned
} catch (error) {
console.error(
"Error fetching data from Google Place Details API:",
error
);
return { error: "Failed to fetch data from Google" }; // Return an error object instead of throwing
}
}),
});

// ChIJ2dGMjMMEdkgRqVqkuXQkj7c Big Ben
// ChIJN1t_tDeuEmsRUsoyG83frY4 Google Office Sydney
// ChIJj61dQgK6j4AR4GeTYWZsKWw from example on https://developers.google.com/maps/documentation/places/web-service/place-details
7 replies
TTCTheo's Typesafe Cult
Created by Circus on 12/9/2023 in #questions
Editable text that doesn't change CSS between <text>, <p>, <div>, etc. and <input> tags (tailwind)
Hi, does anyone have a good example of how to have a textbox that, when in an editable state, doesn't change CSS properties so that it looks like you're typing right into the existing text? I've been having lots of issues with formatting the <input> classNames (via tailwind) to match the properties correctly
2 replies
TTCTheo's Typesafe Cult
Created by Circus on 11/27/2023 in #questions
Clerk Webhooks with Prisma (Sync database, user model)
Hi, does anyone have a working example of how to sync user model via Prisma with Clerk? Clerk recommends using webhooks but the process has proven to be very tedious with little in the way of documentation. I know you can instead be sneaky and use the afterAuth middleware instead, so I'll take those examples as well.
30 replies
TTCTheo's Typesafe Cult
Created by Circus on 10/9/2023 in #questions
T3 - How to create a User record on Clerk signin (i.e. proper way of keeping track of user info)
Hello, is there a way to creat/upsert a User into a User schema when someone logs into your app via Clerk? I'm thinking of creating a User model with similar functionality of typical social media uses e.g. upvotes, likes, posts, etc. I know that with Clerk, people have said you can omit having a User model since you can make queries from your other models (e.g. showing all likes with the desired userId, showing all posts with the userId, etc.), but if you want to show several rows of different databases (posts, likes, etc), wouldn't it make more sense to have a User database so you can just run one query? I've been able to create a function that makes the user, but haven't seen how to run this on signing in, so there's the tedious process of having the user click a button or something else Open-ended question on what is best practice overall and how to best proceed with conventional T3 stack for this functionality- Prisma, Clerk, TRPC, Next
3 replies
TTCTheo's Typesafe Cult
Created by Circus on 10/3/2023 in #questions
Shadcn components don't work out of the box?
No description
8 replies
TTCTheo's Typesafe Cult
Created by Circus on 9/18/2023 in #questions
TRPC & Optimistic Update
No description
2 replies