Skip to content
Open
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
34 changes: 34 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,40 @@ Live at https://tenantfirstaid.com/
```
`--keep-going` will continue to run checks, even if previous `make` rule fail. Omit if you want to stop after the first `make` rule fails.

## Versioning and Releases

This project uses [semantic versioning](https://semver.org/) with automated version management via `setuptools-scm`. The version is automatically derived from Git tags.

### Creating a Release

1. **Determine the version bump type:**
- **Patch release** (0.2.0 → 0.2.1): Bug fixes, minor improvements
- **Minor release** (0.2.0 → 0.3.0): New features, backward-compatible changes
- **Major release** (0.2.0 → 1.0.0): Breaking changes

2. **Create and push a tag:**
```bash
# For a patch release (default for regular PRs)
git tag v0.2.1
git push origin v0.2.1

# For a minor release (feature additions)
git tag v0.3.0
git push origin v0.3.0

# For a major release (breaking changes)
git tag v1.0.0
git push origin v1.0.0
```

3. **The version will automatically be updated** in the backend API and displayed in the frontend UI.

### Checking the Current Version

- **Backend API**: Visit `/api/version` endpoint
- **Frontend UI**: Check the sidebar navigation (bottom)
- **Command line**: Run `uv run python -c "from importlib.metadata import version; print(version('tenant-first-aid'))"`

## Contributing

We currently have regular project meetups: https://www.meetup.com/codepdx/ . Also check out https://www.codepdx.org/ to find our Discord server.
Expand Down
64 changes: 64 additions & 0 deletions backend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Tenant First Aid Backend

Flask backend API for the Tenant First Aid chatbot.

## Development Setup

See the main [README.md](../README.md) for full setup instructions.

## API Endpoints

- `/api/init` - Initialize chat session
- `/api/query` - Send chat message
- `/api/history` - Get chat history
- `/api/clear-session` - Clear current session
- `/api/citation` - Get citation information
- `/api/version` - Get application version

## Version Management

This backend uses `setuptools-scm` for automatic version management based on Git tags. The version is dynamically generated from the repository's tag history.

### Checking Version

```bash
# In the backend directory
uv run python -c "from importlib.metadata import version; print(version('tenant-first-aid'))"

# Or via the API
curl http://localhost:5001/api/version
```

### Creating a New Release

1. Ensure all changes are committed and pushed
2. Create a new tag following semantic versioning:
```bash
git tag v0.3.0 # or appropriate version
git push origin v0.3.0
```
3. The version will automatically be updated in the application

## Development Commands

From the `backend/` directory:

```bash
# Install dependencies
uv sync

# Run the server
uv run python -m tenantfirstaid.app

# Run tests
uv run pytest

# Format code
uv run ruff format

# Lint code
uv run ruff check

# Type check
uv run ty check
```
6 changes: 4 additions & 2 deletions backend/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

[project]
name = "tenant-first-aid"
version = "0.2.0"
dynamic = ["version"]
requires-python = ">=3.12"
dependencies = [
"flask>=3.1.1",
Expand All @@ -21,14 +21,16 @@ dependencies = [
"python-dotenv",
"pandas>=2.3.0",
"vertexai>=1.43.0",
"setuptools-scm>=8",
"importlib-metadata>=8.7.0",
]

[tool.setuptools.packages.find]
where = ["."]
exclude = ["data*"]

[build-system]
requires = ["setuptools>=61"]
requires = ["setuptools>=80", "setuptools-scm>=8"]
build-backend = "setuptools.build_meta"

[dependency-groups]
Expand Down
22 changes: 22 additions & 0 deletions backend/tenantfirstaid/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
import os
import secrets

try:
from importlib.metadata import version
except ImportError:
from importlib_metadata import version


if Path(".env").exists():
from dotenv import load_dotenv
Expand Down Expand Up @@ -89,6 +94,23 @@ def clear_session():
return jsonify({"success": True})


@app.get("/api/version")
def get_version():
try:
# Try the package name as defined in pyproject.toml
app_version = version("tenant-first-aid")
return jsonify({"version": app_version})
except Exception:
try:
# Try alternative package name format
app_version = version("tenant_first_aid")
return jsonify({"version": app_version})
except Exception:
# Fallback for development or when setuptools-scm can't determine version
# This happens when there are no git tags yet
return jsonify({"version": "0.1.0-dev"})


app.add_url_rule(
"/api/init",
view_func=InitSessionView.as_view("init", tenant_session),
Expand Down
48 changes: 47 additions & 1 deletion backend/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

73 changes: 73 additions & 0 deletions frontend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Tenant First Aid Frontend

React frontend application for the Tenant First Aid chatbot.

## Development Setup

See the main [README.md](../README.md) for full setup instructions.

## Version Display

The application version is automatically fetched from the backend API and displayed in the navigation sidebar. The version corresponds to the backend version derived from Git tags.

### Version Hook

The frontend includes a custom `useVersion` hook that fetches version information from `/api/version`:

```typescript
import { useVersion } from "./hooks/useVersion";

function MyComponent() {
const { version, loading, error } = useVersion();

return (
<div>
{loading ? "Loading..." : error ? "Version unavailable" : `v${version}`}
</div>
);
}
```

## Development Commands

From the `frontend/` directory:

```bash
# Install dependencies
npm install

# Start development server
npm run dev

# Build for production
npm run build

# Lint code
npm run lint

# Format code
npm run format

# Preview production build
npm run preview
```

## Creating a New Release

The frontend version automatically reflects the backend version. To create a new release:

1. Ensure all changes are committed and pushed to the main branch
2. Create and push a new Git tag:
```bash
git tag v0.3.0 # Follow semantic versioning
git push origin v0.3.0
```
3. The version will automatically be updated and displayed in the UI

## Architecture

- **React 19** with TypeScript
- **Vite** for build tooling and development server
- **Tailwind CSS** for styling
- **React Router** for navigation
- **TanStack Query** for API state management
2 changes: 2 additions & 0 deletions frontend/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export default tseslint.config(
"warn",
{ allowConstantExport: true },
],
// rando answer from https://github.com/eslint/eslint/discussions/18685
"@typescript-eslint/no-unused-vars": ["warn", { caughtErrors: "none" }],
},
},
);
35 changes: 35 additions & 0 deletions frontend/src/hooks/useVersion.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { useState, useEffect } from "react";

interface VersionResponse {
version: string;
error?: string;
}

export function useVersion() {
const [version, setVersion] = useState<string | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);

useEffect(() => {
const fetchVersion = async () => {
try {
const response = await fetch("/api/version");
const data: VersionResponse = await response.json();

if (response.ok) {
setVersion(data.version);
} else {
setError("Failed to fetch version");
}
} catch (err) {
setError("Failed to fetch version");
} finally {
setLoading(false);
}
};

fetchVersion();
}, []);

return { version, loading, error };
}
Loading