refactor: centralize constants and reorganize documentation

- Create internal/constants package with all hardcoded values
  (environment, cookies, themes, headers, routes, cache)
- Create internal/httputil package for HTTP helper functions
- Update all handlers and middleware to use centralized constants
- Reorganize documentation with numbered prefixes (00-26)
- Remove duplicate docs from validation folder and docs/
- Delete handlers/constants.go (moved to internal/constants)
This commit is contained in:
juanatsap
2025-12-06 16:27:12 +00:00
parent 71d9258c58
commit 2c7f8de242
37 changed files with 732 additions and 343 deletions
+17 -27
View File
@@ -8,6 +8,8 @@ import (
"strings"
"time"
"github.com/juanatsap/cv-site/internal/constants"
"github.com/juanatsap/cv-site/internal/httputil"
"github.com/juanatsap/cv-site/internal/middleware"
"github.com/juanatsap/cv-site/internal/pdf"
)
@@ -31,14 +33,8 @@ func (h *CVHandler) Home(w http.ResponseWriter, r *http.Request) {
return
}
// Get language from query parameter, default to English
lang := r.URL.Query().Get("lang")
if lang == "" {
lang = "en"
}
// Validate language
if lang != "en" && lang != "es" {
lang, ok := httputil.LangOrError(r)
if !ok {
HandleError(w, r, BadRequestError("Unsupported language. Use 'en' or 'es'"))
return
}
@@ -74,7 +70,7 @@ func (h *CVHandler) Home(w http.ResponseWriter, r *http.Request) {
return
}
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.Header().Set(constants.HeaderContentType, constants.ContentTypeHTML)
if err := tmpl.Execute(w, data); err != nil {
HandleError(w, r, TemplateError(err, "index.html"))
return
@@ -83,14 +79,8 @@ func (h *CVHandler) Home(w http.ResponseWriter, r *http.Request) {
// CVContent renders just the CV content for HTMX swaps
func (h *CVHandler) CVContent(w http.ResponseWriter, r *http.Request) {
// Get language from query parameter
lang := r.URL.Query().Get("lang")
if lang == "" {
lang = "en"
}
// Validate language
if lang != "en" && lang != "es" {
lang, ok := httputil.LangOrError(r)
if !ok {
HandleError(w, r, BadRequestError("Unsupported language. Use 'en' or 'es'"))
return
}
@@ -109,7 +99,7 @@ func (h *CVHandler) CVContent(w http.ResponseWriter, r *http.Request) {
return
}
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.Header().Set(constants.HeaderContentType, constants.ContentTypeHTML)
if err := tmpl.Execute(w, data); err != nil {
HandleError(w, r, TemplateError(err, "cv-content.html"))
return
@@ -137,7 +127,7 @@ func (h *CVHandler) DefaultCVShortcut(w http.ResponseWriter, r *http.Request) {
lang := strings.TrimSuffix(langWithExt, ".pdf")
// Validate language
if lang != "en" && lang != "es" {
if !constants.SupportedLanguages[lang] {
http.NotFound(w, r)
return
}
@@ -157,11 +147,11 @@ func (h *CVHandler) DefaultCVShortcut(w http.ResponseWriter, r *http.Request) {
// Prepare cookies for PDF generation (short, with_skills, light mode)
cookies := map[string]string{
"cv-length": "short",
"cv-icons": "show",
"cv-language": lang,
"cv-theme": "default", // with_skills = default theme
"color-theme": "light", // Always light for PDFs
constants.CookieCVLength: constants.CVLengthShort,
constants.CookieCVIcons: constants.CVIconsShow,
constants.CookieCVLanguage: lang,
constants.CookieCVTheme: constants.CVThemeDefault, // with_skills = default theme
constants.CookieColorTheme: constants.ColorThemeLight, // Always light for PDFs
}
// Construct URL for PDF generation
@@ -180,9 +170,9 @@ func (h *CVHandler) DefaultCVShortcut(w http.ResponseWriter, r *http.Request) {
filename := filepath.Base(path) // cv-jamr-2025-en.pdf
// Set response headers with shortcut filename
w.Header().Set("Content-Type", "application/pdf")
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename))
w.Header().Set("Content-Length", fmt.Sprintf("%d", len(pdfData)))
w.Header().Set(constants.HeaderContentType, constants.ContentTypePDF)
w.Header().Set(constants.HeaderContentDisposition, fmt.Sprintf("attachment; filename=%s", filename))
w.Header().Set(constants.HeaderContentLength, fmt.Sprintf("%d", len(pdfData)))
// Write PDF data
if _, err := w.Write(pdfData); err != nil {