create-caspian-app 0.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. create_caspian_app-0.0.1/.gitignore +8 -0
  2. create_caspian_app-0.0.1/CHANGELOG.md +12 -0
  3. create_caspian_app-0.0.1/CONTRIBUTING.md +62 -0
  4. create_caspian_app-0.0.1/LICENSE +21 -0
  5. create_caspian_app-0.0.1/PKG-INFO +116 -0
  6. create_caspian_app-0.0.1/README.md +94 -0
  7. create_caspian_app-0.0.1/pyproject.toml +55 -0
  8. create_caspian_app-0.0.1/scripts/sync_template.py +272 -0
  9. create_caspian_app-0.0.1/src/create_caspian_app/__init__.py +5 -0
  10. create_caspian_app-0.0.1/src/create_caspian_app/__main__.py +5 -0
  11. create_caspian_app-0.0.1/src/create_caspian_app/casp.py +74 -0
  12. create_caspian_app-0.0.1/src/create_caspian_app/cli.py +192 -0
  13. create_caspian_app-0.0.1/src/create_caspian_app/envfile.py +185 -0
  14. create_caspian_app-0.0.1/src/create_caspian_app/features.py +87 -0
  15. create_caspian_app-0.0.1/src/create_caspian_app/installer.py +106 -0
  16. create_caspian_app-0.0.1/src/create_caspian_app/scaffold.py +319 -0
  17. create_caspian_app-0.0.1/src/create_caspian_app/template/.claude/settings.json +3 -0
  18. create_caspian_app-0.0.1/src/create_caspian_app/template/.github/copilot-instructions.md +169 -0
  19. create_caspian_app-0.0.1/src/create_caspian_app/template/.github/instructions/database-generation.instructions.md +47 -0
  20. create_caspian_app-0.0.1/src/create_caspian_app/template/.github/instructions/tailwind-build.instructions.md +20 -0
  21. create_caspian_app-0.0.1/src/create_caspian_app/template/.python-version +1 -0
  22. create_caspian_app-0.0.1/src/create_caspian_app/template/AGENTS.md +455 -0
  23. create_caspian_app-0.0.1/src/create_caspian_app/template/CLAUDE.md +1 -0
  24. create_caspian_app-0.0.1/src/create_caspian_app/template/README.md +63 -0
  25. create_caspian_app-0.0.1/src/create_caspian_app/template/_gitignore +32 -0
  26. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/README.md +24 -0
  27. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/agent-development.md +22 -0
  28. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/ai-validation-checklist.md +116 -0
  29. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/auth.md +793 -0
  30. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/authorization.md +127 -0
  31. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/background-jobs.md +139 -0
  32. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/cache.md +71 -0
  33. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/commands.md +86 -0
  34. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/components.md +820 -0
  35. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/core-runtime-map.md +192 -0
  36. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/database.md +427 -0
  37. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/environment.md +205 -0
  38. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/error-handling.md +127 -0
  39. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/fetch-data.md +536 -0
  40. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/file-conventions.md +315 -0
  41. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/file-uploads.md +219 -0
  42. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/i18n.md +134 -0
  43. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/index.md +161 -0
  44. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/installation.md +29 -0
  45. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/maintenance.md +88 -0
  46. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/mcp.md +60 -0
  47. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/metadata.md +319 -0
  48. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/observability.md +116 -0
  49. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/prepared-pages.md +115 -0
  50. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/project-structure.md +418 -0
  51. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/pulsepoint-runtime-map.md +207 -0
  52. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/pulsepoint.md +2019 -0
  53. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/request-pipeline.md +108 -0
  54. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/routing.md +597 -0
  55. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/state.md +278 -0
  56. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/static-export.md +112 -0
  57. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/task-scheduling.md +80 -0
  58. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/testing.md +324 -0
  59. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/validation.md +370 -0
  60. create_caspian_app-0.0.1/src/create_caspian_app/template/docs/caspian/websockets.md +226 -0
  61. create_caspian_app-0.0.1/src/create_caspian_app/template/main.py +2198 -0
  62. create_caspian_app-0.0.1/src/create_caspian_app/template/prisma/migrations/20260930065337/migration.sql +31 -0
  63. create_caspian_app-0.0.1/src/create_caspian_app/template/prisma/migrations/migration_lock.toml +3 -0
  64. create_caspian_app-0.0.1/src/create_caspian_app/template/prisma/schema.prisma +26 -0
  65. create_caspian_app-0.0.1/src/create_caspian_app/template/prisma/seed.py +40 -0
  66. create_caspian_app-0.0.1/src/create_caspian_app/template/public/css/styles.css +964 -0
  67. create_caspian_app-0.0.1/src/create_caspian_app/template/public/favicon.ico +0 -0
  68. create_caspian_app-0.0.1/src/create_caspian_app/template/public/js/bundle-mjs.mjs.map +1 -0
  69. create_caspian_app-0.0.1/src/create_caspian_app/template/public/js/main.js +16 -0
  70. create_caspian_app-0.0.1/src/create_caspian_app/template/public/js/pp-reactive-v2.min.js +49 -0
  71. create_caspian_app-0.0.1/src/create_caspian_app/template/public/js/tailwind-merge.mjs +3368 -0
  72. create_caspian_app-0.0.1/src/create_caspian_app/template/pyproject.toml +73 -0
  73. create_caspian_app-0.0.1/src/create_caspian_app/template/settings/_component_imports.py +71 -0
  74. create_caspian_app-0.0.1/src/create_caspian_app/template/settings/_markup_equivalence.py +867 -0
  75. create_caspian_app-0.0.1/src/create_caspian_app/template/settings/browser_log.py +526 -0
  76. create_caspian_app-0.0.1/src/create_caspian_app/template/settings/build-static.py +307 -0
  77. create_caspian_app-0.0.1/src/create_caspian_app/template/settings/build.py +49 -0
  78. create_caspian_app-0.0.1/src/create_caspian_app/template/settings/build_pages.py +26 -0
  79. create_caspian_app-0.0.1/src/create_caspian_app/template/settings/check_templates.py +497 -0
  80. create_caspian_app-0.0.1/src/create_caspian_app/template/settings/dev_log_bridge.py +387 -0
  81. create_caspian_app-0.0.1/src/create_caspian_app/template/settings/discovery.py +58 -0
  82. create_caspian_app-0.0.1/src/create_caspian_app/template/settings/fix.py +113 -0
  83. create_caspian_app-0.0.1/src/create_caspian_app/template/settings/format.py +719 -0
  84. create_caspian_app-0.0.1/src/create_caspian_app/template/settings/page_cache.py +62 -0
  85. create_caspian_app-0.0.1/src/create_caspian_app/template/settings/prepare.py +195 -0
  86. create_caspian_app-0.0.1/src/create_caspian_app/template/settings/prepared_pages.py +360 -0
  87. create_caspian_app-0.0.1/src/create_caspian_app/template/settings/python_server.py +159 -0
  88. create_caspian_app-0.0.1/src/create_caspian_app/template/settings/serve-static.py +187 -0
  89. create_caspian_app-0.0.1/src/create_caspian_app/template/settings/serve_mcp.py +30 -0
  90. create_caspian_app-0.0.1/src/create_caspian_app/template/settings/tailwind-tool.json +13 -0
  91. create_caspian_app-0.0.1/src/create_caspian_app/template/settings/tailwind.py +298 -0
  92. create_caspian_app-0.0.1/src/create_caspian_app/template/settings/test.py +419 -0
  93. create_caspian_app-0.0.1/src/create_caspian_app/template/src/app/error.py +94 -0
  94. create_caspian_app-0.0.1/src/create_caspian_app/template/src/app/globals.css +34 -0
  95. create_caspian_app-0.0.1/src/create_caspian_app/template/src/app/index.py +99 -0
  96. create_caspian_app-0.0.1/src/create_caspian_app/template/src/app/layout.py +43 -0
  97. create_caspian_app-0.0.1/src/create_caspian_app/template/src/app/not_found.py +28 -0
  98. create_caspian_app-0.0.1/src/create_caspian_app/template/src/lib/auth/auth_config.py +46 -0
  99. create_caspian_app-0.0.1/src/create_caspian_app/template/src/lib/mcp/fastmcp.json +15 -0
  100. create_caspian_app-0.0.1/src/create_caspian_app/template/src/lib/mcp/mcp_server.py +93 -0
  101. create_caspian_app-0.0.1/src/create_caspian_app/template/src/lib/prisma/__init__.py +43 -0
  102. create_caspian_app-0.0.1/src/create_caspian_app/template/src/lib/prisma/db.py +10289 -0
  103. create_caspian_app-0.0.1/src/create_caspian_app/template/src/lib/prisma/models.py +585 -0
  104. create_caspian_app-0.0.1/src/create_caspian_app/template/src/lib/websocket/sockets.py +873 -0
  105. create_caspian_app-0.0.1/src/create_caspian_app/template/tests/README.md +63 -0
  106. create_caspian_app-0.0.1/src/create_caspian_app/template/tests/conftest.py +156 -0
  107. create_caspian_app-0.0.1/src/create_caspian_app/template/tests/test_app.py +48 -0
  108. create_caspian_app-0.0.1/src/create_caspian_app/template/uv.lock +1896 -0
  109. create_caspian_app-0.0.1/src/create_caspian_app/ui.py +101 -0
  110. create_caspian_app-0.0.1/template_overrides/docs/caspian/testing.md +324 -0
  111. create_caspian_app-0.0.1/template_overrides/tests/README.md +63 -0
  112. create_caspian_app-0.0.1/template_overrides/tests/conftest.py +156 -0
  113. create_caspian_app-0.0.1/template_overrides/tests/test_app.py +48 -0
  114. create_caspian_app-0.0.1/tests/test_scaffold.py +306 -0
@@ -0,0 +1,8 @@
1
+ .venv/
2
+ __pycache__/
3
+ *.py[cod]
4
+ dist/
5
+ build/
6
+ *.egg-info/
7
+ .pytest_cache/
8
+ .ruff_cache/
@@ -0,0 +1,12 @@
1
+ # Changelog
2
+
3
+ ## 0.0.1 — Alpha
4
+
5
+ Initial release of the Caspian Python app generator.
6
+
7
+ - Create apps with the `create-caspian-app` command and a bundled starter template.
8
+ - Choose backend-only apps, Tailwind CSS, MCP, Prisma, and WebSocket support.
9
+ - Generate environment files with fresh secrets for each project.
10
+ - Update existing apps with `casp update project`, preserving managed user files
11
+ and configured exclusions.
12
+ - Include starter app tests and development guides.
@@ -0,0 +1,62 @@
1
+ # Maintaining create-caspian-app
2
+
3
+ Use Python 3.14 for package development and release checks.
4
+
5
+
6
+ The app template comes from the Caspian starter repository
7
+ (`create-caspian-app-python`) and is bundled inside the wheel, so creating an app
8
+ works offline and each release always installs the same files.
9
+
10
+ ```bash
11
+ uv run python scripts/sync_template.py # copy git-tracked files from ../create-caspian-app-python
12
+ uv run python scripts/sync_template.py --check # fail if the bundled template is stale
13
+ uv run pytest # installer tests
14
+ uv run ruff check src/create_caspian_app tests scripts
15
+ uv build # dist/*.whl + dist/*.tar.gz
16
+ uvx twine check --strict dist/create_caspian_app-0.0.1-py3-none-any.whl dist/create_caspian_app-0.0.1.tar.gz
17
+ ```
18
+
19
+ ### Publish 0.0.1
20
+
21
+ The version comes from `src/create_caspian_app/__init__.py`; the package metadata
22
+ marks its development status as Alpha. The exact version is `0.0.1`, so package
23
+ installers treat it as a normal release. A version such as `0.0.1a1` would instead
24
+ be an alpha prerelease under Python's versioning rules.
25
+
26
+ After the checks above pass, upload the two verified artifacts:
27
+
28
+ ```bash
29
+ uv publish dist/create_caspian_app-0.0.1-py3-none-any.whl dist/create_caspian_app-0.0.1.tar.gz
30
+ ```
31
+
32
+ Provide a PyPI API token through `UV_PUBLISH_TOKEN` in your shell or CI secret
33
+ store. Never commit the token. PyPI does not allow replacing an uploaded release
34
+ file; use a new version for subsequent changes.
35
+
36
+ To rehearse on TestPyPI, use a separate TestPyPI token and upload endpoint:
37
+
38
+ ```bash
39
+ uv publish --publish-url https://test.pypi.org/legacy/ dist/create_caspian_app-0.0.1-py3-none-any.whl dist/create_caspian_app-0.0.1.tar.gz
40
+ ```
41
+
42
+ Only files tracked by git in the source repo get copied. `.venv/`, `caspian.config.json`,
43
+ `.env`, and bytecode are always left out. The source repo is also the framework's
44
+ development workspace, so the sync also leaves out its demo pages, benchmarks,
45
+ and the framework's own test suite (`DEVELOPMENT_ONLY` in
46
+ `scripts/sync_template.py`), and applies small checked text edits (`EDITS`). When the
47
+ source changes so that one of those edits no longer applies, the sync stops with an error,
48
+ so development content never ships silently.
49
+
50
+ `template_overrides/` holds the files this package owns, which are added to (or replace
51
+ files in) the template:
52
+
53
+ - `tests/conftest.py`: the app test fixtures (`client`, `rpc`, `csrf_headers`, `sign_in`,
54
+ `config`) and the `feature(...)` / `frontend` markers.
55
+ - `tests/test_app.py`: starter tests for the app shell.
56
+ - `tests/README.md`: the gate, formatting, and test commands.
57
+ - `docs/caspian/testing.md`: the testing guide AI agents follow ("what to test for each
58
+ change", with a recipe for each surface).
59
+
60
+ Edit those files here, not in the source repo, then run the sync. Every code block in the
61
+ Recipes section of `testing.md` was run against a generated app. If you change a recipe,
62
+ check it the same way.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jefferson Abraham Omier
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,116 @@
1
+ Metadata-Version: 2.5
2
+ Name: create-caspian-app
3
+ Version: 0.0.1
4
+ Summary: Create Caspian apps: a high-performance Python web framework (FastAPI + PulsePoint).
5
+ Project-URL: Homepage, https://caspian.tsnc.tech/
6
+ Project-URL: Repository, https://github.com/TheSteelNinjaCode/create-caspian-app
7
+ Author-email: Jefferson Abraham Omier <thesteelninjacode@gmail.com>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Keywords: boilerplate,caspian,create-app,fastapi,mcp,python,scaffold,tailwindcss
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Environment :: Console
13
+ Classifier: Framework :: FastAPI
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.14
18
+ Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
19
+ Classifier: Topic :: Software Development :: Code Generators
20
+ Requires-Python: >=3.14
21
+ Description-Content-Type: text/markdown
22
+
23
+ # create-caspian-app
24
+
25
+ Create a new [Caspian](https://caspian.tsnc.tech/) app, a high-performance Python web
26
+ framework built on FastAPI and the PulsePoint browser runtime.
27
+
28
+ The installer and application tooling use Python.
29
+
30
+ Version **0.0.1** is the initial **alpha** release. APIs and generated project
31
+ structure may change as Caspian develops.
32
+
33
+ ## Create an app
34
+
35
+ With [uv](https://docs.astral.sh/uv/) (recommended, nothing to install first):
36
+
37
+ ```bash
38
+ uvx create-caspian-app my-app
39
+ ```
40
+
41
+ Or install the command once:
42
+
43
+ ```bash
44
+ uv tool install create-caspian-app # or: pipx install create-caspian-app
45
+ create-caspian-app my-app
46
+ ```
47
+
48
+ You'll be asked which features you want:
49
+
50
+ ```
51
+ ? What is your project named? (my-app)
52
+ ? Would you like to use Tailwind CSS? y/N
53
+ ? Would you like to use MCP (Model Context Protocol)? y/N
54
+ ? Would you like to use Prisma ORM (Caspian DB)? y/N
55
+ ? Would you like to use WebSocket? y/N
56
+ ```
57
+
58
+ The installer writes the project, generates a `.env` with fresh secrets, runs
59
+ `uv sync --group dev`, and builds the CSS. When Tailwind is on, it also downloads the
60
+ pinned, checksum-verified Tailwind standalone compiler. Then:
61
+
62
+ ```bash
63
+ cd my-app
64
+ uv run python main.py
65
+ ```
66
+
67
+ ### Skip the questions
68
+
69
+ Pass flags and `-y`. Only the flags you pass are turned on:
70
+
71
+ ```bash
72
+ uvx create-caspian-app my-app --tailwindcss --mcp --prisma --websocket -y
73
+ uvx create-caspian-app my-app --prisma --websocket -y
74
+ ```
75
+
76
+ | Flag | Feature |
77
+ | ---------------- | -------------------------------------------------------------- |
78
+ | `--tailwindcss` | Tailwind CSS v4 via the standalone compiler |
79
+ | `--mcp` | MCP server mounted in FastAPI (`src/lib/mcp`) |
80
+ | `--prisma` | Caspian DB: `prisma/schema.prisma` + generated Python client |
81
+ | `--websocket` | Named sockets (`src/lib/websocket`) |
82
+ | `--skip-install` | Write files only; skip `uv sync` and the CSS build |
83
+ | `-y` | No prompts |
84
+
85
+ ## Update an existing app
86
+
87
+ Run this from the project folder:
88
+
89
+ ```bash
90
+ uvx --from create-caspian-app casp update project # latest
91
+ uvx --from create-caspian-app casp update project 0.0.1 # a specific version
92
+ ```
93
+
94
+ Running `create-caspian-app <name>` inside a folder that has a `caspian.config.json`
95
+ does the same. The update refreshes the Caspian template files and asks about any
96
+ features that aren't enabled yet. It removes the files of features you turn off and
97
+ re-pins the managed dependencies.
98
+
99
+ An update never overwrites:
100
+
101
+ - `.env`
102
+ - `pyproject.toml` (only the managed requirements are re-pinned, with `uv add` / `uv remove`)
103
+ - `uv.lock`
104
+ - `src/app/globals.css` (only the Tailwind directives are added or removed)
105
+ - `prisma/`
106
+ - any path listed in `caspian.config.json` → `"excludeFiles"`
107
+
108
+ Everything else that comes from the template, such as `src/app/index.py`, gets
109
+ overwritten. Add the files you've customized to `excludeFiles` first.
110
+
111
+ ## Requirements
112
+
113
+ - Python 3.14+ for the installer and generated apps. uv can download Python 3.14
114
+ if it is missing.
115
+ - [uv](https://docs.astral.sh/uv/). If it's missing, the installer tries
116
+ `python -m pip install uv`.
@@ -0,0 +1,94 @@
1
+ # create-caspian-app
2
+
3
+ Create a new [Caspian](https://caspian.tsnc.tech/) app, a high-performance Python web
4
+ framework built on FastAPI and the PulsePoint browser runtime.
5
+
6
+ The installer and application tooling use Python.
7
+
8
+ Version **0.0.1** is the initial **alpha** release. APIs and generated project
9
+ structure may change as Caspian develops.
10
+
11
+ ## Create an app
12
+
13
+ With [uv](https://docs.astral.sh/uv/) (recommended, nothing to install first):
14
+
15
+ ```bash
16
+ uvx create-caspian-app my-app
17
+ ```
18
+
19
+ Or install the command once:
20
+
21
+ ```bash
22
+ uv tool install create-caspian-app # or: pipx install create-caspian-app
23
+ create-caspian-app my-app
24
+ ```
25
+
26
+ You'll be asked which features you want:
27
+
28
+ ```
29
+ ? What is your project named? (my-app)
30
+ ? Would you like to use Tailwind CSS? y/N
31
+ ? Would you like to use MCP (Model Context Protocol)? y/N
32
+ ? Would you like to use Prisma ORM (Caspian DB)? y/N
33
+ ? Would you like to use WebSocket? y/N
34
+ ```
35
+
36
+ The installer writes the project, generates a `.env` with fresh secrets, runs
37
+ `uv sync --group dev`, and builds the CSS. When Tailwind is on, it also downloads the
38
+ pinned, checksum-verified Tailwind standalone compiler. Then:
39
+
40
+ ```bash
41
+ cd my-app
42
+ uv run python main.py
43
+ ```
44
+
45
+ ### Skip the questions
46
+
47
+ Pass flags and `-y`. Only the flags you pass are turned on:
48
+
49
+ ```bash
50
+ uvx create-caspian-app my-app --tailwindcss --mcp --prisma --websocket -y
51
+ uvx create-caspian-app my-app --prisma --websocket -y
52
+ ```
53
+
54
+ | Flag | Feature |
55
+ | ---------------- | -------------------------------------------------------------- |
56
+ | `--tailwindcss` | Tailwind CSS v4 via the standalone compiler |
57
+ | `--mcp` | MCP server mounted in FastAPI (`src/lib/mcp`) |
58
+ | `--prisma` | Caspian DB: `prisma/schema.prisma` + generated Python client |
59
+ | `--websocket` | Named sockets (`src/lib/websocket`) |
60
+ | `--skip-install` | Write files only; skip `uv sync` and the CSS build |
61
+ | `-y` | No prompts |
62
+
63
+ ## Update an existing app
64
+
65
+ Run this from the project folder:
66
+
67
+ ```bash
68
+ uvx --from create-caspian-app casp update project # latest
69
+ uvx --from create-caspian-app casp update project 0.0.1 # a specific version
70
+ ```
71
+
72
+ Running `create-caspian-app <name>` inside a folder that has a `caspian.config.json`
73
+ does the same. The update refreshes the Caspian template files and asks about any
74
+ features that aren't enabled yet. It removes the files of features you turn off and
75
+ re-pins the managed dependencies.
76
+
77
+ An update never overwrites:
78
+
79
+ - `.env`
80
+ - `pyproject.toml` (only the managed requirements are re-pinned, with `uv add` / `uv remove`)
81
+ - `uv.lock`
82
+ - `src/app/globals.css` (only the Tailwind directives are added or removed)
83
+ - `prisma/`
84
+ - any path listed in `caspian.config.json` → `"excludeFiles"`
85
+
86
+ Everything else that comes from the template, such as `src/app/index.py`, gets
87
+ overwritten. Add the files you've customized to `excludeFiles` first.
88
+
89
+ ## Requirements
90
+
91
+ - Python 3.14+ for the installer and generated apps. uv can download Python 3.14
92
+ if it is missing.
93
+ - [uv](https://docs.astral.sh/uv/). If it's missing, the installer tries
94
+ `python -m pip install uv`.
@@ -0,0 +1,55 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.27"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "create-caspian-app"
7
+ dynamic = ["version"]
8
+ description = "Create Caspian apps: a high-performance Python web framework (FastAPI + PulsePoint)."
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ license-files = ["LICENSE"]
12
+ requires-python = ">=3.14"
13
+ authors = [{ name = "Jefferson Abraham Omier", email = "thesteelninjacode@gmail.com" }]
14
+ keywords = ["caspian", "python", "fastapi", "scaffold", "create-app", "boilerplate", "tailwindcss", "mcp"]
15
+ classifiers = [
16
+ "Development Status :: 3 - Alpha",
17
+ "Environment :: Console",
18
+ "Framework :: FastAPI",
19
+ "Intended Audience :: Developers",
20
+ "Operating System :: OS Independent",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3.14",
23
+ "Topic :: Internet :: WWW/HTTP :: Dynamic Content",
24
+ "Topic :: Software Development :: Code Generators",
25
+ ]
26
+ # Deliberately empty: the installer uses only the standard library and uv.
27
+ dependencies = []
28
+
29
+ [project.urls]
30
+ Homepage = "https://caspian.tsnc.tech/"
31
+ Repository = "https://github.com/TheSteelNinjaCode/create-caspian-app"
32
+
33
+ [project.scripts]
34
+ create-caspian-app = "create_caspian_app.cli:main"
35
+ casp = "create_caspian_app.casp:main"
36
+
37
+ [dependency-groups]
38
+ dev = ["pytest>=8", "ruff>=0.6"]
39
+
40
+ [tool.hatch.version]
41
+ path = "src/create_caspian_app/__init__.py"
42
+
43
+ [tool.hatch.build.targets.wheel]
44
+ packages = ["src/create_caspian_app"]
45
+
46
+ [tool.hatch.build.targets.sdist]
47
+ include = ["src/", "scripts/", "template_overrides/", "tests/", "README.md", "CHANGELOG.md", "CONTRIBUTING.md", "LICENSE"]
48
+
49
+ [tool.pytest.ini_options]
50
+ testpaths = ["tests"]
51
+ addopts = "-q"
52
+
53
+ [tool.ruff]
54
+ line-length = 100
55
+ extend-exclude = ["src/create_caspian_app/template"]
@@ -0,0 +1,272 @@
1
+ """Copy the Caspian Python starter project into the package template.
2
+
3
+ The source of truth is the Caspian app repository (by default the sibling
4
+ folder ``../create-caspian-app-python``). Only files tracked by git in that
5
+ repository are copied, so its own ``.gitignore`` decides what is private
6
+ (``.env``, ``.tools/``, ``.casp/``, caches).
7
+
8
+ That repository is also the framework's development workspace. Its demo pages,
9
+ benchmarks and framework test suite are not part of a new
10
+ app, so they are left out here, and ``template_overrides/`` supplies what a new
11
+ app gets instead (the app test scaffold and the agent testing guide). Every
12
+ text edit below must match the source exactly; when the source changes so an
13
+ edit no longer applies, the sync fails instead of silently shipping
14
+ development content.
15
+
16
+ Usage:
17
+ uv run python scripts/sync_template.py
18
+ uv run python scripts/sync_template.py --source C:/path/to/caspian-app
19
+ uv run python scripts/sync_template.py --check # fail if template is stale
20
+ """
21
+
22
+ from __future__ import annotations
23
+
24
+ import argparse
25
+ import subprocess
26
+ import sys
27
+ from pathlib import Path
28
+
29
+ ROOT = Path(__file__).resolve().parents[1]
30
+ TEMPLATE = ROOT / "src" / "create_caspian_app" / "template"
31
+ OVERRIDES = ROOT / "template_overrides"
32
+ DEFAULT_SOURCE = ROOT.parent / "create-caspian-app-python"
33
+
34
+ # Tracked in the source repo but never shipped to a new app.
35
+ EXCLUDED_PREFIXES = (
36
+ ".venv/", # the installed runtime belongs to uv, not the template
37
+ ".git/",
38
+ )
39
+ EXCLUDED_FILES = {
40
+ "caspian.config.json", # generated per project by the installer
41
+ ".env", # generated per project (fresh secrets)
42
+ }
43
+ EXCLUDED_SUFFIXES = (".pyc", ".pyo")
44
+
45
+ # Development-only content of the source workspace.
46
+ DEVELOPMENT_ONLY = (
47
+ "docs/prepared-pages-example.md",
48
+ "settings/benchmark_pages.py",
49
+ "src/app/performance/",
50
+ "src/components/performance/",
51
+ "src/lib/performance_demo.py",
52
+ "src/app/form/",
53
+ "src/components/form/",
54
+ # The framework's own test suite. New apps get the scaffold from
55
+ # template_overrides/tests/ and the guide in docs/caspian/testing.md.
56
+ "tests/",
57
+ )
58
+
59
+ # Exact text edits: (old, new) pairs applied to one file.
60
+ EDITS = {
61
+ "src/app/index.py": (
62
+ ("from src.components.performance.ExampleLinks import ExampleLinks\n", ""),
63
+ (" <x-example-links />\n\n", ""),
64
+ ),
65
+ "AGENTS.md": (
66
+ (
67
+ (
68
+ ' Read `docs/caspian/websockets.md` "Named Sockets"; the handshake has no'
69
+ " dedicated tests yet (`tests/test_request_security.py` covers only the"
70
+ " per-connection message rate)."
71
+ ),
72
+ (
73
+ ' Read `docs/caspian/websockets.md` "Named Sockets"; test sockets with'
74
+ ' `client.websocket_connect(...)` as shown in `docs/caspian/testing.md` "Sockets".'
75
+ ),
76
+ ),
77
+ (
78
+ (
79
+ " - Coverage lives in `tests/test_layout.py` (brace escaping), "
80
+ "`tests/test_runtime_security.py` (environment + CSP + path safety), "
81
+ "`tests/test_request_security.py` (page rate limit, missing-asset 404s, "
82
+ "per-connection socket message rate), `tests/test_python_server.py` "
83
+ "(development cookie scoping), `tests/test_page_policy.py` (prepared-page "
84
+ "policy selection), `tests/test_upload_serving.py`, `tests/test_rpc.py`, and "
85
+ "`tests/test_auth.py`. The `/mcp` token gate (`MCPAuthMiddleware`) and the "
86
+ "named-socket handshake (origin check, `require_auth`/`allowed_roles`, "
87
+ "size/idle limits) have no dedicated tests yet — verify them by reading "
88
+ "`main.py` and `src/lib/websocket/sockets.py`."
89
+ ),
90
+ (
91
+ " - The runtime's own security coverage ships with Caspian. Test this app's"
92
+ " security-relevant behavior (route privacy, RBAC, `@rpc()` auth and roles, CSRF on"
93
+ " `route.py`, socket auth) with the `client`, `rpc`, `csrf_headers`, and `sign_in`"
94
+ " fixtures; recipes are in `docs/caspian/testing.md`."
95
+ ),
96
+ ),
97
+ (
98
+ (
99
+ "- Testing/type checking/linting: read `tests/README.md`, `settings/test.py`, and"
100
+ " `docs/caspian/testing.md`. Run `uv run python settings/test.py` (fix: `uv run"
101
+ " python settings/fix.py`). The four checks are native ty, Ruff, templates, and"
102
+ " pytest. A green gate does not prove browser health."
103
+ ),
104
+ (
105
+ "- Testing: **every change to app behavior ships with a test in the same edit batch.**"
106
+ " When you add or change a page, layout, component, `@rpc()` action, `route.py`"
107
+ " endpoint, socket, job, auth/RBAC rule, validation rule, or `src/lib/**` function,"
108
+ " read `docs/caspian/testing.md` first: it maps each kind of change to the test it"
109
+ " needs, with working examples built on the fixtures in `tests/conftest.py`"
110
+ " (`client`, `rpc`, `csrf_headers`, `sign_in`, `config`). Put tests in"
111
+ " `tests/test_<feature>.py`, test routes over HTTP (never import"
112
+ " `src/app/**` modules), and never weaken a test to pass the gate. Then run"
113
+ " `uv run python settings/test.py` (ty, Ruff, templates, pytest; fix: `uv run"
114
+ " python settings/fix.py`) and fix every failure. A green gate does not prove"
115
+ " browser health."
116
+ ),
117
+ ),
118
+ ),
119
+ ".github/copilot-instructions.md": (
120
+ (
121
+ (
122
+ "- App Python edits require uv run python settings/test.py: ty, Ruff, templates,"
123
+ " pytest. Fix all errors."
124
+ ),
125
+ (
126
+ "- App Python edits require uv run python settings/test.py: ty, Ruff, templates,"
127
+ " pytest. Fix all errors. Every new or changed page, component, @rpc() action,"
128
+ " route.py endpoint, socket, job, or auth rule ships with a test in"
129
+ " tests/test_<feature>.py; follow docs/caspian/testing.md."
130
+ ),
131
+ ),
132
+ (
133
+ "pytest exercises app and installed runtime contracts.",
134
+ (
135
+ "pytest runs the app's tests in tests/ (fixtures in tests/conftest.py, recipes in"
136
+ " docs/caspian/testing.md)."
137
+ ),
138
+ ),
139
+ ),
140
+ ".github/instructions/database-generation.instructions.md": (
141
+ (
142
+ (
143
+ "Testing: uv run python settings/test.py. Optional PostgreSQL verification:\n"
144
+ "set CASPIAN_DB_TEST_POSTGRES=1 and run uv run python -m pytest\n"
145
+ "tests/test_prisma_postgresql.py -q, then unset the variable. That test reads .env\n"
146
+ "and uses verified session-local temporary tables, never application tables."
147
+ ),
148
+ (
149
+ "Testing: keep queries in src/lib/** functions that routes call through their\n"
150
+ "module, fake them in route tests, and test the queries themselves against a\n"
151
+ 'dedicated test database; see docs/caspian/testing.md "Database". Then run\n'
152
+ "uv run python settings/test.py."
153
+ ),
154
+ ),
155
+ ),
156
+ }
157
+
158
+ # Dotfiles are renamed inside the wheel so packaging tools never treat them as
159
+ # their own ignore rules. The installer renames them back.
160
+ RENAMED = {".gitignore": "_gitignore"}
161
+
162
+
163
+ def tracked_files(source: Path) -> list[str]:
164
+ try:
165
+ output = subprocess.run(
166
+ ["git", "ls-files", "-z"],
167
+ cwd=source,
168
+ check=True,
169
+ capture_output=True,
170
+ ).stdout
171
+ except (OSError, subprocess.CalledProcessError) as exc:
172
+ raise SystemExit(f"{source} must be a git repository: {exc}") from exc
173
+ return [name for name in output.decode("utf-8").split("\0") if name]
174
+
175
+
176
+ def shipped(name: str) -> bool:
177
+ if name in EXCLUDED_FILES or name.endswith(EXCLUDED_SUFFIXES):
178
+ return False
179
+ if "__pycache__/" in name:
180
+ return False
181
+ if any(name == p or (p.endswith("/") and name.startswith(p)) for p in DEVELOPMENT_ONLY):
182
+ return False
183
+ return not name.startswith(EXCLUDED_PREFIXES)
184
+
185
+
186
+ def apply_edits(name: str, text: str) -> str:
187
+ for old, new in EDITS.get(name, ()):
188
+ if old not in text:
189
+ raise SystemExit(f"{name}: expected text not found (source changed?): {old!r}")
190
+ text = text.replace(old, new)
191
+ return text
192
+
193
+
194
+ def content(name: str, path: Path) -> bytes:
195
+ if name not in EDITS:
196
+ return path.read_bytes()
197
+ raw = path.read_bytes().decode("utf-8")
198
+ crlf = "\r\n" in raw
199
+ text = apply_edits(name, raw.replace("\r\n", "\n")) # edits are written with \n
200
+ return (text.replace("\n", "\r\n") if crlf else text).encode("utf-8")
201
+
202
+
203
+ def destination(name: str) -> str:
204
+ return RENAMED.get(name, name)
205
+
206
+
207
+ def plan(source: Path) -> dict[str, bytes]:
208
+ files = {}
209
+ for name in tracked_files(source):
210
+ path = source / name
211
+ if shipped(name) and path.is_file():
212
+ files[destination(name)] = content(name, path)
213
+ # Files owned by this package: added, or replacing the source's version.
214
+ for path in sorted(OVERRIDES.rglob("*")):
215
+ if path.is_file() and "__pycache__" not in path.parts:
216
+ files[destination(path.relative_to(OVERRIDES).as_posix())] = path.read_bytes()
217
+ return files
218
+
219
+
220
+ def main() -> int:
221
+ parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
222
+ parser.add_argument("--source", type=Path, default=DEFAULT_SOURCE)
223
+ parser.add_argument("--check", action="store_true", help="report drift, write nothing")
224
+ args = parser.parse_args()
225
+
226
+ source = args.source.resolve()
227
+ if not (source / "main.py").is_file():
228
+ raise SystemExit(f"Not a Caspian app (no main.py): {source}")
229
+
230
+ files = plan(source)
231
+ existing = (
232
+ {p.relative_to(TEMPLATE).as_posix() for p in TEMPLATE.rglob("*") if p.is_file()}
233
+ if TEMPLATE.exists()
234
+ else set()
235
+ )
236
+ stale = sorted(existing - files.keys())
237
+ changed = sorted(
238
+ name
239
+ for name, data in files.items()
240
+ if not (TEMPLATE / name).is_file() or (TEMPLATE / name).read_bytes() != data
241
+ )
242
+
243
+ if args.check:
244
+ for name in changed:
245
+ print(f"changed: {name}")
246
+ for name in stale:
247
+ print(f"removed: {name}")
248
+ if changed or stale:
249
+ print("Template is out of date. Run: uv run python scripts/sync_template.py")
250
+ return 1
251
+ print(f"Template is current ({len(files)} files from {source}).")
252
+ return 0
253
+
254
+ for name in stale:
255
+ (TEMPLATE / name).unlink()
256
+ for name in changed:
257
+ target = TEMPLATE / name
258
+ target.parent.mkdir(parents=True, exist_ok=True)
259
+ target.write_bytes(files[name])
260
+ # Drop directories emptied by removals.
261
+ for directory in sorted(TEMPLATE.rglob("*"), reverse=True):
262
+ if directory.is_dir() and not any(directory.iterdir()):
263
+ directory.rmdir()
264
+
265
+ print(
266
+ f"Synced {len(files)} files from {source} ({len(changed)} updated, {len(stale)} removed)."
267
+ )
268
+ return 0
269
+
270
+
271
+ if __name__ == "__main__":
272
+ sys.exit(main())
@@ -0,0 +1,5 @@
1
+ """Scaffold Caspian Python applications."""
2
+
3
+ # One version for both the PyPI package and the Caspian framework: the
4
+ # installer writes it to every project's caspian.config.json.
5
+ __version__ = "0.0.1"
@@ -0,0 +1,5 @@
1
+ import sys
2
+
3
+ from .cli import main
4
+
5
+ sys.exit(main())