diff --git a/README.md b/README.md index 4d1e647..bc7ced8 100644 --- a/README.md +++ b/README.md @@ -6,12 +6,13 @@ Edmonton, Alberta) Built with [Fresh](https://fresh.deno.dev/) and [Deno](https://deno.land/) ``` -deno task start +deno task dev ``` Public data comes from City of Edmonton's open data portal. - `https://data.edmonton.ca/City-Administration/Property-Assessment-Data-Historical-/qi6a-xuwt` +- `https://data.edmonton.ca/City-Administration/Property-Assessment-Data-Current-Calendar-Year-/q7d6-ambg` ### Bugs & features diff --git a/deno.json b/deno.json index 8b38b4a..5d1a77c 100644 --- a/deno.json +++ b/deno.json @@ -1,12 +1,13 @@ { "tasks": { - "dev": "deno run -A --watch=static/,routes/ dev.ts", + "dev": "deno run -A --watch=sr/static/,src/routes/ src/dev.ts", "build": "deno run -A dev.ts build", "start": "deno run -A main.ts", "update": "deno run -A -r jsr:@fresh/update ." }, "imports": { "$fresh/": "https://deno.land/x/fresh@1.7.3/", + "@valibot/valibot": "jsr:@valibot/valibot@^0.42.1", "chartjs": "https://esm.sh/chart.js@4.1.1", "preact": "npm:preact@^10.24.1", "tailwindcss": "npm:tailwindcss@^3.4.14" @@ -26,4 +27,4 @@ "exclude": [ "**/_fresh/*" ] -} \ No newline at end of file +} diff --git a/dev.ts b/dev.ts deleted file mode 100755 index 029ac0d..0000000 --- a/dev.ts +++ /dev/null @@ -1,4 +0,0 @@ -import dev from "$fresh/dev.ts"; -import config from "./fresh.config.ts"; - -await dev(import.meta.url, "./main.ts", config); \ No newline at end of file diff --git a/routes/[id].tsx b/routes/[id].tsx deleted file mode 100644 index 934602e..0000000 --- a/routes/[id].tsx +++ /dev/null @@ -1,95 +0,0 @@ -import type { Handlers, PageProps } from "$fresh/server.ts"; -import { Head } from "$fresh/runtime.ts"; - -import PageLayout from "../components/page_layout.tsx"; -import AssessmentChart from "../islands/assessment_chart.tsx"; - -import { Consumer } from "../src/soda_client.ts"; -import type { PropertyHistory } from "../src/property_history.model.ts"; -import type { PropertyInfo } from "../src/property_info.model.ts"; -import { formatAddress } from "../src/format_address.ts"; -import TopActionBar from "../components/top_action_bar.tsx"; - -type Property = { - info: PropertyInfo | undefined; - history: PropertyHistory[]; -}; - -export const handler: Handlers = { - async GET(_, ctx) { - const { id } = ctx.params; - - const queryInfo = async (accountNumber: string) => { - const consumer = new Consumer("https://data.edmonton.ca", { - datasetId: "dkk9-cj3x", - }); - - const results = await consumer.query() - .where(`account_number = '${accountNumber}'`) - .limit(10) - .getRows(); - - return results.shift(); - }; - - const queryHistory = async (accountNumber: string) => { - const consumer = new Consumer("https://data.edmonton.ca", { - datasetId: "qi6a-xuwt", - }); - - const results = await consumer - .query() - .where(`account_number = '${accountNumber}'`) - .limit(20) - .getRows(); - - // todo(hubert): add .order() to the query instead of sorting after - results.sort((a, b) => a.assessment_year - b.assessment_year); - - return results; - }; - - const property: Property = { - info: await queryInfo(id), - history: await queryHistory(id), - }; - - return ctx.render(property); - }, -}; - -export default function PropertyPage( - { params, data }: PageProps, -) { - if (!data || !data.info || !data.history) { - return

Property {params} not found

; - } - - return ( - <> - - Open Property | {formatAddress(data.info)} - - - }> -
-
-

- {formatAddress(data.info)} -

-

- ${data.history.at(-1)?.assessed_value} -

- - {data.history.at(-1)?.assessment_year} - -
- -
- -
-
-
- - ); -} diff --git a/routes/index.tsx b/routes/index.tsx deleted file mode 100644 index 17fb5b2..0000000 --- a/routes/index.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { Head } from "$fresh/runtime.ts"; -import AppTemplate from "../components/page_layout.tsx"; -import TopNav from "../components/top_nav.tsx"; -import AddressSearch from "../islands/address_search.tsx"; - -export default function HomePage() { - return ( - <> - - Open Property | Edmonton - - - }> - - - - ); -} diff --git a/components/icons/data_icon.tsx b/src/components/icons/data_icon.tsx similarity index 100% rename from components/icons/data_icon.tsx rename to src/components/icons/data_icon.tsx diff --git a/components/icons/github_icon.tsx b/src/components/icons/github_icon.tsx similarity index 100% rename from components/icons/github_icon.tsx rename to src/components/icons/github_icon.tsx diff --git a/components/icons/search_icon.tsx b/src/components/icons/search_icon.tsx similarity index 100% rename from components/icons/search_icon.tsx rename to src/components/icons/search_icon.tsx diff --git a/components/icons/share_icon.tsx b/src/components/icons/share_icon.tsx similarity index 100% rename from components/icons/share_icon.tsx rename to src/components/icons/share_icon.tsx diff --git a/src/dev.ts b/src/dev.ts new file mode 100755 index 0000000..8ba59f7 --- /dev/null +++ b/src/dev.ts @@ -0,0 +1,4 @@ +import dev from "$fresh/dev.ts"; +import config from "../src/fresh.config.ts"; + +await dev(import.meta.url, "./main.ts", config); diff --git a/fresh.config.ts b/src/fresh.config.ts similarity index 73% rename from fresh.config.ts rename to src/fresh.config.ts index 9c42c42..93dfe0c 100644 --- a/fresh.config.ts +++ b/src/fresh.config.ts @@ -1,10 +1,10 @@ import { defineConfig } from "$fresh/server.ts"; import tailwind from "$fresh/plugins/tailwind.ts"; -import googleAnalyticsPlugin from "./plugins/google_analytics.ts"; +import googleAnalyticsPlugin from "./lib/plugins/google_analytics.ts"; export default defineConfig({ plugins: [ tailwind(), googleAnalyticsPlugin("G-LG7XQ7H5RG"), ], -}); \ No newline at end of file +}); diff --git a/fresh.gen.ts b/src/fresh.gen.ts similarity index 57% rename from fresh.gen.ts rename to src/fresh.gen.ts index babb980..ab6e170 100644 --- a/fresh.gen.ts +++ b/src/fresh.gen.ts @@ -4,8 +4,11 @@ import * as $_id_ from "./routes/[id].tsx"; import * as $_app from "./routes/_app.tsx"; +import * as $_layout from "./routes/_layout.tsx"; import * as $index from "./routes/index.tsx"; -import * as $address_search from "./islands/address_search.tsx"; +import * as $address_search_address_search from "./islands/address_search/address_search.tsx"; +import * as $address_search_search_input from "./islands/address_search/search_input.tsx"; +import * as $address_search_search_options from "./islands/address_search/search_options.tsx"; import * as $assessment_chart from "./islands/assessment_chart.tsx"; import * as $google_map from "./islands/google_map.tsx"; import type { Manifest } from "$fresh/server.ts"; @@ -14,10 +17,15 @@ const manifest = { routes: { "./routes/[id].tsx": $_id_, "./routes/_app.tsx": $_app, + "./routes/_layout.tsx": $_layout, "./routes/index.tsx": $index, }, islands: { - "./islands/address_search.tsx": $address_search, + "./islands/address_search/address_search.tsx": + $address_search_address_search, + "./islands/address_search/search_input.tsx": $address_search_search_input, + "./islands/address_search/search_options.tsx": + $address_search_search_options, "./islands/assessment_chart.tsx": $assessment_chart, "./islands/google_map.tsx": $google_map, }, diff --git a/islands/address_search.tsx b/src/islands/address_search/address_search.tsx similarity index 88% rename from islands/address_search.tsx rename to src/islands/address_search/address_search.tsx index 07e1532..00ea0f9 100644 --- a/islands/address_search.tsx +++ b/src/islands/address_search/address_search.tsx @@ -1,9 +1,9 @@ import { useState } from "preact/hooks"; -import SearchInput from "../components/search_input.tsx"; -import SearchOptions from "../components/search_options.tsx"; -import { useSearchResults } from "../src/use_search_results.ts"; +import { SearchInput } from "./search_input.tsx"; +import { SearchOptions } from "./search_options.tsx"; +import { useSearchResults } from "../../lib/use_search_results.ts"; -export default function AddressSearch() { +export function AddressSearch() { const [search, setSearch] = useState(); const [searchDelay, setSearchDelay] = useState(Number.NaN); const [loading, setLoading] = useState(false); @@ -54,7 +54,7 @@ export default function AddressSearch() { {!loading && results && results?.length > 0 && ( -
+
)} diff --git a/components/search_input.tsx b/src/islands/address_search/search_input.tsx similarity index 90% rename from components/search_input.tsx rename to src/islands/address_search/search_input.tsx index 7d1d406..b757781 100644 --- a/components/search_input.tsx +++ b/src/islands/address_search/search_input.tsx @@ -1,7 +1,7 @@ import type { JSX } from "preact"; -import SearchIcon from "./icons/search_icon.tsx"; +import SearchIcon from "../../components/icons/search_icon.tsx"; -export default function SearchInput( +export function SearchInput( props: JSX.HTMLAttributes, ) { return ( diff --git a/components/search_options.tsx b/src/islands/address_search/search_options.tsx similarity index 81% rename from components/search_options.tsx rename to src/islands/address_search/search_options.tsx index 8489781..ce76c68 100644 --- a/components/search_options.tsx +++ b/src/islands/address_search/search_options.tsx @@ -1,7 +1,7 @@ -import { formatAddress } from "../src/format_address.ts"; -import type { PropertyInfo } from "../src/property_info.model.ts"; +import { formatAddress } from "../../lib/format_address.ts"; +import type { PropertyInfo } from "../../lib/data.edmonton.ca/property_info.type.ts"; -export default function SearchOptions( +export function SearchOptions( { searchResults: properties }: { searchResults: PropertyInfo[] }, ) { return ( diff --git a/islands/assessment_chart.tsx b/src/islands/assessment_chart.tsx similarity index 71% rename from islands/assessment_chart.tsx rename to src/islands/assessment_chart.tsx index ed12308..5c601e2 100644 --- a/islands/assessment_chart.tsx +++ b/src/islands/assessment_chart.tsx @@ -5,10 +5,10 @@ import { type ChartOptions, registerables, } from "chartjs"; -import type { PropertyHistory } from "../src/property_history.model.ts"; +import type { Property } from "../lib/data.edmonton.ca/property.type.ts"; export default function AssessmentChart( - props: { histories: PropertyHistory[] }, + props: { histories?: Partial[] }, ) { const canvas = useRef(null); @@ -32,11 +32,14 @@ export default function AssessmentChart( { weight: 100, label: "assessment", - data: props.histories.map(asPoints), + data: props.histories?.map((history) => ({ + x: history.assessment_year?.toString(), + y: history.assessed_value, + })), clip: 20, pointRadius: 4, cubicInterpolationMode: "monotone", - } as ChartDataset, + } as ChartDataset<"line", { x: string; y: number }[]>, ], }, }); @@ -44,10 +47,3 @@ export default function AssessmentChart( return ; } - -function asPoints(history: PropertyHistory) { - return { - x: history.assessment_year, - y: history.assessed_value, - }; -} diff --git a/islands/google_map.tsx b/src/islands/google_map.tsx similarity index 100% rename from islands/google_map.tsx rename to src/islands/google_map.tsx diff --git a/src/lib/data.edmonton.ca/property.type.ts b/src/lib/data.edmonton.ca/property.type.ts new file mode 100644 index 0000000..1a7eebe --- /dev/null +++ b/src/lib/data.edmonton.ca/property.type.ts @@ -0,0 +1,33 @@ +import * as v from "@valibot/valibot"; + +/** Historical Property Data + * https://data.edmonton.ca/City-Administration/Property-Assessment-Data-Historical-/qi6a-xuwt + */ +export const PropertySchema = v.object({ + account_number: v.string(), + assessment_year: v.pipe(v.string(), v.transform(Number)), + suite: v.string(), + house_number: v.string(), + street_name: v.string(), + legal_description: v.string(), + latitude: v.pipe(v.string(), v.transform(Number)), + longitude: v.pipe(v.string(), v.transform(Number)), + point_location: v.object({ + type: v.string("Point"), + coordinates: v.tuple([v.number(), v.number()]), + }), + neighbourhood_name: v.string(), + year_built: v.pipe(v.string(), v.transform(Number)), + garage: v.union([v.literal("Y"), v.literal("N")]), + zoning: v.string(), + lot_size: v.pipe(v.string(), v.transform(Number)), + assessed_value: v.pipe(v.string(), v.transform(Number)), + mill_class_1: v.string(), + tax_class_pct_1: v.string(), + mill_class_2: v.string(), + tax_class_pct_2: v.string(), + mill_class_3: v.string(), + tax_class_pct_3: v.string(), +}); + +export type Property = v.InferOutput; diff --git a/src/property_info.model.ts b/src/lib/data.edmonton.ca/property_info.type.ts similarity index 93% rename from src/property_info.model.ts rename to src/lib/data.edmonton.ca/property_info.type.ts index aa52c9d..b4c2da0 100644 --- a/src/property_info.model.ts +++ b/src/lib/data.edmonton.ca/property_info.type.ts @@ -2,7 +2,7 @@ * Property Information Current Calendar Year * https://data.edmonton.ca/City-Administration/Property-Information-Current-Calendar-Year-/dkk9-cj3x */ -export interface PropertyInfo { +export type PropertyInfo = { account_number: string; suite: string; house_number: string; @@ -18,4 +18,4 @@ export interface PropertyInfo { ward: string; latitude: number; longitude: number; -} +}; diff --git a/src/soda_client.ts b/src/lib/data.edmonton.ca/soda_client.ts similarity index 93% rename from src/soda_client.ts rename to src/lib/data.edmonton.ca/soda_client.ts index 6f7eebb..7ff63e2 100644 --- a/src/soda_client.ts +++ b/src/lib/data.edmonton.ca/soda_client.ts @@ -9,9 +9,9 @@ interface SoqlComponents extends Record { $limit: string; } -export interface SodaOptions { +export type SodaOptions = { datasetId: string; -} +}; export const and = (...clause: string[]) => `AND (${clause.join(" ")})`; @@ -84,12 +84,9 @@ class Query { return this; } - /** - * @returns https://data.edmonton.ca/resource/qi6a-xuwt.json - */ getUrl() { const dataSite = this._consumer.dataSite; - const url = new URL(`${dataSite}/resource/${this._datasetId}.json`); + const url = new URL(`/resource/${this._datasetId}.json`, dataSite); url.search = this.buildSoqlQuery().toString(); return url; } diff --git a/src/format_address.ts b/src/lib/format_address.ts similarity index 50% rename from src/format_address.ts rename to src/lib/format_address.ts index 197be9d..a83d65e 100644 --- a/src/format_address.ts +++ b/src/lib/format_address.ts @@ -1,7 +1,7 @@ -import { PropertyHistory } from "./property_history.model.ts"; -import { PropertyInfo } from "./property_info.model.ts"; +import type { Property } from "./data.edmonton.ca/property.type.ts"; +import type { PropertyInfo } from "./data.edmonton.ca/property_info.type.ts"; -export function formatAddress(property: PropertyInfo | PropertyHistory) { +export function formatAddress(property: PropertyInfo | Property) { let address = ""; if (property.suite) { address += `#${property.suite} `; diff --git a/plugins/google_analytics.ts b/src/lib/plugins/google_analytics.ts similarity index 94% rename from plugins/google_analytics.ts rename to src/lib/plugins/google_analytics.ts index 0ab707b..4770cc1 100644 --- a/plugins/google_analytics.ts +++ b/src/lib/plugins/google_analytics.ts @@ -1,4 +1,4 @@ -import { Plugin } from "$fresh/server.ts"; +import type { Plugin } from "$fresh/server.ts"; export default function googleAnalyticsPlugin(tag: string): Plugin { const googleAnalyticsScript = `data:application/javascript, diff --git a/src/use_search_results.ts b/src/lib/use_search_results.ts similarity index 65% rename from src/use_search_results.ts rename to src/lib/use_search_results.ts index 9c9ea08..4156240 100644 --- a/src/use_search_results.ts +++ b/src/lib/use_search_results.ts @@ -1,13 +1,13 @@ import { useEffect, useState } from "preact/hooks"; -import { and, Consumer, or } from "./soda_client.ts"; -import { PropertyInfo } from "./property_info.model.ts"; +import { and, Consumer, or } from "./data.edmonton.ca/soda_client.ts"; +import type { PropertyInfo } from "./data.edmonton.ca/property_info.type.ts"; function useSearchResults(search: string | undefined, done: () => void) { const maxResults = 5; const [results, setResults] = useState(); - const consumer = new Consumer("https://data.edmonton.ca", { + const historical = new Consumer("https://data.edmonton.ca", { datasetId: "dkk9-cj3x", }); @@ -17,13 +17,13 @@ function useSearchResults(search: string | undefined, done: () => void) { return; } - search = search.toUpperCase(); + const searchValue = search?.toUpperCase(); const hasSpaceQuery = async () => { - const values = search?.split(/\s/); + const values = searchValue?.split(/\s/); if (!values) return; - const result = await consumer + const result = await historical .query() .where( `suite='${values[0]}'`, @@ -42,12 +42,12 @@ function useSearchResults(search: string | undefined, done: () => void) { }; const noSpaceQuery = async () => { - const result = await consumer + const result = await historical .query() .where( - `suite like '${search}%'`, - or(`house_number like '${search}%'`), - or(`street_name like '${search}%'`), + `suite like '${searchValue}%'`, + or(`house_number like '${searchValue}%'`), + or(`street_name like '${searchValue}%'`), ) .limit(maxResults) .getRows(); @@ -56,12 +56,12 @@ function useSearchResults(search: string | undefined, done: () => void) { done(); }; - if (!/\s/g.test(search || "")) { + if (!/\s/g.test(searchValue || "")) { noSpaceQuery(); } else { hasSpaceQuery(); } - }, [search]); + }, [search, historical, done]); return results; } diff --git a/main.ts b/src/main.ts similarity index 100% rename from main.ts rename to src/main.ts diff --git a/src/property_history.model.ts b/src/property_history.model.ts deleted file mode 100644 index 8f00db2..0000000 --- a/src/property_history.model.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* eslint @typescript-eslint/naming-convention: "off" */ -/** Historical Property Data - * https://data.edmonton.ca/City-Administration/Property-Assessment-Data-Historical-/qi6a-xuwt - */ -export interface PropertyHistory { - account_number: string; - assessment_year: number; - suite: string; - house_number: string; - street_name: string; - legal_description: string; - latitude: number; - longitude: number; - // point - neighbourhood_name: string; - year_built: number; - garage: "Y" | "N"; - zoning: string; - lot_size: number; - assessed_value: number; - /** Assessment Class 1 */ - mill_class_1: string; - /** The percentage of buildings or areas on the property making up the first assessment class */ - tax_class_pct_1: string; - /** Assessment Class 2 */ - mill_class_2: string; - /** The percentage of buildings or areas on the property making up the second assessment class */ - tax_class_pct_2: string; - /** Assessment Class 3 */ - mill_class_3: string; - /** The percentage of buildings or areas on the property making up the third assessment class */ - tax_class_pct_3: string; -} diff --git a/components/top_action_bar.tsx b/src/routes/(_components)/top_action_bar.tsx similarity index 83% rename from components/top_action_bar.tsx rename to src/routes/(_components)/top_action_bar.tsx index e4eb7ea..33640e5 100644 --- a/components/top_action_bar.tsx +++ b/src/routes/(_components)/top_action_bar.tsx @@ -1,6 +1,6 @@ -import SearchIcon from "./icons/search_icon.tsx"; +import SearchIcon from "../../components/icons/search_icon.tsx"; -export default function TopActionBar() { +export function TopActionBar() { return (

@@ -14,6 +14,7 @@ export default function TopNav() { aria-label="github repository link" target="_blank" title="Github repository" + rel="noreferrer" > @@ -23,6 +24,7 @@ export default function TopNav() { aria-label="City of Edmonton Property Assessment Data" target="_blank" title="Open Edmonton Data Set" + rel="noreferrer" > diff --git a/src/routes/[id].tsx b/src/routes/[id].tsx new file mode 100644 index 0000000..fc404d2 --- /dev/null +++ b/src/routes/[id].tsx @@ -0,0 +1,127 @@ +import type { Handlers, PageProps } from "$fresh/server.ts"; +import { Head } from "$fresh/runtime.ts"; + +import AssessmentChart from "../islands/assessment_chart.tsx"; + +import { Consumer } from "../lib/data.edmonton.ca/soda_client.ts"; +import { + type Property, + PropertySchema, +} from "../lib/data.edmonton.ca/property.type.ts"; +import type { PropertyInfo } from "../lib/data.edmonton.ca/property_info.type.ts"; +import { formatAddress } from "../lib/format_address.ts"; +import { TopActionBar } from "./(_components)/top_action_bar.tsx"; +import * as v from "@valibot/valibot"; + +type Response = { + info: PropertyInfo | undefined; + history: Partial[]; +}; + +export const handler: Handlers = { + async GET(_, ctx) { + const { id } = ctx.params; + + const queryInfo = async (accountNumber: string) => { + const consumer = new Consumer("https://data.edmonton.ca", { + datasetId: "dkk9-cj3x", + }); + + const results = await consumer.query() + .where(`account_number = '${accountNumber}'`) + .limit(10) + .getRows(); + + return results.shift(); + }; + + const queryCurrent = async (accountNumber: string) => { + const consumer = new Consumer("https://data.edmonton.ca", { + datasetId: "q7d6-ambg", + }); + + const results = await consumer + .query() + .where(`account_number = '${accountNumber}'`) + .limit(1) + .getRows(); + + const current = v.parse(v.partial(PropertySchema), results.at(0)); + + return current; + }; + + const queryHistory = async (accountNumber: string) => { + const consumer = new Consumer("https://data.edmonton.ca", { + datasetId: "qi6a-xuwt", + }); + + const results = await consumer + .query() + .where(`account_number = '${accountNumber}'`) + .limit(20) + .getRows(); + + // todo(hubert): add .order() to the query instead of sorting after + const mapped = results + .toSorted((a, b) => + Number(a.assessment_year) - Number(b.assessment_year) + ) + .map((p) => v.parse(v.partial(PropertySchema), p)); + + return mapped; + }; + + const history = await queryHistory(id); + const current = await queryCurrent(id); + + if (current) { + const lastYear = history.at(-1)?.assessment_year; + current.assessment_year = Number(lastYear) + 1; + history.push(current); + } + + const response: Response = { + info: await queryInfo(id), + history: history, + }; + + return ctx.render(response); + }, +}; + +export default function PropertyPage( + { params, data }: PageProps, +) { + if (!data || !data.info || !data.history) { + return

Property {params} not found

; + } + + return ( + <> + + Open Property | {formatAddress(data.info)} + + + + +
+
+

+ {formatAddress(data.info)} +

+

+ ${data.history.at(-1)?.assessed_value} +

+ + {data.history.at(-1)?.assessment_year} + +
+ +
+ +
+
+ + ); +} diff --git a/routes/_app.tsx b/src/routes/_app.tsx similarity index 100% rename from routes/_app.tsx rename to src/routes/_app.tsx diff --git a/components/page_layout.tsx b/src/routes/_layout.tsx similarity index 58% rename from components/page_layout.tsx rename to src/routes/_layout.tsx index f5b969c..c273a6e 100644 --- a/components/page_layout.tsx +++ b/src/routes/_layout.tsx @@ -1,16 +1,15 @@ -import type { ComponentChildren } from "preact"; +import type { PageProps } from "$fresh/server.ts"; +import { TopNav } from "./(_components)/top_nav.tsx"; -export default function PageLayout( - props: { children: ComponentChildren; header: ComponentChildren }, -) { +export default function Layout({ Component }: PageProps) { return ( <>
- {props.header} +
- {props.children} +
diff --git a/src/routes/index.tsx b/src/routes/index.tsx new file mode 100644 index 0000000..15a1c5b --- /dev/null +++ b/src/routes/index.tsx @@ -0,0 +1,14 @@ +import { Head } from "$fresh/runtime.ts"; +import { AddressSearch } from "../islands/address_search/address_search.tsx"; + +export default function HomePage() { + return ( + <> + + Open Property | Edmonton + + + + + ); +} diff --git a/static/favicon.ico b/src/static/favicon.ico similarity index 100% rename from static/favicon.ico rename to src/static/favicon.ico diff --git a/static/styles.css b/src/static/styles.css similarity index 64% rename from static/styles.css rename to src/static/styles.css index bd6213e..b5c61c9 100644 --- a/static/styles.css +++ b/src/static/styles.css @@ -1,3 +1,3 @@ @tailwind base; @tailwind components; -@tailwind utilities; \ No newline at end of file +@tailwind utilities; diff --git a/static/logo.svg b/static/logo.svg deleted file mode 100644 index ef2fbe4..0000000 --- a/static/logo.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/tailwind.config.ts b/tailwind.config.ts index e5bed31..2492495 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -1,7 +1,7 @@ -import type { Config } from "tailwindcss"; +import type { Config } from "tailwindcss"; export default { content: [ - "{routes,islands,components}/**/*.{ts,tsx}", + "src/**/*.{ts,tsx}", ], -} satisfies Config; \ No newline at end of file +} satisfies Config;