nextjs-app-router-mastery — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited nextjs-app-router-mastery (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
'use client'app/
layout.tsx # Root layout (required)
page.tsx # Route UI
loading.tsx # Loading UI (Suspense boundary)
error.tsx # Error boundary
not-found.tsx # 404 UI
route.ts # API route handler
template.tsx # Re-renders on navigation
default.tsx # Parallel route fallback// app/posts/page.tsx - Server Component
async function PostsPage() {
const posts = await fetchPosts(); // Direct fetch, no useEffect
return <PostList posts={posts} />;
}async function Dashboard() {
// Parallel fetches - don't await sequentially
const [user, posts, analytics] = await Promise.all([
fetchUser(),
fetchPosts(),
fetchAnalytics(),
]);
return <DashboardView user={user} posts={posts} analytics={analytics} />;
}export default function Page() {
return (
<div>
<h1>Dashboard</h1>
<Suspense fallback={<StatsSkeleton />}>
<Stats /> {/* Async component */}
</Suspense>
<Suspense fallback={<ChartSkeleton />}>
<Chart /> {/* Streams in when ready */}
</Suspense>
</div>
);
}// app/actions.ts
'use server';
import { revalidatePath } from 'next/cache';
export async function createPost(formData: FormData) {
const title = formData.get('title') as string;
await db.posts.create({ data: { title } });
revalidatePath('/posts');
}// app/api/posts/route.ts
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
const posts = await fetchPosts();
return NextResponse.json(posts);
}
export async function POST(request: Request) {
const body = await request.json();
const post = await createPost(body);
return NextResponse.json(post, { status: 201 });
}// Force dynamic rendering
export const dynamic = 'force-dynamic';
// Revalidate every 60 seconds
export const revalidate = 60;
// Static generation
export const dynamic = 'force-static';
// Per-fetch revalidation
fetch(url, { next: { revalidate: 3600 } });
// On-demand revalidation
revalidatePath('/posts');
revalidateTag('posts');// Static metadata
export const metadata: Metadata = {
title: 'My App',
description: 'App description',
};
// Dynamic metadata
export async function generateMetadata({ params }): Promise<Metadata> {
const post = await fetchPost(params.id);
return { title: post.title };
}loading.tsx for route-level loading states(group) for organization without affecting URL~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.