1
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
# fossilrepo -- bootstrap
2
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
3
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
This is the primary conventions document. All agent shims (`CLAUDE.md`, `AGENTS.md`) point here.
4
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
5
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
An agent given this document and a business requirement should be able to generate correct, idiomatic code without exploring the codebase.
6
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
7
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
---
8
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
9
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
## What is fossilrepo
10
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
11
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
Omnibus-style installer for a self-hosted Fossil forge. One command gets you a full-stack code hosting platform: VCS, issues, wiki, timeline, web UI, SSL, and continuous backups -- all powered by Fossil SCM.
12
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
13
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
Think GitLab Omnibus, but for Fossil.
14
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
15
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
---
16
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
17
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
## Why Fossil
18
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
19
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
A Fossil repo is a single SQLite file. It contains the full VCS history, issue tracker, wiki, forum, and timeline. No external services. No rate limits. Portable -- hand the file to someone and they have everything.
20
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
21
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
For teams running CI agents or automation:
22
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
- Agents commit, file tickets, and update the wiki through one CLI and one protocol
23
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
- No API rate limits when many agents are pushing simultaneously
24
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
- The `.fossil` file IS the project artifact -- a self-contained archive
25
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
- Litestream replicates it to S3 continuously -- backup and point-in-time recovery for free
26
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
27
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
Fossil also has a built-in web UI (skinnable), autosync, peer-to-peer sync, and unversioned content storage (like Git LFS but built-in).
28
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
29
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
---
30
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
31
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
## What fossilrepo Does
32
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
33
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
fossilrepo packages everything needed to run a production Fossil server into one installable unit:
34
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
35
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
- **Fossil server** -- serves all repos from a single process
36
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
- **Caddy** -- SSL termination, subdomain-per-repo routing (`reponame.your-domain.com`)
37
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
- **Litestream** -- continuous SQLite replication to S3/MinIO (backup + point-in-time recovery)
38
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
- **CLI** -- repo lifecycle management (create, list, delete) and sync tooling
39
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
- **Sync bridge** -- mirror Fossil repos to GitHub/GitLab as downstream read-only copies
40
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
41
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
New project = `fossil init`. No restart, no config change. Litestream picks it up automatically.
42
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
43
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
---
44
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
45
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
## Server Stack
46
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
47
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```
48
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
Caddy (SSL termination, routing, subdomain per repo)
49
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
+-- fossil server --repolist /data/repos/
50
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
+-- /data/repos/
51
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
|-- projecta.fossil
52
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
|-- projectb.fossil
53
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
+-- ...
54
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
55
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
Litestream -> S3/MinIO (continuous replication, point-in-time recovery)
56
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```
57
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
58
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
One binary serves all repos. The whole platform is: repo creation + subdomain provisioning + Litestream config.
59
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
60
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
### Sync Bridge
61
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
62
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
Mirrors Fossil to GitHub/GitLab as a downstream copy. Fossil is the source of truth.
63
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
64
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
Maps:
65
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
- Fossil commits -> Git commits
66
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
- Fossil tickets -> GitHub/GitLab Issues (optional, configurable)
67
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
- Fossil wiki -> repo docs (optional, configurable)
68
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
69
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
Triggered on demand or on schedule.
70
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
71
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
---
72
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
73
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
## Architecture
74
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
75
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```
76
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
fossilrepo/
77
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
|-- config/ # Django settings, URLs, Celery
78
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
|-- core/ # Base models, permissions, middleware
79
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
|-- accounts/ # Session-based auth
80
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
|-- organization/ # Org + member management
81
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
|-- docker/ # Fossil-specific: Caddyfile, litestream.yml
82
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
|-- templates/ # HTMX templates
83
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
|-- _old_fossilrepo/ # Original server/sync/cli code (being ported)
84
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
+-- docs/ # Architecture guides
85
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```
86
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
87
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
---
88
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
89
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
## What's Already Built
90
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
91
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
| Layer | What's there |
92
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
|---|---|
93
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
| Auth | Session-based auth (accounts), login/logout views with templates, rate limiting |
94
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
| Data | Postgres 16, `Tracking` base model (version, created/updated/deleted by+at, soft deletes, history) |
95
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
| API | Django views returning HTML (full pages + HTMX partials) |
96
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
| Permissions | Group-based via `P` enum, checked in every view |
97
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
| Async | Celery worker + beat, Redis broker |
98
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
| Admin | Django Admin with `BaseCoreAdmin` (import/export, tracking fields) |
99
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
| Infra | Docker Compose: postgres, redis, celery-worker, celery-beat, mailpit |
100
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
| CI | GitHub Actions: lint (Ruff) + tests (Postgres + Redis services) |
101
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
| Seed | `python manage.py seed` creates admin/viewer users, sample data |
102
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
| Frontend | HTMX 2.0 + Alpine.js 3 + Tailwind CSS, server-rendered templates |
103
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
104
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
---
105
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
106
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
## App Structure
107
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
108
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
| App | Purpose |
109
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
|---|---|
110
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
| `config` | Django settings, URLs, Celery configuration |
111
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
| `core` | Base models (Tracking, BaseCoreModel), admin (BaseCoreAdmin), permissions (P enum), middleware |
112
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
| `accounts` | Session-based authentication: login/logout views with rate limiting |
113
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
| `organization` | Organization + OrganizationMember models |
114
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
| `testdata` | `seed` management command for development data |
115
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
116
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
---
117
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
118
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
## Conventions
119
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
120
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
### Models
121
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
122
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
All business models inherit from one of:
123
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
124
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
**`Tracking`** (abstract) -- audit trails:
125
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```python
126
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
from core.models import Tracking
127
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
128
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
class Invoice(Tracking):
129
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
amount = models.DecimalField(...)
130
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```
131
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
Provides: `version` (auto-increments), `created_at/by`, `updated_at/by`, `deleted_at/by`, `history` (simple_history).
132
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
133
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
**`BaseCoreModel(Tracking)`** (abstract) -- named entities:
134
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```python
135
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
from core.models import BaseCoreModel
136
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
137
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
class Project(BaseCoreModel):
138
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
visibility = models.CharField(...)
139
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```
140
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
Adds: `guid` (UUID), `name`, `slug` (auto-generated, unique), `description`.
141
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
142
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
**Soft deletes:** call `obj.soft_delete(user=request.user)`, never `.delete()`.
143
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
144
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
**ActiveManager:** Use `objects` (excludes deleted) for queries, `all_objects` for admin.
145
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
146
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
---
147
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
148
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
### Views (HTMX Pattern)
149
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
150
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
Views return full pages for normal requests, HTMX partials for `HX-Request`:
151
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
152
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```python
153
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
@login_required
154
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
def project_list(request):
155
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
P.PROJECT_VIEW.check(request.user)
156
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
projects = Project.objects.all()
157
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
158
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
if request.headers.get("HX-Request"):
159
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
return render(request, "projects/partials/project_table.html", {"projects": projects})
160
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
161
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
return render(request, "projects/project_list.html", {"projects": projects})
162
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```
163
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
164
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
**URL patterns** follow CRUD convention:
165
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```python
166
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
urlpatterns = [
167
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
path("", views.project_list, name="list"),
168
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
path("create/", views.project_create, name="create"),
169
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
path("<slug:slug>/", views.project_detail, name="detail"),
170
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
path("<slug:slug>/edit/", views.project_update, name="update"),
171
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
path("<slug:slug>/delete/", views.project_delete, name="delete"),
172
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
]
173
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```
174
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
175
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
---
176
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
177
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
### Permissions
178
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
179
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
Group-based. Never user-based. Checked in every view.
180
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
181
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```python
182
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
from core.permissions import P
183
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
184
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
P.PROJECT_VIEW.check(request.user) # raises PermissionDenied if denied
185
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
P.PROJECT_ADD.check(request.user, raise_error=False) # returns False instead
186
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```
187
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
188
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
Template guards:
189
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```html
190
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
{% if perms.projects.view_project %}
191
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
<a href="{% url 'projects:list' %}">Projects</a>
192
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
{% endif %}
193
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```
194
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
195
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
---
196
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
197
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
### Admin
198
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
199
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
All admin classes inherit `BaseCoreAdmin`:
200
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```python
201
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
from core.admin import BaseCoreAdmin
202
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
203
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
@admin.register(Project)
204
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
class ProjectAdmin(BaseCoreAdmin):
205
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
list_display = ("name", "slug", "visibility", "created_at")
206
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
search_fields = ("name", "slug")
207
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```
208
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
209
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
`BaseCoreAdmin` provides: audit fields as readonly, `created_by`/`updated_by` auto-set, import/export.
210
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
211
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
---
212
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
213
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
### Templates
214
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
215
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
- `base.html` -- layout with HTMX, Alpine.js, Tailwind CSS, CSRF injection, messages
216
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
- `includes/nav.html` -- navigation bar with permission guards
217
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
- `{app}/partials/*.html` -- HTMX partial templates (no `{% extends %}`)
218
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
- CSRF token sent with all HTMX requests via `htmx:configRequest` event
219
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
220
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
Alpine.js patterns for client-side interactivity:
221
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```html
222
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
<div x-data="{ open: false }">
223
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
<button @click="open = !open">Toggle</button>
224
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
<div x-show="open" x-transition>Content</div>
225
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
</div>
226
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```
227
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
228
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
---
229
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
230
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
### Tests
231
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
232
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
pytest + real Postgres. Assert against database state.
233
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
234
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```python
235
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
@pytest.mark.django_db
236
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
class TestProjectCreate:
237
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
def test_create_saves_project(self, admin_client, admin_user, org):
238
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
response = admin_client.post(reverse("projects:create"), {
239
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
"name": "New App", "visibility": "private", ...
240
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
})
241
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
assert response.status_code == 302
242
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
project = Project.objects.get(name="New App")
243
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
assert project.created_by == admin_user
244
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
245
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
def test_create_denied_for_viewer(self, viewer_client):
246
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
response = viewer_client.get(reverse("projects:create"))
247
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
assert response.status_code == 403
248
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```
249
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
250
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
Both allowed AND denied permission cases for every endpoint.
251
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
252
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
---
253
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
254
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
### Code Style
255
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
256
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
| Tool | Config |
257
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
|------|--------|
258
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
| Ruff (lint + format) | `pyproject.toml`, line length 140 |
259
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
| Import sorting | Ruff isort rules |
260
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
| Python version | 3.12+ |
261
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
262
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
Run `ruff check .` and `ruff format --check .` before committing.
263
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
264
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
---
265
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
266
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
## Adding a New App
267
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
268
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```bash
269
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
# 1. Create the app
270
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
python manage.py startapp myapp
271
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
272
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
# 2. Add to INSTALLED_APPS in config/settings.py
273
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
274
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
# 3. Create models inheriting Tracking or BaseCoreModel
275
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
276
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
# 4. Create migrations
277
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
python manage.py makemigrations
278
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
279
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
# 5. Create admin (inherit BaseCoreAdmin)
280
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
281
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
# 6. Create views with @login_required + P.PERMISSION.check()
282
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
283
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
# 7. Create URL patterns (list, detail, create, update, delete)
284
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
285
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
# 8. Create templates (full page + HTMX partials)
286
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
287
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
# 9. Add permission entries to core/permissions.py P enum
288
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
289
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
# 10. Write tests (allowed + denied)
290
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
python -m pytest --cov -v
291
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```
292
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
293
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
---
294
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
295
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
## Ports (local Docker)
296
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
297
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
| Service | URL |
298
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
|---|---|
299
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
| Django | http://localhost:8000 |
300
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
| Django Admin | http://localhost:8000/admin/ |
301
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
| Health | http://localhost:8000/health/ |
302
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
| Mailpit | http://localhost:8025 |
303
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
| Postgres | localhost:5432 |
304
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
| Redis | localhost:6379 |
305
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
306
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
---
307
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
308
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
## Common Commands
309
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
310
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```bash
311
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
make up # Start the stack
312
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
make build # Build and start
313
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
make down # Stop the stack
314
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
make migrate # Run migrations
315
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
make migrations # Create migrations
316
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
make seed # Load dev fixtures
317
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
make test # Run tests with coverage
318
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
make lint # Run Ruff check + format
319
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
make superuser # Create Django superuser
320
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
make shell # Shell into container
321
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
make logs # Tail Django logs
322
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```
323
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
324
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
---
325
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
326
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
## Platform Vision (fossilrepos.com)
327
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
328
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
GitLab model:
329
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
- **Self-hosted** -- open source, run it yourself. fossilrepo is the tool.
330
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
- **Managed** -- fossilrepos.com, hosted for you. Subdomain per repo, modern UI, billing.
331
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
332
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
The platform is Fossil's built-in web UI with a modern skin + thin API wrapper + authentication. Not a rewrite -- Fossil already does the hard parts. The value is the hosting and UX polish.
333
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
334
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
Not being built yet -- get the self-hosted tool right first.
335
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
336
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
---
337
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
338
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
## License
339
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
340
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
MIT.
341
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!