Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
"contenido",
"controlado",
"copypaste",
"CPA",
"cpa",
"cpath",
"crect",
"cspell",
Expand Down Expand Up @@ -66,8 +68,13 @@
"PKGBUILD",
"preconfigured",
"pydantic",
"pygobject",
"PyPI",
"pypi",
"pyproject",
"pyright",
"pytest",
"pywal",
"radix",
"Reakit",
"recharts",
Expand All @@ -86,13 +93,15 @@
"transpiling",
"trivy",
"trufflehog",
"turborepo",
"Turborepo",
"turborepo",
"typer",
"ulises",
"ulisesjeremias",
"unmemoized",
"unvetted",
"uvicorn",
"uvx",
"vaul",
"vercel",
"vite",
Expand All @@ -101,15 +110,16 @@
"Vlang",
"webextension",
"workdir",
"wpgtk",
"wscript"
],
"ignorePaths": [
"node_modules/**",
"**/*.svg",
".next/**",
"pnpm-lock.yaml",
"megalinter-reports/**",
"node_modules/**",
"pnpm-lock.yaml",
"public/**",
"**/*.svg",
"tools/danger/package-lock.json"
]
}
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
blank_issues_enabled: false
contact_links:
- name: 💬 General Question
url: https://github.com/Create-Node-App/create-node-app/discussions/categories/q-a
url: https://github.com/Create-Python-App/create-python-app/discussions/categories/q-a
about: Please ask and answer questions as a discussion thread
10 changes: 5 additions & 5 deletions src/app/extensions/[slug]/ExtensionDetailsClient.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export function ExtensionDetailsClient({ extension, compatibleTemplates }: Exten
</h3>
<p>To use this extension with a compatible template, run the following command:</p>
<div className="bg-muted rounded-md p-4 font-mono text-sm overflow-x-auto shimmer">
<p>npx create-awesome-node-app --template [template-name] --addons {extension.slug}</p>
<p>uvx create-awesome-python-app --template [template-name] --addons {extension.slug}</p>
</div>
<h3 className="text-transparent bg-clip-text bg-gradient-to-r from-teal-600 to-amber-500">
With Specific Templates
Expand All @@ -123,7 +123,7 @@ export function ExtensionDetailsClient({ extension, compatibleTemplates }: Exten
className="bg-muted rounded-md p-4 font-mono text-sm overflow-x-auto shimmer mb-4"
>
<p>
npx create-awesome-node-app --template {template.slug} --addons {extension.slug}
uvx create-awesome-python-app --template {template.slug} --addons {extension.slug}
</p>
</div>
))}
Expand Down Expand Up @@ -178,15 +178,15 @@ export function ExtensionDetailsClient({ extension, compatibleTemplates }: Exten
</CardHeader>
<CardContent>
<div className="bg-muted rounded-md p-4 font-mono text-sm overflow-x-auto mb-4">
<p className="text-green-500">$ npx create-awesome-node-app \\</p>
<p className="text-green-500">$ uvx create-awesome-python-app \\</p>
<p className="pl-4">--template [template-name] \\</p>
<p className="pl-4">--addons {extension.slug}</p>
</div>
</CardContent>
<CardFooter className="flex flex-col items-start gap-4">
<CopyButton
className="w-full bg-gradient-to-r from-teal-600 to-amber-500 hover:from-teal-600/90 hover:to-amber-500/90 glow transition-all duration-300"
command={`npx create-awesome-node-app --template [template-name] --addons ${extension.slug}`}
command={`uvx create-awesome-python-app --template [template-name] --addons ${extension.slug}`}
/>
<Link href={extension.url} className="w-full" target="_blank" rel="noopener noreferrer">
<Button
Expand Down Expand Up @@ -301,7 +301,7 @@ export function ExtensionDetailsClient({ extension, compatibleTemplates }: Exten
className="bg-gradient-to-r from-teal-600 to-amber-500 hover:from-teal-600/90 hover:to-amber-500/90 glow transition-all duration-300"
onClick={() => {
navigator.clipboard?.writeText?.(
`npx create-awesome-node-app --template [template-name] --addons ${extension.slug}`,
`uvx create-awesome-python-app --template [template-name] --addons ${extension.slug}`,
);
}}
>
Expand Down
28 changes: 15 additions & 13 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,25 @@ import { Button } from '@/components/ui/button';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card';
import { getTemplatesData } from '@/lib/data';

const PRIMARY_COMMAND = 'npm create awesome-node-app@latest my-app';
const PRIMARY_COMMAND = 'uvx create-awesome-python-app my-app';

export default async function Home() {
const { templates, categories } = await getTemplatesData();

const saasTemplate = templates.find((t) => t.slug === 'nextjs-saas-ai-starter');
const otherTemplates = templates.filter((t) => t.slug !== 'nextjs-saas-ai-starter');
const featuredTemplates = saasTemplate ? [saasTemplate, ...otherTemplates].slice(0, 3) : templates.slice(0, 3);
const flagshipTemplate = templates.find((t) => t.slug === 'fastapi-starter');
const otherTemplates = templates.filter((t) => t.slug !== 'fastapi-starter');
const featuredTemplates = flagshipTemplate
? [flagshipTemplate, ...otherTemplates].slice(0, 3)
: templates.slice(0, 3);

return (
<div className="flex min-h-screen flex-col">
<main className="flex-1">
<AnnouncementBanner
message={
<>New: Next.js SaaS AI Starter — multi-tenant SaaS with AI, Auth.js v5, Drizzle + pgvector, and more.</>
<>New: FastAPI Starter — production-ready API with uv, Ruff, pytest, and composable Python extensions.</>
}
ctaHref="/templates/nextjs-saas-ai-starter"
ctaHref="/templates/fastapi-starter"
ctaLabel="Explore template"
/>
<HeroSection
Expand All @@ -43,7 +45,7 @@ export default async function Home() {
<span className="text-gradient-primary animate-gradient-text">in one command.</span>
</>
}
description="Choose a template, add addons, and ship a production-ready Node, Web, or AI-ready app from a cozy developer workbench."
description="Choose a template, add extensions, and ship a production-ready FastAPI, Django, Celery, or CLI app from a cozy developer workbench."
actions={
<>
<CopyButton
Expand Down Expand Up @@ -82,7 +84,7 @@ export default async function Home() {
Start with a solid foundation
</h2>
<p className="max-w-[900px] text-muted-foreground md:text-xl/relaxed">
Curated starters for frontend, full-stack, and SaaS — not a dump of every option.
Curated starters for APIs, workers, CLIs, and uv workspaces — not a dump of every option.
</p>
</div>
</div>
Expand Down Expand Up @@ -183,19 +185,19 @@ export default async function Home() {
</CardHeader>
<CardContent className="space-y-3">
<div className="bg-muted rounded-md p-4 font-mono text-sm overflow-x-auto">
<p className="text-teal-700 dark:text-teal-300">$ npm create awesome-node-app@latest my-app \</p>
<p className="pl-4">--template react-vite-boilerplate \</p>
<p className="pl-4">--addons tailwind-css zustand github-setup</p>
<p className="text-teal-700 dark:text-teal-300">$ uvx create-awesome-python-app my-app \</p>
<p className="pl-4">--template fastapi-starter \</p>
<p className="pl-4">--addons python-docker github-setup</p>
</div>
<CopyButton
command="npm create awesome-node-app@latest my-app -- --template react-vite-boilerplate --addons tailwind-css zustand github-setup --no-interactive"
command="uvx create-awesome-python-app my-app --template fastapi-starter --addons python-docker github-setup --no-interactive"
variant="outline"
className="w-full"
/>
</CardContent>
<CardFooter>
<p className="text-sm text-muted-foreground">
Generates a React app with Tailwind, Zustand, GitHub setup, and AI-ready conventions when enabled.
Generates a FastAPI app with uv tooling, Docker packaging, and GitHub Actions setup.
</p>
</CardFooter>
</Card>
Expand Down
52 changes: 28 additions & 24 deletions src/app/templates/[slug]/TemplateDetailsClient.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@ import type { Extension, Template } from '@/lib/schemas';

function getTemplateIcon(type: string) {
switch (type) {
case 'react':
case 'vue':
return <Code className="h-6 w-6 text-primary" />;
case 'nestjs':
case 'express':
case 'fastapi-backend':
return <Server className="h-6 w-6 text-primary" />;
case 'django-backend':
return <Code className="h-6 w-6 text-primary" />;
case 'cli-app':
return <Code className="h-6 w-6 text-primary" />;
case 'celery-worker':
return <Package className="h-6 w-6 text-primary" />;
case 'uv-workspace':
return <Package className="h-6 w-6 text-primary" />;
default:
return <Package className="h-6 w-6 text-primary" />;
}
Expand Down Expand Up @@ -112,11 +116,11 @@ export function TemplateDetailsClient({ template, compatibleExtensions }: Templa
Key Benefits
</h3>
<ul>
<li>Pre-configured development environment</li>
<li>Modern tooling and best practices</li>
<li>TypeScript support out of the box</li>
<li>Linting and formatting setup</li>
<li>Testing infrastructure ready to go</li>
<li>Pre-configured uv project with lockfile workflow</li>
<li>Ruff, pytest, and type checking out of the box</li>
<li>Python 3.12+ with modern typing patterns</li>
<li>AGENTS.md for AI assistant guardrails</li>
<li>Extension-ready structure for Docker, Postgres, and CI</li>
</ul>
</div>
</TabsContent>
Expand All @@ -127,15 +131,15 @@ export function TemplateDetailsClient({ template, compatibleExtensions }: Templa
</h3>
<p>To use this template, run the following command:</p>
<div className="bg-muted rounded-md p-4 font-mono text-sm overflow-x-auto shimmer">
<p>npx create-awesome-node-app --template {template.slug}</p>
<p>uvx create-awesome-python-app --template {template.slug}</p>
</div>
<h3 className="text-transparent bg-clip-text bg-gradient-to-r from-primary to-teal-600">
With Extensions
</h3>
<p>You can also add extensions to enhance your template:</p>
<div className="bg-muted rounded-md p-4 font-mono text-sm overflow-x-auto shimmer">
<p>
npx create-awesome-node-app --template {template.slug} --addons{' '}
uvx create-awesome-python-app --template {template.slug} --addons{' '}
{compatibleExtensions.length >= 2
? `${compatibleExtensions[0].slug} ${compatibleExtensions[1].slug}`
: compatibleExtensions.length === 1
Expand All @@ -153,20 +157,20 @@ export function TemplateDetailsClient({ template, compatibleExtensions }: Templa
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 not-prose mt-4">
{[
{
title: 'TypeScript Support',
desc: 'Full TypeScript integration with properly configured tsconfig.',
title: 'uv & pyproject.toml',
desc: 'Dependencies and scripts managed with uv and a single pyproject.toml.',
},
{
title: 'Modern Tooling',
desc: 'ESLint, Prettier, and other tools preconfigured for code quality.',
title: 'Quality tooling',
desc: 'Ruff, pytest, and mypy/pyright preconfigured for Python 3.12+.',
},
{
title: 'Testing Setup',
desc: 'Testing framework and utilities ready for unit and integration tests.',
title: 'Testing setup',
desc: 'pytest fixtures and examples ready for unit and integration tests.',
},
{
title: 'Optimized Build',
desc: 'Production-ready build configuration for optimal performance.',
title: 'Production patterns',
desc: 'Settings, health checks, and extension hooks aligned with CPA best practices.',
},
].map((f) => (
<Card key={f.title} className="bg-background/50 backdrop-blur-sm border-primary/10">
Expand Down Expand Up @@ -194,14 +198,14 @@ export function TemplateDetailsClient({ template, compatibleExtensions }: Templa
</CardHeader>
<CardContent>
<div className="bg-muted rounded-md p-4 font-mono text-sm overflow-x-auto mb-4">
<p className="text-green-500">$ npx create-awesome-node-app \</p>
<p className="text-green-500">$ uvx create-awesome-python-app \</p>
<p className="pl-4">--template {template.slug}</p>
</div>
</CardContent>
<CardFooter className="flex flex-col items-start gap-4">
<CopyButton
className="w-full bg-gradient-to-r from-primary to-teal-600 hover:from-primary/90 hover:to-teal-600/90 glow transition-all duration-300"
command={`npx create-awesome-node-app --template ${template.slug}`}
command={`uvx create-awesome-python-app --template ${template.slug}`}
/>
<Link href={template.url} className="w-full" target="_blank" rel="noopener noreferrer">
<Button
Expand Down Expand Up @@ -332,15 +336,15 @@ export function TemplateDetailsClient({ template, compatibleExtensions }: Templa
Ready to Build?
</h2>
<p className="max-w-[900px] text-muted-foreground md:text-xl/relaxed lg:text-base/relaxed xl:text-xl/relaxed">
Start creating your awesome Node.js app with this template
Start creating your awesome Python app with this template
</p>
</div>
<div className="flex flex-col gap-2 min-[400px]:flex-row">
<Button
size="lg"
className="bg-gradient-to-r from-primary to-teal-600 hover:from-primary/90 hover:to-teal-600/90 glow transition-all duration-300"
onClick={() => {
navigator.clipboard?.writeText?.(`npx create-awesome-node-app --template ${template.slug}`);
navigator.clipboard?.writeText?.(`uvx create-awesome-python-app --template ${template.slug}`);
}}
>
Get Started
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ export default function TemplateExtensionPage({

<div className="bg-muted rounded-md p-4 font-mono text-sm overflow-x-auto shimmer">
<p>
<span className="text-green-500">$ npx create-awesome-node-app</span>{' '}
<span className="text-green-500">$ uvx create-awesome-python-app</span>{' '}
<span className="break-all">--template {template.slug}</span>{' '}
<span className="break-all">--addons {extension.slug}</span>
</p>
Expand Down Expand Up @@ -292,7 +292,7 @@ export default function TemplateExtensionPage({
<CardContent>
<div className="bg-muted rounded-md p-4 font-mono text-sm overflow-x-auto mb-4">
<p>
<span className="text-green-500">$ npx create-awesome-node-app</span>{' '}
<span className="text-green-500">$ uvx create-awesome-python-app</span>{' '}
<span className="break-all">--template {template.slug}</span>{' '}
<span className="break-all">--addons {extension.slug}</span>
</p>
Expand All @@ -301,7 +301,7 @@ export default function TemplateExtensionPage({
<CardFooter className="flex flex-col items-start gap-4">
<CopyButton
className="w-full bg-gradient-to-r from-primary via-teal-600 to-amber-500 hover:from-primary/90 hover:via-teal-600/90 hover:to-amber-500/90 glow transition-all duration-300"
command={`npx create-awesome-node-app --template ${template.slug} --addons ${extension.slug}`}
command={`uvx create-awesome-python-app --template ${template.slug} --addons ${extension.slug}`}
/>
<div className="flex w-full gap-2">
<Link href={template.url} className="flex-1" target="_blank">
Expand Down Expand Up @@ -401,7 +401,7 @@ export default function TemplateExtensionPage({
<div className="flex flex-col gap-2 min-[400px]:flex-row">
<CopyButton
className="bg-gradient-to-r from-primary via-teal-600 to-amber-500 hover:from-primary/90 hover:via-teal-600/90 hover:to-amber-500/90 glow transition-all duration-300"
command={`npx create-awesome-node-app --template ${template.slug} --addons ${extension.slug}`}
command={`uvx create-awesome-python-app --template ${template.slug} --addons ${extension.slug}`}
size="lg"
/>
<Button
Expand Down
Loading
Loading