create-qwik 0.0.38 → 0.0.39-dev20220805031634

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/package.json +1 -1
  2. package/starters/apps/base/package.json +7 -7
  3. package/starters/apps/base/src/entry.dev.tsx +4 -2
  4. package/starters/apps/base/src/entry.ssr.tsx +3 -3
  5. package/starters/apps/blank/src/entry.express.tsx +10 -3
  6. package/starters/apps/blank/src/entry.ssr.tsx +3 -3
  7. package/starters/apps/qwik-city/package.json +1 -1
  8. package/starters/apps/qwik-city/src/components/body/body.tsx +2 -2
  9. package/starters/apps/qwik-city/src/components/breadcrumbs/breadcrumbs.css +25 -0
  10. package/starters/apps/qwik-city/src/components/breadcrumbs/breadcrumbs.tsx +77 -0
  11. package/starters/apps/qwik-city/src/components/counter/counter.tsx +2 -2
  12. package/starters/apps/qwik-city/src/components/footer/footer.css +1 -1
  13. package/starters/apps/qwik-city/src/components/footer/footer.tsx +3 -1
  14. package/starters/apps/qwik-city/src/components/header/header.css +10 -1
  15. package/starters/apps/qwik-city/src/components/header/header.tsx +24 -32
  16. package/starters/apps/qwik-city/src/components/menu/menu.css +10 -0
  17. package/starters/apps/qwik-city/src/components/menu/menu.tsx +5 -5
  18. package/starters/apps/qwik-city/src/global.css +21 -12
  19. package/starters/apps/qwik-city/src/root.tsx +1 -1
  20. package/starters/apps/qwik-city/src/routes/about-us.tsx +2 -4
  21. package/starters/apps/qwik-city/src/routes/api/[org]/[user].json/index.ts +12 -23
  22. package/starters/apps/qwik-city/src/routes/api/_layout-foo/index.tsx +18 -24
  23. package/starters/apps/qwik-city/src/routes/api/data.json.ts +6 -9
  24. package/starters/apps/qwik-city/src/routes/api/index@foo.tsx +7 -4
  25. package/starters/apps/qwik-city/src/routes/blog/[...slug].tsx +28 -5
  26. package/starters/apps/qwik-city/src/routes/blog/_layout/index.tsx +2 -2
  27. package/starters/apps/qwik-city/src/routes/dashboard/index.tsx +8 -0
  28. package/starters/apps/qwik-city/src/routes/docs/[category]/[id]/index.tsx +14 -6
  29. package/starters/apps/qwik-city/src/routes/docs/{_layout/docs.css → _layout!/index.css} +2 -1
  30. package/starters/apps/qwik-city/src/routes/docs/_layout!/index.tsx +31 -0
  31. package/starters/apps/qwik-city/src/routes/docs/_menu.md +4 -2
  32. package/starters/apps/qwik-city/src/routes/docs/getting-started.md +44 -0
  33. package/starters/apps/qwik-city/src/routes/docs/index.tsx +2 -4
  34. package/starters/apps/qwik-city/src/routes/docs/{introduction → overview}/index.md +2 -2
  35. package/starters/apps/qwik-city/src/routes/index.tsx +6 -1
  36. package/starters/apps/qwik-city/src/routes/products/[id].tsx +122 -0
  37. package/starters/features/react/package.json +1 -1
  38. package/starters/features/react/src/entry.ssr.tsx +1 -1
  39. package/starters/features/tailwindcss/{postcss.config.js → postcss.config.cjs} +0 -0
  40. package/starters/features/tailwindcss/{tailwind.config.js → tailwind.config.cjs} +0 -0
  41. package/starters/servers/cloudflare-pages/src/entry.cloudflare.tsx +4 -50
  42. package/starters/servers/express/package.json +1 -1
  43. package/starters/servers/express/src/entry.express.tsx +19 -8
  44. package/starters/servers/{netlify → netlify-edge}/.node-version +0 -0
  45. package/starters/servers/{netlify → netlify-edge}/README.md +0 -0
  46. package/starters/servers/{netlify → netlify-edge}/netlify.toml +0 -0
  47. package/starters/servers/{netlify → netlify-edge}/package.json +0 -0
  48. package/starters/servers/{netlify → netlify-edge}/public/_headers +0 -0
  49. package/starters/servers/netlify-edge/src/entry.netlify.ts +6 -0
  50. package/starters/servers/{netlify → netlify-edge}/tsconfig.json +0 -0
  51. package/starters/apps/qwik-city/src/routes/__auth/_layout.tsx +0 -17
  52. package/starters/apps/qwik-city/src/routes/__auth/sign-in.tsx +0 -25
  53. package/starters/apps/qwik-city/src/routes/__auth/sign-up.tsx +0 -29
  54. package/starters/apps/qwik-city/src/routes/docs/_layout/index.tsx +0 -23
  55. package/starters/apps/qwik-city/src/routes/docs/getting-started.mdx +0 -32
  56. package/starters/servers/netlify/src/entry.netlify.ts +0 -27
@@ -1,13 +1,36 @@
1
- import { component$, Host } from '@builder.io/qwik';
2
- import { useLocation } from '@builder.io/qwik-city';
1
+ import { component$, Host, Resource } from '@builder.io/qwik';
2
+ import { useEndpoint, DocumentHead, EndpointHandler } from '@builder.io/qwik-city';
3
3
 
4
4
  export default component$(() => {
5
- const { pathname, params } = useLocation();
5
+ const resource = useEndpoint<typeof onGet>();
6
6
 
7
7
  return (
8
8
  <Host>
9
- <h1>Blog {pathname}</h1>
10
- <p>Slug: {params.slug}</p>
9
+ <Resource
10
+ resource={resource}
11
+ onResolved={(blog) => (
12
+ <>
13
+ <h1>{blog.blogTitle}</h1>
14
+ <p>{blog.blogContent}</p>
15
+ </>
16
+ )}
17
+ />
11
18
  </Host>
12
19
  );
13
20
  });
21
+
22
+ export const onGet: EndpointHandler<EndpointData> = async ({ params, request }) => {
23
+ return {
24
+ blogTitle: `Blog: ${params.slug}`,
25
+ blogContent: `${params.slug}, ${request.url}`,
26
+ };
27
+ };
28
+
29
+ export const head: DocumentHead<EndpointData> = ({ data }) => {
30
+ return { title: data?.blogTitle };
31
+ };
32
+
33
+ export interface EndpointData {
34
+ blogTitle: string;
35
+ blogContent: string;
36
+ }
@@ -9,10 +9,10 @@ export default component$(() => {
9
9
  <aside class="blog-menu">
10
10
  <ul>
11
11
  <li>
12
- <a href="/blog/how-to-use-a-toaster">How to use a toaster</a>
12
+ <a href="/blog/what-is-resumability">What Is Resumability?</a>
13
13
  </li>
14
14
  <li>
15
- <a href="/blog/how-to-crack-an-egg">How to crack an egg</a>
15
+ <a href="/blog/serializing-props">Serializing Props</a>
16
16
  </li>
17
17
  </ul>
18
18
  </aside>
@@ -1,9 +1,17 @@
1
1
  import { component$, Host } from '@builder.io/qwik';
2
+ import type { DocumentHead } from '@builder.io/qwik-city';
2
3
 
3
4
  export default component$(() => {
4
5
  return (
5
6
  <Host>
6
7
  <h1>Dashboard</h1>
8
+ <p>
9
+ <a href="/sign-out">Sign Out</a>
10
+ </p>
7
11
  </Host>
8
12
  );
9
13
  });
14
+
15
+ export const head: DocumentHead = {
16
+ title: 'Dashboard',
17
+ };
@@ -1,15 +1,23 @@
1
1
  import { component$, Host } from '@builder.io/qwik';
2
- import { useLocation } from '@builder.io/qwik-city';
2
+ import { useLocation, DocumentHead } from '@builder.io/qwik-city';
3
3
 
4
4
  export default component$(() => {
5
- const loc = useLocation();
5
+ const { pathname, params } = useLocation();
6
6
 
7
7
  return (
8
8
  <Host>
9
- <h1>Docs</h1>
10
- <p>pathname: {loc.pathname}</p>
11
- <p>category: {loc.params.category}</p>
12
- <p>id: {loc.params.id}</p>
9
+ <h1>
10
+ Docs: {params.category} {params.id}
11
+ </h1>
12
+ <p>pathname: {pathname}</p>
13
+ <p>category: {params.category}</p>
14
+ <p>id: {params.id}</p>
13
15
  </Host>
14
16
  );
15
17
  });
18
+
19
+ export const head: DocumentHead = ({ params }) => {
20
+ return {
21
+ title: `${params.category} ${params.id}`,
22
+ };
23
+ };
@@ -1,7 +1,8 @@
1
- .docs {
1
+ .docs main {
2
2
  display: grid;
3
3
  grid-template-columns: 200px 1fr;
4
4
  padding: 0;
5
+ margin: 0;
5
6
  }
6
7
 
7
8
  .docs-content {
@@ -0,0 +1,31 @@
1
+ import { component$, Host, Slot, useStyles$ } from '@builder.io/qwik';
2
+ import type { DocumentHead } from '@builder.io/qwik-city';
3
+ import { Breadcrumbs } from '../../../components/breadcrumbs/breadcrumbs';
4
+ import Footer from '../../../components/footer/footer';
5
+ import Header from '../../../components/header/header';
6
+ import { Menu } from '../../../components/menu/menu';
7
+ import styles from './index.css?inline';
8
+
9
+ export default component$(() => {
10
+ useStyles$(styles);
11
+
12
+ return (
13
+ <Host class="docs full-screen">
14
+ <Header />
15
+ <main>
16
+ <Menu />
17
+ <section class="docs-content">
18
+ <Breadcrumbs />
19
+ <Slot />
20
+ <Footer />
21
+ </section>
22
+ </main>
23
+ </Host>
24
+ );
25
+ });
26
+
27
+ export const head: DocumentHead = ({ head }) => {
28
+ return {
29
+ title: `Docs: ${head.title}`,
30
+ };
31
+ };
@@ -1,9 +1,11 @@
1
1
  # Docs
2
2
 
3
- ## Getting Started
3
+ ## Introduction
4
4
 
5
- - [Introduction](introduction/index.md)
5
+ - [Overview](overview/index.md)
6
+ - [Getting Started](getting-started.md)
6
7
 
7
8
  ## Components
8
9
 
9
10
  - [Basics](/docs/components/basics)
11
+ - [Listeners](/docs/components/listeners)
@@ -0,0 +1,44 @@
1
+ ---
2
+ title: Getting Started
3
+ ---
4
+
5
+ # Getting Started
6
+
7
+ ## Creating an app using the CLI
8
+
9
+ The first step is to create an application. Qwik comes with a CLI that allows you to create a basic working skeleton of an application. We will use the CLI to create a Todo sample app, and we will use that application to do a walk-through of Qwik so that you can familiarize yourself with it.
10
+
11
+ ## Running in development
12
+
13
+ Once the application is download.
14
+
15
+ 1. Change into the directory created by the `npm create qwik@latest`.
16
+
17
+ ```shell
18
+ cd qwik-todo
19
+ ```
20
+
21
+ 2. Install NPM modules:
22
+
23
+ ```shell
24
+ npm install
25
+ ```
26
+
27
+ 3. Invoke the dev server
28
+
29
+ ```shell
30
+ npm start
31
+ ```
32
+
33
+ 4. You should see a server running with your To-do application
34
+
35
+ ```shell
36
+ vite v2.8.6 dev server running at:
37
+
38
+ > Local: http://localhost:3000/
39
+ > Network: use `--host` to expose
40
+
41
+ ready in 157ms.
42
+ ```
43
+
44
+ 5. Visit http://localhost:3000/ to explore the To-do app.
@@ -9,8 +9,6 @@ export default component$(() => {
9
9
  );
10
10
  });
11
11
 
12
- export const head: DocumentHead = () => {
13
- return {
14
- title: 'Welcome!',
15
- };
12
+ export const head: DocumentHead = {
13
+ title: 'Welcome!',
16
14
  };
@@ -1,7 +1,7 @@
1
1
  ---
2
- title: Introduction
2
+ title: Overview
3
3
  ---
4
4
 
5
- # Introduction
5
+ # Overview
6
6
 
7
7
  Qwik is a new kind of web framework that can deliver instant loading web applications at any size or complexity. Your sites and apps can boot with less than 1kb of JS (_including_ your code, regardless of complexity), and achieve unheard of performance at scale.
@@ -1,11 +1,16 @@
1
1
  import { component$, Host } from '@builder.io/qwik';
2
+ import type { DocumentHead } from '@builder.io/qwik-city';
2
3
 
3
4
  export default component$(() => {
4
5
  return (
5
6
  <Host>
6
- <h1>Welcome to QwikCity</h1>
7
+ <h1>Welcome to Qwik City</h1>
7
8
 
8
9
  <p>The meta-framework for Qwik.</p>
9
10
  </Host>
10
11
  );
11
12
  });
13
+
14
+ export const head: DocumentHead = {
15
+ title: 'Welcome to Qwik City',
16
+ };
@@ -0,0 +1,122 @@
1
+ import { Resource, component$, Host } from '@builder.io/qwik';
2
+ import { useEndpoint, useLocation, EndpointHandler, DocumentHead } from '@builder.io/qwik-city';
3
+ import os from 'os';
4
+
5
+ export default component$(() => {
6
+ const { params } = useLocation();
7
+
8
+ const resource = useEndpoint<typeof onGet>();
9
+
10
+ return (
11
+ <Host>
12
+ <Resource
13
+ resource={resource}
14
+ onPending={() => <p>Loading</p>}
15
+ onResolved={(product) => {
16
+ if (product == null) {
17
+ return <h1>Product "{params.id}" not found</h1>;
18
+ }
19
+
20
+ return (
21
+ <>
22
+ <h1>Product: {product.productId}</h1>
23
+ <p>Price: {product.price}</p>
24
+ <p>{product.description}</p>
25
+ </>
26
+ );
27
+ }}
28
+ />
29
+
30
+ <p>(Artificial response delay of 250ms)</p>
31
+
32
+ <hr />
33
+
34
+ <ul>
35
+ <li>
36
+ <a href="/products/jacket">Jacket</a>
37
+ </li>
38
+ <li>
39
+ <a href="/products/hat">Hat</a>
40
+ </li>
41
+ <li>
42
+ <a href="/products/shirt">T-Shirt (Redirect to /products/tshirt)</a>
43
+ </li>
44
+ <li>
45
+ <a href="/products/hoodie">Hoodie (404 Not Found)</a>
46
+ </li>
47
+ </ul>
48
+ </Host>
49
+ );
50
+ });
51
+
52
+ export const head: DocumentHead<ProductData> = ({ data }) => {
53
+ return {
54
+ title: `Product ${data.productId}, ${data.price}`,
55
+ };
56
+ };
57
+
58
+ export const onGet: EndpointHandler<EndpointData> = async ({ params, response }) => {
59
+ // Serverside Endpoint
60
+ // During SSR, this method is called directly on the server and returns the data object
61
+ // On the client, this same data can be requested with fetch() at the same URL, but also
62
+ // requires the "accept: application/json" request header.
63
+
64
+ if (params.id === 'shirt') {
65
+ // Redirect, which will skip any rendering and the server will immediately redirect
66
+ response.redirect('/products/tshirt');
67
+ return;
68
+ }
69
+
70
+ // artificially slow database call
71
+ const productData = await loadProduct(params.id);
72
+
73
+ if (!productData) {
74
+ // Product data not found
75
+ // but the data is still given to the renderer to decide what to do
76
+ response.status = 404;
77
+ return;
78
+ }
79
+
80
+ // Found the product data
81
+ // This same data is passed to the head() function
82
+ // and in the component$() it can be access with useEndpoint()
83
+ response.headers.set('Cache-Control', 'no-cache, no-store, no-fun');
84
+ return productData;
85
+ };
86
+
87
+ // our pretty awesome function to load product data
88
+ const loadProduct = (productId: string) => {
89
+ return new Promise<ProductData | null>((resolve) =>
90
+ setTimeout(() => {
91
+ const productPrice = PRODUCT_DB[productId];
92
+ if (!productPrice) {
93
+ return null;
94
+ }
95
+
96
+ const productData: ProductData = {
97
+ productId,
98
+ price: productPrice,
99
+ description: `Node ${process.versions.node} ${os.platform()} ${os.arch()} ${
100
+ os.cpus()[0].model
101
+ }`,
102
+ };
103
+
104
+ resolve(productData);
105
+ }, 250)
106
+ );
107
+ };
108
+
109
+ // Our pretty awesome database of prices
110
+ const PRODUCT_DB: Record<string, string> = {
111
+ hat: '$21.96',
112
+ jacket: '$48.96',
113
+ tshirt: '$18.96',
114
+ };
115
+
116
+ type EndpointData = ProductData;
117
+
118
+ interface ProductData {
119
+ productId: string;
120
+ price: string;
121
+ description: string;
122
+ }
@@ -5,7 +5,7 @@
5
5
  "fmt.check": "prettier --check ."
6
6
  },
7
7
  "devDependencies": {
8
- "@builder.io/qwik-react": "0.0.7",
8
+ "@builder.io/qwik-react": "0.0.8",
9
9
  "@emotion/react": "11.9.3",
10
10
  "@emotion/server": "11.4.0",
11
11
  "@emotion/styled": "11.9.3",
@@ -3,7 +3,7 @@ import { renderToString } from '@builder.io/qwik-react';
3
3
  import { manifest } from '@qwik-client-manifest';
4
4
  import Root from './root';
5
5
 
6
- export function render(opts: RenderOptions) {
6
+ export default function (opts: RenderOptions) {
7
7
  return renderToString(<Root />, {
8
8
  manifest,
9
9
  ...opts,
@@ -1,52 +1,6 @@
1
- import { render } from './entry.ssr';
1
+ import render from './entry.ssr';
2
+ import { qwikCity } from '@builder.io/qwik-city/middleware/cloudflare-pages';
2
3
 
3
- /**
4
- * Cloudflare Pages Request Handler
5
- */
6
- export const onRequest: PagesFunction = async ({ request, next, waitUntil }) => {
7
- try {
8
- const url = new URL(request.url);
4
+ const qwikCityMiddleware = qwikCity(render);
9
5
 
10
- // Handle static assets
11
- if (/\.\w+$/.test(request.url)) {
12
- return next(request);
13
- }
14
-
15
- // Do not using caching during development
16
- const useCache = url.hostname !== 'localhost' && request.method === 'GET';
17
-
18
- // Early return from cache
19
- const cache = await caches.open('custom:qwik');
20
- if (useCache) {
21
- const cachedResponse = await cache.match(request);
22
- if (cachedResponse) {
23
- return cachedResponse;
24
- }
25
- }
26
-
27
- // Generate Qwik SSR HTML
28
- const result = await render({
29
- url: request.url,
30
- });
31
-
32
- // Create HTTP Response
33
- const response = new Response(result.html, {
34
- headers: {
35
- 'Content-Type': 'text/html; charset=utf-8',
36
- 'Cache-Control': useCache
37
- ? `max-age=60, s-maxage=10, stale-while-revalidate=604800, stale-if-error=604800`
38
- : `no-cache, max-age=0`,
39
- },
40
- });
41
-
42
- if (useCache) {
43
- waitUntil(cache.put(request, response.clone()));
44
- }
45
-
46
- // Return Qwik SSR response
47
- return response;
48
- } catch (e) {
49
- // 500 Error
50
- return new Response(String(e), { status: 500 });
51
- }
52
- };
6
+ export const onRequestGet = [qwikCityMiddleware];
@@ -2,7 +2,7 @@
2
2
  "description": "Express.js server.",
3
3
  "scripts": {
4
4
  "build.ssr": "vite build --ssr src/entry.express.tsx",
5
- "serve": "node server/entry.express.mjs"
5
+ "serve": "node server/entry.express"
6
6
  },
7
7
  "devDependencies": {
8
8
  "@types/express": "4.17.13",
@@ -1,19 +1,30 @@
1
1
  import express from 'express';
2
2
  import { fileURLToPath } from 'url';
3
3
  import { join } from 'path';
4
- import cityPlan from '@qwik-city-plan';
5
4
  import { qwikCity } from '@builder.io/qwik-city/middleware/express';
6
- import { render } from './entry.ssr';
5
+ import render from './entry.ssr';
7
6
 
7
+ // directories where the static assets are located
8
+ const distDir = join(fileURLToPath(import.meta.url), '..', '..', 'dist');
9
+ const buildDir = join(distDir, 'build');
10
+
11
+ // create the Qwik City express middleware
12
+ const { router, notFound } = qwikCity(render);
13
+
14
+ // create the express server
8
15
  const app = express();
9
16
 
10
- app.use(
11
- qwikCity(render, {
12
- ...cityPlan,
13
- staticDir: join(fileURLToPath(import.meta.url), '..', '..', 'dist'),
14
- })
15
- );
17
+ // use Qwik City's page and endpoint handler
18
+ app.use(router);
19
+
20
+ // static asset handlers
21
+ app.use(`/build`, express.static(buildDir, { immutable: true, maxAge: '1y', index: false }));
22
+ app.use(express.static(distDir, { index: false }));
23
+
24
+ // use Qwik City's 404 handler
25
+ app.use(notFound);
16
26
 
27
+ // start the express server
17
28
  app.listen(8080, () => {
18
29
  /* eslint-disable */
19
30
  console.log(`http://localhost:8080/`);
@@ -0,0 +1,6 @@
1
+ import render from './entry.ssr';
2
+ import { qwikCity } from '@builder.io/qwik-city/middleware/netlify-edge';
3
+
4
+ const qwikCityHandler = qwikCity(render);
5
+
6
+ export default qwikCityHandler;
@@ -1,17 +0,0 @@
1
- import { component$, Host, Slot } from '@builder.io/qwik';
2
-
3
- export default component$(() => {
4
- return (
5
- <Host>
6
- <section>
7
- <Slot />
8
- </section>
9
- <aside>
10
- <p>Account Help</p>
11
- <ul>
12
- <li>Forgot password</li>
13
- </ul>
14
- </aside>
15
- </Host>
16
- );
17
- });
@@ -1,25 +0,0 @@
1
- import { component$, Host } from '@builder.io/qwik';
2
- import type { DocumentHead } from '@builder.io/qwik-city';
3
-
4
- export default component$(() => {
5
- return (
6
- <Host>
7
- <h1>Sign In</h1>
8
- <form action="/api/on-sign-in" method="post">
9
- <label>
10
- <span>Username</span>
11
- <input name="username" type="text" />
12
- </label>
13
- <label>
14
- <span>Password</span>
15
- <input name="password" type="password" />
16
- </label>
17
- <button>Log In</button>
18
- </form>
19
- </Host>
20
- );
21
- });
22
-
23
- export const head: DocumentHead = {
24
- title: 'Sign In',
25
- };
@@ -1,29 +0,0 @@
1
- import { component$, Host } from '@builder.io/qwik';
2
- import type { DocumentHead } from '@builder.io/qwik-city';
3
-
4
- export default component$(() => {
5
- return (
6
- <Host>
7
- <h1>Sign Up</h1>
8
- <form>
9
- <label>
10
- <span>Username</span>
11
- <input type="text" />
12
- </label>
13
- <label>
14
- <span>Password</span>
15
- <input type="password" />
16
- </label>
17
- <label>
18
- <span>Re-entry Password</span>
19
- <input type="password" />
20
- </label>
21
- <button>Create Account</button>
22
- </form>
23
- </Host>
24
- );
25
- });
26
-
27
- export const head: DocumentHead = {
28
- title: 'Sign Up',
29
- };
@@ -1,23 +0,0 @@
1
- import { component$, Host, Slot, useStyles$ } from '@builder.io/qwik';
2
- import type { DocumentHead } from '@builder.io/qwik-city';
3
- import { Menu } from '../../../components/menu/menu';
4
- import styles from './docs.css?inline';
5
-
6
- export default component$(() => {
7
- useStyles$(styles);
8
-
9
- return (
10
- <Host class="docs">
11
- <Menu />
12
- <section class="docs-content">
13
- <Slot />
14
- </section>
15
- </Host>
16
- );
17
- });
18
-
19
- export const head: DocumentHead = ({ head }) => {
20
- return {
21
- title: `Docs: ${head.title}`,
22
- };
23
- };
@@ -1,32 +0,0 @@
1
- ---
2
- title: Welcome
3
- ---
4
-
5
- import { Counter } from '~/components/counter/counter';
6
-
7
- # Welcome
8
-
9
- Welcome to the fabulous Qwik City. QwikCity is our official kit to build amazing sites:
10
-
11
- - 🐎 Powered by Qwik. Zero hydration and instant interactivity.
12
- - 🗃 File based routing (like Nextjs)
13
- - 🌏 Deploy easily to the edge: Netlify, Cloudflare, Vercel, Deno...
14
- - 📖 Author content directly in Markdown or MDX. MDX brings the best of markdown and JSX, allowing you to render Qwik components directly in markdown, like this one:
15
-
16
- <Counter />
17
-
18
- ## Next steps
19
-
20
- Open your editor and check out the following:
21
-
22
- **The `src/routes` folder**
23
-
24
- This is where the main content lives. Adding folders and / or files (`.md`, `.mdx`, or `.tsx`) will automatically create new URLs. For example, code saved at `routes/dashboard/settings/index.tsx` will be accessible via the URL path `/dashboard/settings`.
25
-
26
- **The `src/routes/_layout` files and folders**
27
-
28
- These bring form to your content. Since different pages may need to be rendered by different layouts, QwikCity provides the ability to scope layouts to specific routes, while still allowing for easy reuse across different content. For any page without its own layout defined, the `src/routes/_layout.tsx` is used by default.
29
-
30
- **The `src/components` folder**
31
-
32
- QwikCity is still a normal Qwik app. Any custom component, design systems, or functionality should live here. Notice the `header`, `footer` and `content-nav` components. They are used by the `default` layout!