1
mirror of https://github.com/jakejarvis/jarv.is.git synced 2025-07-03 12:46:38 -04:00

vercel analytics ➡️ umami

This commit is contained in:
2025-03-11 14:28:29 -04:00
parent fa54a4f978
commit 125a6932c2
17 changed files with 151 additions and 170 deletions

18
app/analytics.tsx Normal file
View File

@ -0,0 +1,18 @@
import Script from "next/script";
const Analytics = () => {
if (!process.env.NEXT_PUBLIC_UMAMI_WEBSITE_ID || process.env.NEXT_PUBLIC_VERCEL_ENV !== "production") {
return null;
}
return (
<Script
src="/_stream/u/script.js" // see next.config.ts rewrite
strategy="afterInteractive"
data-website-id={process.env.NEXT_PUBLIC_UMAMI_WEBSITE_ID}
data-domains={process.env.NEXT_PUBLIC_VERCEL_PROJECT_PRODUCTION_URL}
/>
);
};
export default Analytics;

View File

@ -27,7 +27,7 @@ export async function sendMessage(
// backup to client-side validations just in case someone squeezes through without them
if (!validatedFields.success) {
console.error("[contact form] validation error:", validatedFields.error.flatten());
console.debug("[contact form] validation error:", validatedFields.error.flatten());
return {
success: false,

View File

@ -1,5 +1,5 @@
import clsx from "clsx";
import { Analytics } from "@vercel/analytics/next";
import Analytics from "./analytics";
import { ThemeProvider } from "../contexts/ThemeContext";
import Header from "../components/Header";
import Footer from "../components/Footer";

View File

@ -32,7 +32,7 @@ A very simple hit counter on each blog post tallies an aggregate number of pagev
The [database schema](https://github.com/jakejarvis/jarv.is/blob/main/prisma/schema.prisma), [serverless function](https://github.com/jakejarvis/jarv.is/blob/main/app/api/hits/route.ts) and [client script](https://github.com/jakejarvis/jarv.is/blob/main/app/notes/%5Bslug%5D/counter.tsx) are open source, and [snapshots of the database](https://github.com/jakejarvis/website-stats) are public.
[**Vercel Analytics**](https://vercel.com/products/observability) is also used to gain insights into referrers, search terms, etc. [without collecting anything identifiable](https://vercel.com/docs/analytics/privacy-policy#data-point-information) about you.
A self-hosted [**Umami**](https://umami.is/) instance is also used to gain insights into referrers, search terms, etc. [without collecting anything identifiable](https://umami.is/blog/why-privacy-matters) about you. [The dashboard is even public!](/stats)
## Third-Party Content

View File

@ -42,7 +42,7 @@ type Project = {
async function getRepos(): Promise<Project[] | null> {
// don't fail the entire site build if the required API key for this page is missing
if (!process.env.GITHUB_TOKEN || process.env.GITHUB_TOKEN === "") {
if (!process.env.GITHUB_TOKEN) {
console.warn(`ERROR: I can't fetch any GitHub projects without "GITHUB_TOKEN" set! Skipping for now...`);
return null;

View File

@ -11,12 +11,13 @@ const sitemap = async (): Promise<MetadataRoute.Sitemap> => {
const routes: MetadataRoute.Sitemap = [
{
// homepage
url: `${config.baseUrl}/`,
url: config.baseUrl,
priority: 1.0,
lastModified: new Date(process.env.RELEASE_DATE || Date.now()), // timestamp frozen when a new build is deployed
},
{ url: `${config.baseUrl}/tweets/` },
{ url: `${config.baseUrl}/y2k/` },
{ url: `${config.baseUrl}/stats` },
{ url: `${config.baseUrl}/tweets` },
{ url: `${config.baseUrl}/y2k` },
];
// add each directory in the app folder as a route (excluding special routes)
@ -34,7 +35,7 @@ const sitemap = async (): Promise<MetadataRoute.Sitemap> => {
).forEach((route) => {
routes.push({
// remove matching page.(tsx|mdx) file and make all URLs absolute
url: `${config.baseUrl}/${route.replace(/page\.(tsx|mdx)$/, "")}`,
url: `${config.baseUrl}/${route.replace(/\/page\.(tsx|mdx)$/, "")}`,
});
});