Skip to content
This repository was archived by the owner on Jun 21, 2026. It is now read-only.

Commit 926653c

Browse files
authored
Merge pull request #16 from rasulkireev/prompt-improvements
refactor: optimize prompts and project details structure
2 parents 745c6f5 + c741a92 commit 926653c

9 files changed

Lines changed: 386 additions & 137 deletions

File tree

.cursor/rules/backend.mdc

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
---
2+
description: Rules for working with the Backend (Django in this case)
3+
globs: *.py
4+
alwaysApply: false
5+
---
6+
## Key Principles
7+
- We will only have one django app, called 'core'. Everything about our webapp will be here
8+
- Use Django's built-in features and tools wherever possible
9+
- Prioritize readability and maintainability; follow PEP 8
10+
- Use descriptive variable/function names with underscores
11+
- Use Django templates for HTML, django-ninja for APIs
12+
- Keep business logic in models/forms
13+
- Keep views focused on request handling
14+
- Implement comprehensive logging
15+
- Use double quotes instead of single quotes
16+
17+
18+
## Django/Python
19+
- Use CBVs for complex views; FBVs for simpler logic
20+
- Leverage Django's ORM; avoid raw SQL when possible
21+
- Use Django's built-in user model and authentication
22+
- Utilize Django form/model form classes
23+
- Follow MVT pattern strictly
24+
25+
## Logging and Error Handling
26+
- Use Python's logging module (structlog) extensively
27+
- Include context in log messages:
28+
logger.warning(
29+
"Error occurred during profile update",
30+
error=str(e),
31+
profile_id=profile.id
32+
)
33+
- Use appropriate log levels (INFO, WARNING, ERROR)
34+
- Use Django's validation framework
35+
- Use try-except blocks for specific erros, try to avoid excepting Exception
36+
- Customize error pages (404, 500)
37+
38+
## API Development
39+
- Use django-ninja instead of DRF
40+
- django-ninja generate openapi documentation, so make sure to populate views with relevant data in order for it to hsow up in the OpenAPI docs.
41+
- Use Pydantic models for schema validation
42+
- Use django-ninja's authentication classes
43+
44+
## Workers
45+
- Use django-q2 syntax for workers

.cursor/rules/frontend.mdc

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
description: Frontend related rule (HTML Template and Stimulus.js)
3+
globs: *.js, *.html
4+
alwaysApply: false
5+
---
6+
## Frontend Development
7+
- Prefer Stimulus JS for adding interactivity to Django templates instead of raw script elements
8+
- Use Stimulus controllers to encapsulate JavaScript behavior and keep it separate from HTML structure
9+
- Leverage Stimulus data attributes to connect HTML elements with JavaScript functionality
10+
- Utilize Stimulus targets to reference specific elements within a controller
11+
- Employ Stimulus actions to handle user interactions and events
12+
13+
## Stimulusjs Specific Guidelines
14+
- Add semicolons at the end of statements
15+
- Use double quotes instead of single quotes
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
---
2+
description: This rule explains the project's tech stack and code conventions
3+
globs:
4+
alwaysApply: true
5+
---
6+
This rule serves as high-level documentation for how the codebase is structured.
7+
8+
## Rules for AI
9+
10+
- Use this file to understand how the codebase works
11+
- Treat this rule/file as your "source of truth" when making code recommendations
12+
- When creating migrations, always use `dm makemigrations` instead of creating the file yourself
13+
14+
## Project Tech Stack
15+
16+
- Web framework: Django
17+
- Django's built-in testing framework
18+
- Django Ninja for API development
19+
- Django Q2 for background tasks
20+
- Stimulus JS for frontend interactivity
21+
- TailwindCSS for styles
22+
- Database: PostgreSQL
23+
- Background tasks: Django Q2
24+
- External
25+
- Payments: Stripe
26+
- [Other external services your project uses]
27+
28+
## Project conventions
29+
30+
These conventions should be used when writing code for the project.
31+
32+
### Convention 1: Minimize dependencies, vanilla Django is plenty
33+
34+
Dependencies are a natural part of building software, but we aim to minimize them when possible to keep this codebase easy to understand, maintain, and contribute to.
35+
36+
- Push Django to its limits before adding new dependencies
37+
- When a new dependency is added, there must be a strong technical or business reason to add it
38+
- When adding dependencies, you should favor old and reliable over new and flashy
39+
40+
### Convention 2: Leverage models and mixins over separate service layers
41+
42+
This codebase adopts a "skinny views, fat models" convention following Django's MVT pattern. We put business logic in models and avoid separate folders for business logic.
43+
44+
- Organize large pieces of business logic into Django models and mixins
45+
- While a mixin _may_ offer shared functionality, it can also be a "one-off" mixin that is only included in one place for better organization and readability
46+
- When mixins are used for code organization, they should be organized around the "traits" of a model; not for simply moving code to another spot in the codebase
47+
- When possible, models should answer questions about themselves—for example, we might have a method, `account.balance_series` that returns a time-series of the account's most recent balances
48+
49+
### Convention 3: Prefer server-side solutions over client-side solutions
50+
51+
- When possible, leverage Django templates over complex, JS-driven client-side solutions
52+
- When writing a client-side solution, use Stimulus controllers and keep it simple!
53+
- Keep client-side code for where it truly shines. For example, bulk selection is a case where server-side solutions would degrade the user experience significantly
54+
55+
### Convention 4: Sacrifice performance, optimize for simplicitly and clarity
56+
57+
This codebase is still young. We are still rapidly iterating on domain designs and features. Because of this, code should be optimized for simplicitly and clarity over performance.
58+
59+
- Focus on good OOP design first, performance second
60+
- Be mindful of large performance bottlenecks, but don't sweat the small stuff
61+
62+
### Convention 5: Prefer semantic, native HTML features
63+
64+
The HTML spec has improved tremendously over the years and offers a ton of functionality out of the box. We prefer semantic, native HTML solutions over JS-based ones. A few examples of this include:
65+
66+
- Using the `dialog` element for modals
67+
- Using `summary` / `details` elements for disclosures (or `popover` attribute)
68+
69+
Stimulus works very well with these native elements and we optimize for this.
70+
71+
### Convention 6: Use Django's testing framework and fixtures
72+
73+
Due to the open-source nature of this project, we have chosen Django's testing framework and fixtures for testing to maximize familiarity and predictability.
74+
75+
- Always use Django's testing framework and fixtures for testing
76+
- Keep fixtures to a minimum. Most models should have 2-3 fixtures maximum that represent the "base cases" for that model
77+
- "Edge cases" should be created on the fly, within the context of the test which it is needed
78+
- For tests that require a large number of fixture records to be created, use test helpers to act as a "factory" for creating these
79+
80+
### Convention 7: Use Django models for complex validations, DB for simple ones, keep business logic out of DB
81+
82+
- Enforce `null` checks, unique constraints, and other simple validations in the DB
83+
- Django model validations _may_ mirror the DB level ones, but not 100% necessary
84+
- These are for convenience when error handling in forms. Always prefer client-side form validation when possible
85+
- Complex validations and business logic should remain in Django models
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
description: This file describes Marketing Agent's design system and how views should be styled
3+
globs: *.html, views.py, *.js, *.css
4+
alwaysApply: false
5+
---
6+
Use this rule whenever you are writing html, css, or even styles in Stimulus controllers that use D3.js.
7+
8+
The codebase uses TailwindCSS v3.x with no custom design system defined.
9+
10+
- Always generate semantic HTML
11+
- Never create new styles without explicitly receiving permission to do so
12+
- Always favor the "utility first" Tailwind approach. Reusable style classes should not be created often. Code should be reused primarily through template components.

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
.logfire/
2+
.ruff_cache/
3+
14
# DB
25
backup-dbs/
36
media/

CLAUDE.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Commands
2+
- Build/Run: `make serve` (docker-compose up -d --build)
3+
- Test: `make test` (docker compose run --rm backend pytest)
4+
- Test single file: `docker compose run --rm backend pytest path/to/test.py::TestClass::test_method -v`
5+
- Shell: `make shell` (Django shell_plus with IPython)
6+
- Stripe sync: `make stripe-sync`
7+
- Frontend: `npm run build`, `npm start`, `npm run watch`
8+
9+
# Code Style
10+
## Python
11+
- Line length: 120
12+
- Formatting: black
13+
- Imports: isort (Django profile, combine_as_imports, trailing_comma)
14+
- Linting: ruff
15+
- Django templates: djlint (profile=django)
16+
- Error handling: Proper exception catching and logging
17+
18+
## Frontend
19+
- StimulusJS: Use controllers for all interactive elements
20+
- TailwindCSS: Use for styling (with @tailwindcss/forms, @tailwindcss/typography)
21+
- JavaScript: @babel/eslint-parser, eslint:recommended, required semicolons
22+
- SCSS: stylelint-config-standard-scss
23+
24+
## Naming & Structure
25+
- Follow Django conventions for models, views
26+
- Use type hints in Python
27+
- Follow existing pattern in codebase for component structure
28+
- Document complex functions and classes

core/models.py

Lines changed: 6 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -176,24 +176,6 @@ class Project(BaseModel):
176176
def __str__(self):
177177
return self.name
178178

179-
@property
180-
def project_details_string(self):
181-
return f"""
182-
- Today's Date: {timezone.now().strftime("%Y-%m-%d")}
183-
- Project URL: {self.url}
184-
- Project Name: {self.name}
185-
- Project Type: {self.type}
186-
- Project Summary: {self.summary}
187-
- Blog Theme: {self.blog_theme}
188-
- Founders: {self.founders}
189-
- Key Features: {self.key_features}
190-
- Target Audience: {self.target_audience_summary}
191-
- Pain Points: {self.pain_points}
192-
- Product Usage: {self.product_usage}
193-
- Language: {self.language}
194-
- Links: {self.links}
195-
"""
196-
197179
@property
198180
def project_details(self):
199181
return ProjectDetails(
@@ -218,19 +200,6 @@ def liked_title_suggestions(self):
218200
def disliked_title_suggestions(self):
219201
return self.blog_post_title_suggestions.filter(user_score__lt=0).all()
220202

221-
@property
222-
def get_liked_disliked_title_suggestions_string(self):
223-
liked_titles = "\n".join(f"- {suggestion.title}" for suggestion in self.liked_title_suggestions)
224-
disliked_titles = "\n".join(f"- {suggestion.title}" for suggestion in self.disliked_title_suggestions)
225-
226-
return f"""
227-
Liked Title Suggestions:
228-
{liked_titles}
229-
230-
Disliked Title Suggestions:
231-
{disliked_titles}
232-
"""
233-
234203
def get_page_content(self):
235204
"""
236205
Fetch page content using Jina Reader API and update the project.
@@ -291,7 +260,7 @@ def get_page_content(self):
291260

292261
def analyze_content(self):
293262
"""
294-
Analyze the page content using Claude via PydanticAI and update project details.
263+
Analyze the page content using PydanticAI and update project details.
295264
Should be called after get_page_content().
296265
"""
297266
agent = Agent(
@@ -370,15 +339,15 @@ def add_project_details(ctx: RunContext[TitleSuggestionContext]) -> str:
370339
"""
371340

372341
@agent.system_prompt
373-
def add_language_specification(ctx: RunContext[TitleSuggestionContext]) -> str:
342+
def add_number_of_titles_to_generate(ctx: RunContext[TitleSuggestionContext]) -> str:
374343
return f"""IMPORTANT: Generate only {ctx.deps.num_titles} titles."""
375344

376345
@agent.system_prompt
377-
def add_number_of_titles_to_generate(ctx: RunContext[TitleSuggestionContext]) -> str:
346+
def add_language_specification(ctx: RunContext[TitleSuggestionContext]) -> str:
378347
project = ctx.deps.project_details
379348
return f"""
380349
IMPORTANT: Generate all titles in {project.language} language.
381-
Make sure the titles are grammatically correct and culturally appropriate for {self.language}-speaking audiences.
350+
Make sure the titles are grammatically correct and culturally appropriate for {project.language}-speaking audiences.
382351
"""
383352

384353
@agent.system_prompt
@@ -513,12 +482,12 @@ def generate_content(self, content_type=ContentType.SHARING):
513482
The generated blog post
514483
"""
515484
agent = Agent(
516-
"anthropic:claude-3-7-sonnet-latest",
485+
"google-gla:gemini-2.0-flash",
517486
result_type=BlogPostContent,
518487
deps_type=BlogPostGenerationContext,
519488
system_prompt=GENERATE_CONTENT_SYSTEM_PROMPTS[content_type],
520489
retries=2,
521-
model_settings={"max_tokens": 8000, "temperature": 0.4},
490+
model_settings={"max_tokens": 8192, "temperature": 0.4},
522491
)
523492

524493
@agent.system_prompt

0 commit comments

Comments
 (0)